openapi: 3.0.3
info:
  title: Tigris Partner Integrations API reference
  description: |
    This API provides additional functionality for managing buckets, access keys, and organizations.

    ## OpenAPI specification
    This API follows the OpenAPI 3.0 specification, and the spec can be downloaded by clicking on the `Export` button in the top right corner.

    ## Authentication

    To authenticate with Tigris Object Store, you need to sign your requests with the signing key by following these steps:

    :::note
    Reach out to [help@tigrisdata.com](mailto:help@tigrisdata.com) to request a:
    - Provider ID
    - Signing Key
    :::

    ### 1. Generate current timestamp
    Set the `X-Tigris-Time` header to the current timestamp in milliseconds since epoch. Example: `1731703213870`
    ```
    X-Tigris-Time: 1731703213870
    ```

    ### 2. Generate a unique nonce
    Set the `X-Tigris-Nonce` header to a unique random string to identify the request and prevent replay attacks. Example: `f8d133cb-5a42-47b1-9ef2-874bb55bab72`
    ```
    X-Tigris-Nonce: f8d133cb-5a42-47b1-9ef2-874bb55bab72
    ```

    ### 3. Create a canonical request
    Concatenate the following details with a newline character in between:
    ```
    <HTTPMethod>\n
    <CanonicalURI>\n
    <Header:X-Tigris-Time>\n
    <Header:X-Tigris-Nonce>
    ```

    :::tip
    The `CanonicalURI` is the full request URL including the scheme, host, path, and query parameters.

    For example, for a `POST` request to `/provider/laravel/orgs/my-org/provision`, the `CanonicalURI` would be:
    ```
    https://mgmt.storage.dev/provider/your-provider-id/orgs/user-org-id/provision
    ```
    And for a `GET` request with query parameters:
    ```
    https://mgmt.storage.dev/provider/your-provider-id/orgs/?include_inactive=true
    ```
    :::



    ### 4. Generate request signature
    Calculate the HMAC-SHA256 of the canonical request using the shared secret as the signing key. Example:
    ```
    Signature = hex(sha256sign(canonical_request, "signing_key"))
    ```

    ### 5. Include the signature in the request
    Set the `X-Tigris-Signature` header to the generated signature.
    ```
    X-Tigris-Signature: <generated_signature>
    ```
  version: 0.0.1
servers:
  - url: https://mgmt.storage.dev
    description: Tigris production server
tags:
  - name: buckets
    description: Bucket management
    x-displayName: Buckets
  - name: snapshots
    description: Bucket snapshots
    x-displayName: Snapshots
  - name: billing
    description: Usage and billing
    x-displayName: Usage and Billing
  - name: iam
    description: Identity and Access Management
    x-displayName: IAM
  - name: organizations
    description: Organization management
    x-displayName: Organizations
  - name: account
    description: Provider account management
    x-displayName: Account
paths:
  /v1/providers/{provider_id}/orgs/{org_id}/provision:
    post:
      tags:
        - buckets
      summary: Provision a new bucket
      description: |
        Provisions a new bucket in the organization account and also creates the organization account if it doesn't exist. This is an
        idempotent operation, and calling it multiple times with the same parameters will not create duplicate buckets.

        Provisioning API responds with an access key and secret to access the newly provisioned bucket.
      operationId: Tigris_Provisioning
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProvisioningRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProvisioningResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
  /v1/providers/{provider_id}/orgs/{org_id}/buckets/{bucket_name}:
    delete:
      tags:
        - buckets
      summary: Delete a bucket
      description: |
        Deletes the bucket and all its contents. If the bucket is not empty, it will not be deleted unless the `force` query parameter is set to `true`.
      operationId: Tigris_DeleteBucket
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
        - name: force
          in: query
          required: false
          description: If set to true, deletes the bucket even if it's not empty
          schema:
            type: boolean
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteBucketResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    get:
      tags:
        - buckets
      summary: Get bucket details
      description: |
        Returns the details of the bucket including its size, object count, and other metadata.
      operationId: Tigris_GetBucket
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetBucketResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    put:
      tags:
        - buckets
      summary: Update bucket settings
      description: |
        Updates the bucket settings like public access, storage class, and object ACL.
      operationId: Tigris_UpdateBucket
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateBucketRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpdateBucketResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/buckets:
    get:
      tags:
        - buckets
      summary: List all buckets for an organization
      description: |
        Lists all the buckets provisioned in the organization account.
      operationId: Tigris_ListBuckets
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - name: limit
          in: query
          description:
            Maximum number of buckets to return. Defaults to 500, max 5000.
          schema:
            type: integer
        - name: continuation_token
          in: query
          description: Token from previous response to fetch next page
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListBucketsResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
  /v1/providers/{provider_id}/orgs/{org_id}/buckets/{bucket_name}/domain:
    post:
      tags:
        - buckets
      summary: Attach a custom domain to a bucket
      description: |
        Sets a custom domain for a bucket. If the domain is already set, it will be replaced.

        :::note
        The custom domain must have a CNAME record that points to the bucket URL.
        :::

        ##### Example:
        If your bucket is `my-bucket` and you want to use `images.example.com`,
        create a CNAME record pointing `images.example.com` to `my-bucket.t3.storage.dev`.

        After setting the custom domain, objects will be accessible via:
        - `https://images.example.com/object.jpg`
        - `https://my-bucket.t3.storage.dev/object.jpg` (original URL still works)

      operationId: Tigris_SetCustomDomain
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SetCustomDomainRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SetCustomDomainResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    delete:
      tags:
        - buckets
      summary: Remove custom domain from bucket
      description: |
        Removes the custom domain from a bucket. After removal, the bucket will only be accessible via its default Tigris URL.
        The CNAME DNS record can be safely deleted after the custom domain is removed.
      operationId: Tigris_DeleteCustomDomain
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteCustomDomainResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    get:
      tags:
        - buckets
      summary: Get custom domain settings for a bucket
      description: |
        Returns the currently configured custom domain for the bucket, or an empty
        object if no custom domain is set.
      operationId: Tigris_GetCustomDomain
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetCustomDomainResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/buckets/{bucket_name}/lifecycle:
    put:
      tags:
        - buckets
      summary: Set lifecycle rules for a bucket
      description: |
        Sets lifecycle rules for automatic object transitions and expiration. If lifecycle rules already exist,
        they will be completely replaced with the new configuration.

        ## Lifecycle Rules Overview

        Lifecycle rules allow you to automatically:
        - **Transition** objects to cheaper storage classes after a specified time
        - **Expire** (permanently delete) objects after a specified time

        ## Examples

        ### Archive old logs and delete after 1 year
        ```json
        {
          "rules": [
            {
              "id": "archive-and-cleanup-logs",
              "enabled": true,
              "transitions": [
                { "days": 90, "storage_class": "GLACIER" }
              ],
              "expiration": { "days": 365 }
            }
          ]
        }
        ```
      operationId: Tigris_SetLifecycleRules
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SetLifecycleRulesRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SetLifecycleRulesResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    get:
      tags:
        - buckets
      summary: Get lifecycle rules for a bucket
      description: |
        Returns the currently configured lifecycle rules for the bucket. Returns an empty rules array
        if no lifecycle rules are configured.
      operationId: Tigris_GetLifecycleRules
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetLifecycleRulesResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    delete:
      tags:
        - buckets
      summary: Remove all lifecycle rules from a bucket
      description: |
        Removes all lifecycle rules from the bucket. Objects will no longer be automatically
        transitioned or expired. This is equivalent to sending a PUT request with an empty rules array.
      operationId: Tigris_DeleteLifecycleRules
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteLifecycleRulesResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/buckets/{bucket_name}/snapshots:
    post:
      tags:
        - snapshots
      summary: Take a snapshot of the bucket
      description: |
        Takes a snapshot of the bucket's current state. The bucket must have
        snapshots enabled. See https://www.tigrisdata.com/docs/snapshots/.
      operationId: Tigris_CreateSnapshot
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateSnapshotRequest"
        required: false
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateSnapshotResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    get:
      tags:
        - snapshots
      summary: List snapshots for a bucket
      description: |
        Lists snapshots for the bucket, ordered by creation time. See
        https://www.tigrisdata.com/docs/snapshots/.
      operationId: Tigris_ListSnapshots
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListSnapshotsResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/buckets/{bucket_name}/snapshots/{version}:
    get:
      tags:
        - snapshots
      summary: Get snapshot details
      description: |
        Returns snapshot metadata. See https://www.tigrisdata.com/docs/snapshots/.
      operationId: Tigris_GetSnapshot
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
        - $ref: "#/components/parameters/version"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetSnapshotResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    delete:
      tags:
        - snapshots
      summary: Delete a snapshot
      description: |
        Deletes the snapshot. See https://www.tigrisdata.com/docs/snapshots/.
      operationId: Tigris_DeleteSnapshot
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/bucket_name"
        - $ref: "#/components/parameters/version"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteSnapshotResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/key/get:
    post:
      tags:
        - iam
      summary: Get Access Key details
      description: |
        Returns detailed information about an access key, including attached IAM policies.
      operationId: Tigris_GetAccessKey
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/GetAccessKeyRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetAccessKeyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/key/rotate:
    post:
      tags:
        - iam
      summary: Rotate Access Key secret
      description: |
        Rotates the access key secret for a user. The old secret will be invalidated, and the new secret will be returned in the response.
      operationId: Tigris_RotateAccessKey
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RotateAccessKeyRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RotateAccessKeyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
  /v1/providers/{provider_id}/orgs/{org_id}/key:
    post:
      tags:
        - iam
      summary: Create a new Access Key
      description: |
        Creates a new access key for a user. The access key ID and secret will be returned in the response.
      operationId: Tigris_CreateAccessKey
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateAccessKeyRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateAccessKeyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    put:
      tags:
        - iam
      summary: Update an Access Key
      description: |
        Updates the access key details like user role and bucket access permissions.
      operationId: Tigris_UpdateAccessKey
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateAccessKeyRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpdateAccessKeyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    delete:
      tags:
        - iam
      summary: Delete an Access Key
      description: |
        Deletes an access key for a user. The access key will be invalidated and can't be used for further requests.
      operationId: Tigris_DeleteAccessKey
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeleteAccessKeyRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteAccessKeyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/policies:
    post:
      tags:
        - iam
      summary: Create an IAM policy
      description: |
        Creates a new IAM policy with the given name and document.
        Returns 409 if a policy with the same name already exists — use
        [Update Policy](#tag/iam/operation/Tigris_UpdatePolicy) to modify existing policies.

        The policy document follows the [AWS IAM policy syntax](https://www.tigrisdata.com/docs/iam/policies/).

        After creating a policy, attach it to an access key using the
        [Update Access Key](#tag/iam/operation/Tigris_UpdateAccessKey) endpoint
        with the `add_policies` field.

        ##### Example: Read-write access to a prefix

        ```json
        {
          "name": "uploads-readwrite",
          "document": {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
                "Resource": ["arn:aws:s3:::my-bucket/uploads/*"]
              },
              {
                "Effect": "Allow",
                "Action": ["s3:ListBucket"],
                "Resource": ["arn:aws:s3:::my-bucket"]
              }
            ]
          }
        }
        ```
      operationId: Tigris_CreatePolicy
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreatePolicyRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PolicyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    get:
      tags:
        - iam
      summary: List IAM policies
      description: |
        Lists all IAM policies in the organization.
      operationId: Tigris_ListPolicies
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - name: limit
          in: query
          description:
            Maximum number of policies to return. Defaults to 100, max 1000.
          schema:
            type: integer
        - name: continuation_token
          in: query
          description: Token from previous response to fetch next page
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListPoliciesResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/policies/{policy_name}:
    get:
      tags:
        - iam
      summary: Get an IAM policy
      description: |
        Returns the policy details including its document.
      operationId: Tigris_GetPolicy
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/policy_name"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PolicyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    put:
      tags:
        - iam
      summary: Update an IAM policy
      description: |
        Updates the document and/or description of an existing IAM policy.
        Changes take effect immediately for all access keys the policy is attached to.

        The policy document follows the [AWS IAM policy syntax](https://www.tigrisdata.com/docs/iam/policies/).
        For supported actions, see the [full list of supported actions](https://www.tigrisdata.com/docs/iam/policies/supported-actions).
      operationId: Tigris_UpdatePolicy
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/policy_name"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdatePolicyRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PolicyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    delete:
      tags:
        - iam
      summary: Delete an IAM policy
      description: |
        Deletes an IAM policy. The policy is automatically detached from all access keys before deletion.
      operationId: Tigris_DeletePolicy
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - $ref: "#/components/parameters/policy_name"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeletePolicyResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/keys:
    post:
      tags:
        - iam
      summary: List all Access Keys
      description: |
        Lists all the access keys for a user in the organization account.
      operationId: Tigris_ListAccessKeys
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ListAccessKeysRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListAccessKeysResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/account/invoices/{month}:
    get:
      tags:
        - account
      summary: Get provider account invoice for a month
      description: |
        Returns the provider's consolidated invoice for the specified month. This invoice
        aggregates charges across all member organizations under the provider.
      operationId: Tigris_GetAccountInvoice
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - name: month
          in: path
          required: true
          description: Month in format YYYY-MM
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetInvoiceResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}/invoices/{month}:
    get:
      tags:
        - billing
      summary: Get invoice for a month
      description: |
        Returns the invoice for the specified month. The invoice will include all the charges for the month.
      operationId: Tigris_GetInvoice
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - name: month
          in: path
          required: true
          description: Month in format YYYY-MM
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetInvoiceResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
  /v1/providers/{provider_id}/orgs/{org_id}/usage:
    get:
      tags:
        - billing
      summary: Get usage details for an organization
      description: |
        Returns the usage details for the specified period. The usage details will include all the billable metrics for the period.
      operationId: Tigris_GetUsage
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
        - name: starting_on
          in: query
          required: true
          description:
            RFC3339 formatted UTC midnight timestamp for starting period
          example: "2021-09-01T00:00:00Z"
          schema:
            type: string
        - name: ending_before
          in: query
          required: true
          description:
            RFC3339 formatted UTC midnight timestamp for ending period
          example: "2021-09-01T00:00:00Z"
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetUsageResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs/{org_id}:
    get:
      tags:
        - organizations
      summary: Get organization
      operationId: Tigris_GetOrganization
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetOrganizationResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    put:
      tags:
        - organizations
      summary: Update organization details
      description: |
        Updates the organization details like active status.
      operationId: Tigris_UpdateOrganization
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateOrganizationRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpdateOrganizationResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
    post:
      tags:
        - organizations
      summary: Create a new organization
      description: |
        Creates a new organization account
      operationId: Tigris_CreateOrganization
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - $ref: "#/components/parameters/org_id"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateOrganizationRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateOrganizationResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"

  /v1/providers/{provider_id}/orgs:
    get:
      tags:
        - organizations
      summary: List all organizations
      operationId: Tigris_ListOrganizations
      parameters:
        - $ref: "#/components/parameters/provider_id"
        - name: include_inactive
          in: query
          description:
            If set to true, includes inactive organizations in the response.
            Defaults to false.
          schema:
            type: boolean
        - name: limit
          in: query
          description:
            Maximum number of organizations to return. Defaults to 1000, max
            5000.
          schema:
            type: integer
        - name: continuation_token
          in: query
          description: Token from previous response to fetch next page
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListOrganizationsResponse"
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenericError"
components:
  schemas:
    ProvisioningRequest:
      type: object
      additionalProperties: false
      required:
        - bucket_name
        - org_name
        - user_id
      properties:
        bucket_name:
          type: string
          description: Name of the bucket to be provisioned
        org_name:
          type: string
          description:
            Name of the organization where the bucket should be provisioned
        org_quota:
          $ref: "#/components/schemas/OrgQuota"
        user_id:
          type: string
          description: ID of the user who is requesting the bucket
        bucket_options:
          $ref: "#/components/schemas/BucketOptions"
        user_role:
          $ref: "#/components/schemas/OrgMembership"
        fork_of:
          type: string
          description: |
            Create this bucket as a fork of the named source bucket. The source
            must belong to the same organization, and the acting user must
            either have `user_role=Admin` or own the source bucket. See
            https://www.tigrisdata.com/docs/forks/.
        source_snapshot:
          type: string
          description: |
            Fork from a specific snapshot of the source bucket. Accepts a snapshot
            version string or any UNIX nanosecond-precision timestamp (e.g.
            `1765889000501544464`). Requires `fork_of`. See
            https://www.tigrisdata.com/docs/forks/.
        access_key_scope:
          $ref: "#/components/schemas/AccessKeyScope"
    OrgMembership:
      type: string
      description: |
        Role of the user in the organization. Controls what the user can do
        through the Partner API management endpoints.

        - `Admin`: Full org access. Can list and manage all access keys in the
          org, update org settings, and manage users. ListAccessKeys returns
          all keys in the org.
        - `Member`: Standard access. Can only manage their own access keys.
          ListAccessKeys returns only keys owned by this user.

        If omitted, defaults to `Member` behavior.
      enum: [Admin, Member]
    OrgQuota:
      type: object
      required:
        - limit_bytes
      properties:
        limit_bytes:
          type: integer
          format: int64
          description:
            The number of bytes that the organization is allowed to store across
            all of its buckets. Zero means no limit.
    BucketOptions:
      type: object
      properties:
        public:
          type: boolean
          description:
            If set to true, the bucket will be publicly accessible. Default is
            false.
        enable_public_list_objects:
          type: boolean
          description:
            If set to true, anonymous users can list objects in public buckets.
            Default is false for new buckets. Only applicable to public buckets.
        storage_class:
          $ref: "#/components/schemas/StorageClass"
        regions:
          $ref: "#/components/schemas/Regions"
        enable_object_acl:
          type: boolean
          description:
            If set to true, per object ACL will be enabled. Default is false.
        enable_snapshots:
          type: boolean
          description: |
            Enable snapshots on the bucket at creation. Snapshots can also be
            enabled or disabled on an existing bucket from the Storage Settings
            page in the Tigris Dashboard. See https://www.tigrisdata.com/docs/snapshots/.
        object_notifications:
          $ref: "#/components/schemas/ObjectNotifications"
        lifecycle_rules:
          $ref: "#/components/schemas/LifecycleRules"
    ObjectNotifications:
      type: object
      description: |
        Configuration for object event notifications via webhook. Receive HTTP callbacks when objects are created, updated, or deleted in your bucket.

        **Update behavior (partial updates supported):**
        - **Omit field entirely**: Keeps existing settings unchanged
        - **Include only `enabled`**: Toggles notifications on/off while preserving all other config
        - **Include any field**: Updates specified fields, preserves others (auth not re-required)
        - **Remove completely**: Send `{"enabled": false}` with no other fields

        **Common operations:**
        ```json
        // Enable notifications (preserves webhook, filter, auth)
        {"enabled": true}

        // Disable temporarily (keeps all config for later)
        {"enabled": false, "webhook": "https://..."}

        // Update webhook only (preserves auth, filter)
        {"webhook": "https://new-endpoint.com"}

        // Change auth type (replaces entire auth object)
        {"auth": {"token": "new-token"}}

        // Remove all notifications
        {"enabled": false}
        ```

        **Note:** Auth credentials are masked in responses. You don't need to re-send them when updating other fields.
      required:
        - enabled
      properties:
        enabled:
          type: boolean
          description:
            Enable or disable notifications (webhook required when true)
        webhook:
          type: string
          format: uri
          description: HTTPS endpoint to receive notification events
          example: "https://webhook.example.com/tigris-events"
        filter:
          type: string
          description:
            SQL WHERE clause to filter which objects trigger notifications
            (e.g., size comparisons)
          example: "size > 1000000"
        auth:
          $ref: "#/components/schemas/ObjectNotificationAuth"
    ObjectNotificationAuth:
      type: object
      description: Authentication credentials for webhook endpoint
      properties:
        basic_user:
          type: string
          description: Basic auth username
        basic_pass:
          type: string
          description: Basic auth password
          format: password
        token:
          type: string
          description: Bearer token for authorization
          format: password
    LifecycleRules:
      type: object
      description: |
        Lifecycle rules to automatically transition objects to different storage classes or permanently delete (expire) them.

        - **Transitions**: Automatically move objects to a cheaper storage class after a specified time or on a specific date.
          Use this for data that is accessed less frequently over time (e.g., logs, backups, archives).
        - **Expiration**: Automatically and permanently delete objects after a specified time or on a specific date.
          Use this for temporary data, logs with retention policies, or any data that should be cleaned up automatically.

        ## Example: Archive old logs and delete after 1 year

        ```json
        {
          "rules": [
            {
              "id": "archive-and-cleanup-logs",
              "enabled": true,
              "transitions": [
                { "days": 90, "storage_class": "GLACIER" }
              ],
              "expiration": { "days": 365 }
            }
          ]
        }
        ```

        This rule transitions objects to `GLACIER` after 90 days, and permanently deletes them after 365 days.

        ## Update Behavior (Partial Updates Supported)

        - **Omit field entirely**: Keeps existing lifecycle rules unchanged
        - **Include empty rules array `[]`**: Removes all lifecycle rules
        - **Include rules**: Replaces all lifecycle rules with the provided set

        Note: When updating rules, you must provide the complete rule configuration. To preserve existing rules while making changes, first retrieve the current bucket configuration, modify the desired fields, and submit the complete updated rules.
      properties:
        rules:
          type: array
          items:
            $ref: "#/components/schemas/LifecycleRule"
    LifecycleRule:
      type: object
      required:
        - id
        - enabled
      properties:
        id:
          type: string
          description: |
            Unique identifier for the rule (max 255 chars). Use a descriptive name like `archive-old-logs` or `expire-temp-uploads`.
          maxLength: 255
        enabled:
          type: boolean
          description: |
            Whether the rule is currently active. Set to `false` to temporarily disable a rule without deleting it.
            When disabled, objects will not be transitioned or expired by this rule.
        expiration:
          $ref: "#/components/schemas/LifecycleExpiration"
        transitions:
          type: array
          description: |
            List of storage class transitions. Objects will transition through each defined step.
            Transitions must be in chronological order (earlier days/dates first).
          items:
            $ref: "#/components/schemas/LifecycleTransition"
        filter:
          $ref: "#/components/schemas/LifecycleRuleFilter"
    LifecycleRuleFilter:
      type: object
      description: |
        Optional scope for a lifecycle rule. When unset, the rule applies to every object in the bucket.
      properties:
        prefix:
          type: string
          description: |
            Only apply this rule to objects whose keys start with the given prefix.
            For example, `logs/` scopes the rule to objects under that prefix.
    LifecycleExpiration:
      type: object
      description: |
        Configuration for automatic object deletion (expiration).

        When the expiration condition is met, objects matching this rule are **permanently deleted**.

        ## Specify ONE Condition (Not Both)

        - `days`: Delete objects N days after their creation date
        - `date`: Delete all matching objects on a specific date
        ```
      properties:
        days:
          type: integer
          description: |
            Number of days after object creation when the object will be deleted.
            The deletion happens at midnight UTC on the calculated expiration date.

            Example: If `days: 30` and an object was created on Dec 1, it expires on Dec 31.
        date:
          type: string
          format: date-time
          description: |
            Specific date (at midnight UTC) when all matching objects will be deleted, regardless of when they were created.
            Use this for one-time cleanup operations or compliance deadlines.

            Must be a future date in RFC3339 format with midnight UTC time.
          example: "2025-01-01T00:00:00Z"
    LifecycleTransition:
      type: object
      required:
        - storage_class
      description: |
        Configuration for transitioning objects to a different storage class.

        When the transition condition is met, objects are moved to the specified storage class.
        This is useful for reducing storage costs by moving infrequently accessed data to cheaper tiers.

        ## Specify ONE Condition (Not Both)

        - `days`: Transition objects N days after their creation date
        - `date`: Transition all matching objects on a specific date
        ```
      properties:
        days:
          type: integer
          description: |
            Number of days after object creation when the transition occurs.
            The transition happens at midnight UTC on the calculated date.

            Example: If `days: 60` and an object was created on Jan 1, it transitions on Mar 2.
        date:
          type: string
          format: date-time
          description: |
            Specific date (at midnight UTC) when all matching objects will be transitioned, regardless of when they were created.
            Use this for planned migrations or cost optimization deadlines.

            Must be a future date in RFC3339 format with midnight UTC time.
          example: "2025-06-01T00:00:00Z"
        storage_class:
          $ref: "#/components/schemas/StorageClass"
    ProvisioningResponse:
      type: object
    UpdateBucketRequest:
      type: object
      additionalProperties: false
      properties:
        public:
          type: boolean
          description:
            If set to true, the bucket will be publicly accessible. Default is
            false.
        enable_object_acl:
          type: boolean
          description:
            If set to true, per object ACL will be enabled. Default is false.
        enable_public_list_objects:
          type: boolean
          description:
            If set to true, anonymous users can list objects in public buckets.
            Only applicable to public buckets.
        object_notifications:
          $ref: "#/components/schemas/ObjectNotifications"
        regions:
          $ref: "#/components/schemas/Regions"
    UpdateBucketResponse:
      type: object
    DeleteBucketResponse:
      type: object
    GetBucketResponse:
      type: object
      properties:
        bucket:
          $ref: "#/components/schemas/BucketInfo"
    ListBucketsResponse:
      type: object
      required:
        - buckets
      properties:
        buckets:
          type: array
          items:
            $ref: "#/components/schemas/BucketInfo"
        next_continuation_token:
          type: string
          description:
            Pass as continuation_token for next page. Empty if no more results.
    GetInvoiceResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/Invoice"
    BucketWebsiteSettings:
      type: object
      additionalProperties: false
      properties:
        domain_name:
          type: string
          example: "images.example.com"
          description: |
            Custom domain name for the bucket. Must be a valid fully-qualified domain name (FQDN) and 
            have a CNAME record pointing to the bucket URL.
    SetCustomDomainRequest:
      type: object
      additionalProperties: false
      required:
        - website
      properties:
        website:
          $ref: "#/components/schemas/BucketWebsiteSettings"
    SetCustomDomainResponse:
      type: object
    DeleteCustomDomainResponse:
      type: object
    GetCustomDomainResponse:
      type: object
      additionalProperties: false
      required:
        - website
      properties:
        website:
          $ref: "#/components/schemas/BucketWebsiteSettings"
    SetLifecycleRulesRequest:
      type: object
      additionalProperties: false
      required:
        - rules
      properties:
        rules:
          type: array
          description: |
            List of lifecycle rules to apply to the bucket.
          items:
            $ref: "#/components/schemas/LifecycleRule"
    SetLifecycleRulesResponse:
      type: object
    GetLifecycleRulesResponse:
      type: object
      additionalProperties: false
      required:
        - rules
      properties:
        rules:
          type: array
          description: |
            Currently configured lifecycle rules for the bucket. Empty array if no rules are configured.
          items:
            $ref: "#/components/schemas/LifecycleRule"
    DeleteLifecycleRulesResponse:
      type: object
    Invoice:
      type: object
      properties:
        org_id:
          type: string
          description: Organization ID
        plan_name:
          type: string
          description: Name of the plan
        charges:
          type: array
          description: List of charges in the invoice
          items:
            $ref: "#/components/schemas/InvoiceCharge"
        subtotal:
          type: number
          description: Amount before any credits/discounts/minimum commitments
          format: double
        total:
          type: number
          description: Total payable amount
          format: double
        created_at:
          type: string
          format: date-time
          description: RFC3339 timestamp when this invoice was generated
          example: "2021-09-01T12:00:00Z"
        last_modified:
          type: string
          format: date-time
          description: RFC3339 timestamp when this invoice was last modified
          example: "2021-09-01T12:00:00Z"
        starting_on:
          type: string
          format: date-time
          description:
            RFC3339 starting time for usage period during which items were added
            to this invoice
          example: "2021-09-01T12:00:00Z"
        ending_before:
          type: string
          format: date-time
          description:
            RFC3339 ending time for usage period during which items were added
            to this invoice
          example: "2021-09-01T12:00:00Z"
        status:
          type: string
          description: |
            * `DRAFT` - Invoice can be modified as the billing period progresses
            * `FINALIZED` - Invoice is locked and can't be modified
            * `PAID` - Payment has been collected
            * `PAST_DUE` - Payment is overdue
          enum:
            - DRAFT
            - FINALIZED
            - PAID
            - PAST_DUE
        memo:
          type: string
          description:
            Human-readable description explaining the billing context for this
            invoice
        minimum_commit:
          type: number
          description: Volume commitment amount applied to the invoice
          format: double
        credits:
          type: number
          description: Credits applied to the invoice
          format: double
      required:
        - org_id
        - charges
        - plan_name
        - subtotal
        - total
        - created_at
        - last_modified
        - starting_on
        - ending_before
        - status
    InvoiceCharge:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the charge
        name:
          type: string
          description: User friendly name of the charge
        quantity:
          type: number
          description: Number of units consumed
          format: double
        unit:
          type: string
          description: Consumption unit
        total:
          type: number
          description: Total cost for the charge
          format: double
        tiers:
          type: array
          items:
            $ref: "#/components/schemas/ChargeTier"
        charged_quantity:
          type: number
          description: Actual number of units charged for
          format: double
      required:
        - id
        - name
        - quantity
        - unit
        - total
        - tiers
        - charged_quantity
    ChargeTier:
      type: object
      properties:
        name:
          type: string
        quantity:
          type: number
          description: Number of units consumed
          format: double
        starting_after:
          type: number
          description: Starting point when this tier is applicable
          format: double
        price:
          type: number
          description: Rate per unit
          format: double
        subtotal:
          type: number
          description: Total cost for the tier
          format: double
      required:
        - name
        - quantity
        - starting_after
        - price
        - subtotal
    SnapshotInfo:
      type: object
      description: |
        A point-in-time snapshot of a bucket. See
        https://www.tigrisdata.com/docs/snapshots/.
      properties:
        version:
          type: string
          description: Snapshot version (UNIX nanosecond-precision timestamp).
        created_at:
          type: string
          format: date-time
        bucket:
          type: string
          description: Name of the bucket this snapshot belongs to.
        description:
          type: string
          description: Optional name or description.
    CreateSnapshotRequest:
      type: object
      additionalProperties: false
      properties:
        description:
          type: string
          description: Optional name or description for the snapshot.
    CreateSnapshotResponse:
      type: object
      properties:
        snapshot:
          $ref: "#/components/schemas/SnapshotInfo"
    ListSnapshotsResponse:
      type: object
      properties:
        snapshots:
          type: array
          items:
            $ref: "#/components/schemas/SnapshotInfo"
    GetSnapshotResponse:
      type: object
      properties:
        snapshot:
          $ref: "#/components/schemas/SnapshotInfo"
    DeleteSnapshotResponse:
      type: object
    ForkInfo:
      type: object
      description: |
        Fork metadata for a bucket that was created as a fork, or that has forks
        depending on it. See https://www.tigrisdata.com/docs/forks/.
      properties:
        parent_bucket:
          type: string
          description:
            Name of the immediate source bucket this bucket was forked from.
        snapshot:
          type: string
          description:
            Snapshot version this bucket was forked from (UNIX
            nanosecond-precision timestamp).
        has_children:
          type: boolean
          description:
            True if one or more buckets have been forked from this bucket.
    BucketInfo:
      type: object
      properties:
        name:
          type: string
          description: Name of the bucket
        created_at:
          type: string
          format: date-time
          description: RFC3339 formatted timestamp of bucket creation
          example: "2021-09-01T12:00:00Z"
        size:
          type: integer
          format: int64
          description: Estimated size of the bucket in bytes
        object_count:
          type: integer
          format: int64
          description: Estimated number of objects in the bucket
        public:
          type: boolean
          description: If set to true, the bucket is publicly accessible
        storage_class:
          $ref: "#/components/schemas/StorageClass"
        regions:
          $ref: "#/components/schemas/Regions"
        object_acl_enabled:
          type: boolean
          description: If set to true, per object ACL is enabled
        public_list_objects_enabled:
          type: boolean
          description:
            If true, anonymous users can list objects in this public bucket
        snapshots_enabled:
          type: boolean
          description: True if snapshots are enabled on the bucket.
        fork_info:
          $ref: "#/components/schemas/ForkInfo"
        website:
          $ref: "#/components/schemas/BucketWebsiteSettings"
        object_notifications:
          $ref: "#/components/schemas/ObjectNotifications"
        lifecycle_rules:
          $ref: "#/components/schemas/LifecycleRules"
    GetUsageResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/Usage"
    Usage:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the usage metric
        name:
          type: string
          description: Display name for customer invoice
        description:
          type: string
          description: Human readable description of the usage metric
        unit:
          type: string
          description: Unit of measurement
        values:
          type: array
          items:
            $ref: "#/components/schemas/UsageValue"
      required:
        - id
        - name
        - description
        - unit
        - values
    UsageValue:
      type: object
      properties:
        starting_on:
          type: string
          format: date-time
          description: RFC3339 formatted UTC timestamp for starting period
          example: "2021-09-01T01:00:00Z"
        ending_before:
          type: string
          format: date-time
          description: RFC3339 formatted UTC timestamp for ending period
          example: "2021-09-01T02:00:00Z"
        value:
          type: number
          description: Usage value for the period
          format: double
      required:
        - starting_on
        - ending_before
        - value
    AccessKeyScope:
      type: string
      enum: [standard, no_default_allow]
      description: |
        Controls whether the key receives the implicit default-allowed operations
        (such as create bucket or list buckets) on top of what its policies and
        bucket roles grant.

        - `standard` (default): grants the default-allowed operations.
        - `no_default_allow`: denies them, so the key can do only what its policies
          and bucket roles explicitly allow.
    CreateAccessKeyRequest:
      type: object
      additionalProperties: false
      required:
        - user_id
      properties:
        name:
          type: string
          description: Name of the access key
        user_id:
          type: string
          description: ID of the user for whom the access key is being created
        user_role:
          $ref: "#/components/schemas/OrgMembership"
        buckets_roles:
          type: array
          items:
            $ref: "#/components/schemas/BucketAccess"
        attach_policies:
          type: array
          items:
            type: string
          description: |
            Names of existing IAM policies to attach to this access key.
            All policies must already exist — if any policy name is invalid, the
            request fails and no key is created.
        create_policies:
          type: array
          items:
            $ref: "#/components/schemas/CreatePolicyRequest"
          description: |
            New IAM policies to create and attach to this access key.
            Each policy is created first, then attached atomically. If a policy
            with the same name already exists the request fails — use
            attach_policies to reuse an existing policy. If policy document
            validation fails, no key is created.
        access_key_scope:
          $ref: "#/components/schemas/AccessKeyScope"
    CreateAccessKeyResponse:
      type: object
      required:
        - id
        - secret_key
      properties:
        id:
          type: string
          description: Access key ID
        secret_key:
          type: string
          description: Access secret
        name:
          type: string
          description: Name of the access key
    BucketAccess:
      type: object
      description: |
        Access permissions for a bucket. The role assigned to the access key defines the permissions (read, write, admin) for the associated bucket.
      required:
        - bucket_name
        - role
      properties:
        bucket_name:
          type: string
          description: Name of the bucket
        role:
          type: string
          description: |
            The role defines the permissions for the associated bucket:

            - `ReadOnly`: Read-only access to the bucket. Permits read
              operations like GetObject, HeadObject, ListObjects.
            - `Editor`: Read and write access to the bucket. Includes
              everything in ReadOnly, plus PutObject, DeleteObject, and bucket
              configuration operations.
            - `Admin`: Full access to all buckets in the org, bypasses all
              permission checks. When used with `bucket_name: "*"`, the access
              key is treated as a full org admin. The value of `bucket_name`
              should always be `*` when using this role.

              Example:
              ```
              {
                "bucket_name": "*",
                "role": "Admin"
              }
              ```
          enum: [ReadOnly, Editor, Admin]
    UpdateAccessKeyRequest:
      type: object
      additionalProperties: false
      required:
        - user_id
        - id
      properties:
        user_id:
          type: string
          description: ID of the user for whom the access key is being updated
        id:
          type: string
          description: Access key ID
        user_role:
          $ref: "#/components/schemas/OrgMembership"
        buckets_roles:
          type: array
          items:
            $ref: "#/components/schemas/BucketAccess"
        add_policies:
          type: array
          items:
            type: string
          description: |
            Names of IAM policies to attach to this access key. Policies already attached are ignored.
            Can be combined with `remove_policies` in the same request — removals are applied first.
        remove_policies:
          type: array
          items:
            type: string
          description: |
            Names of IAM policies to detach from this access key. Policies not currently attached are ignored.
        access_key_scope:
          allOf:
            - $ref: "#/components/schemas/AccessKeyScope"
          description: |
            Omitting this field leaves the key's current scope unchanged.
    UpdateAccessKeyResponse:
      type: object
    RotateAccessKeyRequest:
      type: object
      additionalProperties: false
      required:
        - user_id
        - id
      properties:
        user_id:
          type: string
          description: ID of the user for whom the access key is being updated
        id:
          type: string
          description: Access key ID
        user_role:
          $ref: "#/components/schemas/OrgMembership"
    RotateAccessKeyResponse:
      type: object
      properties:
        new_secret:
          type: string
          description: Rotated access key secret
    ListAccessKeysRequest:
      type: object
      additionalProperties: false
      required:
        - user_id
      properties:
        user_id:
          type: string
          description: ID of the user for whom the access keys are being listed
        user_role:
          $ref: "#/components/schemas/OrgMembership"
        limit:
          type: integer
          description:
            Maximum number of keys to return. Defaults to 100, max 1000.
        continuation_token:
          type: string
          description: Token from previous response to fetch next page.
        key_id_prefix:
          type: string
          description: List only keys with specific ID prefix
    ListAccessKeysResponse:
      type: object
      required:
        - keys
      properties:
        keys:
          type: array
          items:
            $ref: "#/components/schemas/AccessKeyInfo"
        next_continuation_token:
          type: string
          description:
            Pass as continuation_token for next page. Empty if no more results.
    AccessKeyInfo:
      type: object
      required:
        - id
        - status
        - name
      properties:
        id:
          type: string
          description: Access key ID
        name:
          type: string
          description: Name of the access key
        status:
          type: string
          description: Status of the access key.
          enum: [Active, Inactive]
        buckets_roles:
          type: array
          items:
            $ref: "#/components/schemas/BucketAccess"
    DeleteAccessKeyRequest:
      type: object
      additionalProperties: false
      required:
        - user_id
        - id
      properties:
        id:
          type: string
          description: Access key ID
        user_id:
          type: string
          description: ID of the user for whom the access key is being deleted
        user_role:
          $ref: "#/components/schemas/OrgMembership"
    DeleteAccessKeyResponse:
      type: object
    CreateOrganizationRequest:
      type: object
      additionalProperties: false
      required:
        - org_name
        - user_id
      properties:
        org_name:
          type: string
          description: Name of the organization to be created
        user_id:
          type: string
          description: ID of the user who is creating the organization
        org_quota:
          $ref: "#/components/schemas/OrgQuota"
    CreateOrganizationResponse:
      type: object
    UpdateOrganizationRequest:
      type: object
      additionalProperties: false
      required:
        - user_id
      properties:
        user_id:
          type: string
          description: ID of the user who is updating the organization
        user_role:
          $ref: "#/components/schemas/OrgMembership"
        active:
          type: boolean
          description:
            If set to false, the organization will be deactivated and no new
            resources can be provisioned. Existing resources will be
            inaccessible.
        org_quota:
          $ref: "#/components/schemas/OrgQuota"
    UpdateOrganizationResponse:
      type: object
    ListOrganizationsResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/OrgInfo"
        next_continuation_token:
          type: string
          description:
            Pass as continuation_token for next page. Empty if no more results.
    GetOrganizationResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/OrgInfo"
    OrgInfo:
      type: object
      required:
        - id
      properties:
        id:
          type: string
          description: Organization ID
        name:
          type: string
          description: Name of the organization
        active:
          type: boolean
          description: If set to false, the organization is deactivated
        quota:
          $ref: "#/components/schemas/OrgQuota"
    StorageClass:
      type: string
      description: Storage class for the bucket. Default is `STANDARD`.
      enum: [STANDARD, STANDARD_IA, GLACIER, GLACIER_IR]
    Regions:
      type: string
      description: |
        Restricts the regions where bucket data is stored. Default is empty,
        which means no restrictions (global distribution).

        Accepted values:
        - Specific region(s): "iad", "sjc", "iad,sjc,lhr" (comma-separated)
        - No restrictions (global distribution): "global"

        If you want to remove existing region restrictions, you can set the value to "global".

        See https://www.tigrisdata.com/docs/objects/object_regions/ for more details.
    GetAccessKeyRequest:
      type: object
      additionalProperties: false
      required:
        - user_id
        - id
      properties:
        user_id:
          type: string
          description: ID of the user who owns the access key
        id:
          type: string
          description: Access key ID
        user_role:
          $ref: "#/components/schemas/OrgMembership"
    GetAccessKeyResponse:
      allOf:
        - $ref: "#/components/schemas/AccessKeyInfo"
        - type: object
          properties:
            attached_policies:
              type: array
              items:
                type: string
              description: Names of IAM policies attached to this access key
            access_key_scope:
              $ref: "#/components/schemas/AccessKeyScope"
    CreatePolicyRequest:
      type: object
      additionalProperties: false
      required:
        - name
        - document
      properties:
        name:
          type: string
          description: |
            Name of the policy. Must be unique within the organization.
            Only alphanumeric characters and `+=,.@_-` are allowed.
          maxLength: 128
        document:
          $ref: "#/components/schemas/PolicyDocument"
        description:
          type: string
          description: A description for the policy
          maxLength: 1000
    UpdatePolicyRequest:
      type: object
      additionalProperties: false
      required:
        - document
      properties:
        document:
          $ref: "#/components/schemas/PolicyDocument"
        description:
          type: string
          description: A description for the policy
          maxLength: 1000
    PolicyDocument:
      type: object
      description: |
        AWS IAM-compatible policy document.
        See [IAM Policies documentation](https://www.tigrisdata.com/docs/iam/policies/) for details.
      required:
        - Version
        - Statement
      properties:
        Version:
          type: string
          enum: ["2012-10-17"]
          description: Policy language version.
        Statement:
          type: array
          items:
            $ref: "#/components/schemas/PolicyStatement"
    PolicyStatement:
      type: object
      description: A permission statement within a policy document.
      required:
        - Effect
        - Action
        - Resource
      properties:
        Sid:
          type: string
          description: Optional identifier for the statement
        Effect:
          type: string
          enum: [Allow, Deny]
          description:
            Whether this statement allows or denies the specified actions
        Action:
          type: array
          items:
            type: string
          description: |
            S3 actions to allow or deny. Common actions: `s3:GetObject`, `s3:PutObject`,
            `s3:DeleteObject`, `s3:ListBucket`, `s3:*`.
            See [supported actions](https://www.tigrisdata.com/docs/iam/policies/supported-actions).
        Resource:
          type: array
          items:
            type: string
          description: |
            S3 resource ARNs. Use `arn:aws:s3:::bucket` for bucket-level and
            `arn:aws:s3:::bucket/prefix/*` for prefix-scoped access.
        Condition:
          type: object
          description: |
            Optional conditions (IP, time-based).
            See [condition examples](https://www.tigrisdata.com/docs/iam/policies/examples/ip-restrictions).
    PolicyInfo:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Name of the policy
        description:
          type: string
          description: Description of the policy
        attachment_count:
          type: integer
          description: Number of access keys this policy is attached to
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    PolicyResponse:
      type: object
      required:
        - name
        - document
      properties:
        name:
          type: string
          description: Name of the policy
        description:
          type: string
        document:
          $ref: "#/components/schemas/PolicyDocument"
        attachment_count:
          type: integer
          description: Number of access keys this policy is attached to
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    ListPoliciesResponse:
      type: object
      required:
        - policies
      properties:
        policies:
          type: array
          items:
            $ref: "#/components/schemas/PolicyInfo"
        next_continuation_token:
          type: string
          description:
            Pass as continuation_token for next page. Empty if no more results.
    DeletePolicyResponse:
      type: object
    GenericError:
      type: object
      properties:
        message:
          type: string
  parameters:
    provider_id:
      name: provider_id
      in: path
      required: true
      description: Provider ID
      schema:
        type: string
    org_id:
      name: org_id
      in: path
      required: true
      description: Organization ID
      schema:
        type: string
    bucket_name:
      name: bucket_name
      in: path
      required: true
      description: Bucket name
      schema:
        type: string
    policy_name:
      name: policy_name
      in: path
      required: true
      description: Name of the IAM policy
      schema:
        type: string
    version:
      name: version
      in: path
      required: true
      description: Snapshot version (UNIX nanosecond-precision timestamp).
      schema:
        type: string
  securitySchemes:
    Nonce:
      type: apiKey
      in: header
      name: X-Tigris-Nonce
      description: |
        Random unique string to identify the request and prevent replay attacks. Example: "f8d133cb-5a42-47b1-9ef2-874bb55bab72"
    Timestamp:
      type: apiKey
      in: header
      name: X-Tigris-Time
      description: |
        Unix timestamp in milliseconds of the request. Example: 1731703213870
    Signature:
      type: apiKey
      in: header
      name: X-Tigris-Signature
      description: |
        HMAC-SHA256 of the canonical request signed using the signing key.
        To create the signature, concatenate the HTTP method, URL, timestamp, and nonce with a newline character in between.
        Then, calculate the HMAC-SHA256 of the concatenated string using the signing key. Example:

        Create the `canonical_request` as:
        ```
        POST
        https://mgmt.storage.dev/provider/your-provider-id/orgs/user-org-id/provision
        1731703213870
        f8d133cb-5a42-47b1-9ef2-874bb55bab72
        ```
        Then, calculate HMAC-SHA256 of the canonical request using the signing key as:
        ```
        Signature = hex(sha256sign(canonical_request, "signing_key"))
        ```
security:
  - Signature: []
    Nonce: []
    Timestamp: []
