{
  "openapi": "3.1.0",
  "info": {
    "title": "Token Factory Management API",
    "version": "1",
    "summary": "Programmatic organization administration on portal.<domain>/api/v1/mgmt",
    "description": "The Token Factory Management API lets you administer your organization programmatically:\nprojects and their guardrails, API keys, members and pending invites, usage and cost,\nbilling reads, the model catalog and the audit log. It is a JSON REST API served on the\nportal host.\n\n### Base URL\n`https://portal.<domain>/api/v1/mgmt` — the inference API (`https://api.<domain>/v1`) is a\nseparate surface with separate credentials.\n\n### Authentication\nSend a personal access token on every call: `Authorization: Bearer tf-pat_…`. An\norganization admin creates tokens in the portal under **Settings → API Tokens**; each token\ncarries explicit scopes and always expires (90 days by default, 365 at most). A project API\nkey or a portal session is refused with 401 `credential_type_mismatch`, and a personal\naccess token is refused on the inference API the same way.\n\n### Authorization\nEvery operation needs its scope (`x-tf-scope`) **and** the token owner's current rights in\nthe organization: a token never does more than its owner can do right now. Missing either is\n403 `insufficient_scope`, and the message says which. Scopes: `org:read`, `org:write`*,\n`members:read`, `members:write`*, `projects:read`, `projects:write`*, `keys:read`,\n`keys:write`, `usage:read`, `billing:read`, `audit:read`, `catalog:read` (* sensitive). There\nis no wildcard; read and write are independent.\n\n### Idempotency\nEvery `POST`, `PATCH`, `PUT` and `DELETE` requires an `Idempotency-Key` header. Retrying with\nthe same key and the same request within 24 hours replays the original response\n(`Idempotent-Replayed: true`) instead of repeating the change.\n\n### Pagination\nLists return `{\"data\": [...], \"has_more\": bool, \"next_cursor\": string|null}`, newest first;\npass `next_cursor` as `cursor` for the next page. `limit` is 1–200 (default 50). An\nunsupported query parameter is 422 `unsupported_filter`, never silently ignored.\n\n### Rate limits\nLimits apply per token. Authenticated responses carry `X-RateLimit-Limit`,\n`X-RateLimit-Remaining` and `X-RateLimit-Reset`; a 429 carries `Retry-After`.\n\n### Errors and support\nErrors share one envelope with a stable `code`, a human `message` and, where useful, an\n`action` describing the fix. Every response carries `X-Request-Id`, repeated in errors as\n`error.request_id` — quote it when you contact support.\n",
    "contact": {
      "name": "Token Factory support"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://tokenfactory.iamsaif.ai/api/v1/mgmt",
      "description": "This environment"
    }
  ],
  "security": [
    {
      "personalAccessToken": []
    }
  ],
  "tags": [
    {
      "name": "Organization",
      "description": "Read and update your organization's name, slug and settings."
    },
    {
      "name": "Members",
      "description": "List members, change roles and project access, disable, enable, remove and sign out members."
    },
    {
      "name": "Invites",
      "description": "List and revoke pending invitations."
    },
    {
      "name": "Projects",
      "description": "Create, update, disable, enable and delete projects, and set their guardrails."
    },
    {
      "name": "API keys",
      "description": "Create, update, rotate, disable, enable and delete a project's API keys."
    },
    {
      "name": "Usage",
      "description": "Aggregated usage and cost reports, and per-request usage exports."
    },
    {
      "name": "Billing",
      "description": "Read balances, credit grants and invoices."
    },
    {
      "name": "Audit",
      "description": "Read and export the organization's audit log."
    },
    {
      "name": "Catalog",
      "description": "The models and regions your organization can use."
    },
    {
      "name": "Tokens",
      "description": "List and revoke your own personal access tokens."
    }
  ],
  "paths": {
    "/org": {
      "get": {
        "tags": [
          "Organization"
        ],
        "operationId": "getOrg",
        "summary": "Get the organization",
        "description": "**Scope:** `org:read`.\n\nThe response depends on the token owner's current role:\n- **Admin:** the full organization record with its settings (defaults, budget, MFA toggle,\n  spend ceiling, billing mode), the same object as `GET /org/settings`.\n- **Member:** only the organization's identity: id, name, slug, region, active state,\n  creation time and the owner's own role. Settings and billing mode are admin-only.",
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/Organization"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationIdentity"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "org:read"
      },
      "patch": {
        "tags": [
          "Organization"
        ],
        "operationId": "updateOrg",
        "summary": "Update organization settings",
        "description": "**Scope:** `org:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nOnly the fields present are changed. Accepts exactly the fields Settings → Organization edits.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "org:write"
      }
    },
    "/org/settings": {
      "get": {
        "tags": [
          "Organization"
        ],
        "operationId": "getOrgSettings",
        "summary": "Get the organization settings",
        "description": "**Scope:** `org:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n\nThe full organization record: identity plus its settings (defaults, budget, MFA toggle, spend\nceiling) and billing mode.",
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "org:read"
      }
    },
    "/members": {
      "get": {
        "tags": [
          "Members"
        ],
        "operationId": "listMembers",
        "summary": "List members",
        "description": "**Scope:** `members:read`.\n\nThe rows depend on the token owner's current role:\n- **Admin:** the full `Member` record (state, email verification, last login, key count).\n- **Member:** only each member's identity: id, email, name, role and creation time\n  (`MemberIdentity`). Member state is admin-only, so a member may not pass `status`\n  (403 `insufficient_scope`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "role",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "admin",
                "member"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Member state. Admin only; a member gets 403 `insufficient_scope`.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "disabled"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "anyOf": [
                              {
                                "$ref": "#/components/schemas/Member"
                              },
                              {
                                "$ref": "#/components/schemas/MemberIdentity"
                              }
                            ]
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:read"
      }
    },
    "/members/removed": {
      "get": {
        "tags": [
          "Members"
        ],
        "operationId": "listRemovedMembers",
        "summary": "List removed members",
        "description": "**Scope:** `members:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n\nPeople an admin removed from the organization, newest removal first. A removed person can't\nrejoin through SSO automatic membership; restore them (`POST /members/removed/{id}/restore`)\nor invite them to give access again. `last_role`, `name` and the projects are `null` / not\nrecorded for removals made before they were captured.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/RemovedMember"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:read"
      }
    },
    "/members/removed/{id}/restore": {
      "post": {
        "tags": [
          "Members"
        ],
        "operationId": "restoreRemovedMember",
        "summary": "Restore a removed member",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nGives a removed person access again with their previous role and the recorded projects that\nstill exist (member, with no projects, when none were recorded). Removal deleted their\nsign-in, so they become a member when they next sign in: the organization's SSO lets them\nstraight in, any other sign-in method uses the link in the email they receive (\"You've been\ngiven access to <organization> again\"). Until then they are listed under `GET /invites`\n(`invite_id`) and still listed under `GET /members/removed` (`invite_pending: true`): the\nremoved marker is cleared only when they accept; if the invitation is revoked or expires they\nstay removed. 409 `already_a_member` when the person is a\nmember again; 409 `conflict` when the invitation rules refuse the address (for example the\norganization's SSO limits invitations to the admin's email domain).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestoredMember"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      }
    },
    "/members/{id}": {
      "get": {
        "tags": [
          "Members"
        ],
        "operationId": "getMember",
        "summary": "Get a member",
        "description": "**Scope:** `members:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Member"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:read"
      },
      "patch": {
        "tags": [
          "Members"
        ],
        "operationId": "updateMember",
        "summary": "Change a member's role or name",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nDemoting the organization's last active admin is refused with 409 `last_admin`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MemberPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Member"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      },
      "delete": {
        "tags": [
          "Members"
        ],
        "operationId": "removeMember",
        "summary": "Remove a member",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nRemoves the member from the organization (their personal access tokens are deleted with them). `delete_keys: true` also revokes every API key they created. Last admin → 409 `last_admin`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MemberRemove"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Done (no body).",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      }
    },
    "/members/{id}/projects": {
      "put": {
        "tags": [
          "Members"
        ],
        "operationId": "setMemberProjects",
        "summary": "Replace a member's project access",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nReplaces the member's project list. Admins see every project regardless.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MemberProjects"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Member"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      }
    },
    "/members/{id}/disable": {
      "post": {
        "tags": [
          "Members"
        ],
        "operationId": "disableMember",
        "summary": "Disable a member",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nSigns the member out of every browser session and revokes all of their personal access tokens. Disabling the last active admin is refused with 409 `last_admin`; disabling yourself with 409 `cannot_act_on_self`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Member"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      }
    },
    "/members/{id}/enable": {
      "post": {
        "tags": [
          "Members"
        ],
        "operationId": "enableMember",
        "summary": "Re-enable a member",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nTokens revoked by the disable are not restored.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Member"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      }
    },
    "/members/{id}/sessions": {
      "delete": {
        "tags": [
          "Members"
        ],
        "operationId": "revokeMemberSessions",
        "summary": "Sign a member out everywhere",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nEnds every sign-in session of the member. 409 `sessions_unavailable` when the member has no active sign-in session to end.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Done (no body).",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      }
    },
    "/invites": {
      "get": {
        "tags": [
          "Invites"
        ],
        "operationId": "listInvites",
        "summary": "List pending invites",
        "description": "**Scope:** `members:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Invite"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:read"
      },
      "post": {
        "tags": [
          "Invites"
        ],
        "operationId": "createInvite",
        "summary": "Invite a member",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nReuses the portal invite flow: the email is normalized, the role must be `member` or `admin`\n(default `member`; `superadmin` is rejected), project access is applied, and an organization\nwith an active SSO connection only accepts the acting admin's own email domain.\n\nIdempotent per email: an address already in the organization answers `status: already_member`,\nand an existing pending invite answers `status: already_pending` — the existing record is\nreturned, never duplicated.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 254,
                    "description": "One bare address (no display name). A missing or malformed address is 400 `invalid_request` (param `email`)."
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "member",
                      "admin"
                    ],
                    "default": "member"
                  },
                  "project_ids": {
                    "type": "array",
                    "maxItems": 100,
                    "description": "Projects a `member` joins on acceptance (ignored for `admin`). Every id must be a project of the caller's organization; otherwise 400 `invalid_request` (param `project_ids`).",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The address already belongs to the organization, or already has a pending invite — the existing record is returned, never duplicated.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteCreateResult"
                }
              }
            }
          },
          "201": {
            "description": "A new invitation was created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteCreateResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      }
    },
    "/invites/{id}": {
      "delete": {
        "tags": [
          "Invites"
        ],
        "operationId": "revokeInvite",
        "summary": "Revoke a pending invite",
        "description": "**Scope:** `members:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Done (no body).",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "members:write"
      }
    },
    "/projects": {
      "get": {
        "tags": [
          "Projects"
        ],
        "operationId": "listProjects",
        "summary": "List projects",
        "description": "**Scope:** `projects:read`.\n\nAdmins see every project; members see the projects they belong to. List rows omit `guardrails` — get the project for them.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Project state.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "disabled"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Project"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "projects:read"
      },
      "post": {
        "tags": [
          "Projects"
        ],
        "operationId": "createProject",
        "summary": "Create a project",
        "description": "**Scope:** `projects:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\n`guardrails.ip_allowlist` cannot be set at creation; set it with PATCH.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "projects:write"
      }
    },
    "/projects/{id}": {
      "get": {
        "tags": [
          "Projects"
        ],
        "operationId": "getProject",
        "summary": "Get a project with its guardrails",
        "description": "**Scope:** `projects:read`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "projects:read"
      },
      "patch": {
        "tags": [
          "Projects"
        ],
        "operationId": "updateProject",
        "summary": "Rename a project or change its guardrails",
        "description": "**Scope:** `projects:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nGuardrails are merged over the current values: an absent field is kept, `null` clears it. The default project cannot be renamed (409 `default_project_protected`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "projects:write"
      },
      "delete": {
        "tags": [
          "Projects"
        ],
        "operationId": "deleteProject",
        "summary": "Permanently delete a project",
        "description": "**Scope:** `projects:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nIrreversible: the project, its settings and memberships are deleted. The default project is protected (409 `default_project_protected`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Done (no body).",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "projects:write"
      }
    },
    "/projects/{id}/disable": {
      "post": {
        "tags": [
          "Projects"
        ],
        "operationId": "disableProject",
        "summary": "Disable a project",
        "description": "**Scope:** `projects:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.\n\nIts API keys stop authenticating until the project is enabled again. The default project is protected (409).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "projects:write"
      }
    },
    "/projects/{id}/enable": {
      "post": {
        "tags": [
          "Projects"
        ],
        "operationId": "enableProject",
        "summary": "Enable a project",
        "description": "**Scope:** `projects:write`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n**Idempotency-Key** header required.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "projects:write"
      }
    },
    "/projects/{id}/keys": {
      "get": {
        "tags": [
          "API keys"
        ],
        "operationId": "listKeys",
        "summary": "List a project's API keys",
        "description": "**Scope:** `keys:read`.\n\nSecrets are never listed. Members see only the keys they created.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Key state.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "disabled",
                "revoked"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ApiKey"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:read"
      },
      "post": {
        "tags": [
          "API keys"
        ],
        "operationId": "createKey",
        "summary": "Create an API key",
        "description": "**Scope:** `keys:write`.\n**Idempotency-Key** header required.\n\nThe `secret` is returned **once**. Replaying the same request with the same token and Idempotency-Key within 24 h returns it again (the replay is audited as `key_create_replayed`) — only while you can still see the key (project access, and for members, keys you created are re-checked). If the secret is not available for replay, the replay is 409 `idempotency_replay_unavailable`: the secret was delivered once, on the original response; if it was lost, retry with a new Idempotency-Key and revoke the unused key. Members may create keys only in projects they belong to.\n\nSpend limits are set on the project (`spend_limit_usd`), not on keys: a body carrying `spend_cap_amount`, `spend_cap_reset_period` or `clear_spend_cap` — any value, including `null` — is rejected with 400 `invalid_request`, `param` naming the field.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyWithSecret"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:write"
      }
    },
    "/keys/{id}": {
      "get": {
        "tags": [
          "API keys"
        ],
        "operationId": "getKey",
        "summary": "Get an API key",
        "description": "**Scope:** `keys:read`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:read"
      },
      "patch": {
        "tags": [
          "API keys"
        ],
        "operationId": "updateKey",
        "summary": "Update an API key",
        "description": "**Scope:** `keys:write`.\n**Idempotency-Key** header required.\n\nRename, change expiry (`null` = never) and IP allowlist (`[]` = no restriction). Use the enable/disable endpoints for the active flag.\n\nSpend limits are set on the project (`spend_limit_usd`), not on keys: a body carrying `spend_cap_amount`, `spend_cap_reset_period` or `clear_spend_cap` — any value, including `null` — is rejected with 400 `invalid_request`, `param` naming the field.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:write"
      },
      "delete": {
        "tags": [
          "API keys"
        ],
        "operationId": "deleteKey",
        "summary": "Revoke an API key permanently",
        "description": "**Scope:** `keys:write`.\n**Idempotency-Key** header required.\n\n`confirmed_leak: true` also cuts off requests already streaming on the key.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyRevoke"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Done (no body).",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:write"
      }
    },
    "/keys/{id}/rotate": {
      "post": {
        "tags": [
          "API keys"
        ],
        "operationId": "rotateKey",
        "summary": "Rotate an API key",
        "description": "**Scope:** `keys:write`.\n**Idempotency-Key** header required.\n\nIssues a new secret (returned once, and again on an idempotent replay by the same token while you can still see the key — audited as `key_rotate_replayed`; if the secret is not available for replay the replay is 409 `idempotency_replay_unavailable`, see createKey). The previous secret keeps working until `rotation.grace_expires_at` (default 24 h, 1–168 h).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RotateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyWithSecret"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:write"
      }
    },
    "/keys/{id}/rotate/cancel": {
      "post": {
        "tags": [
          "API keys"
        ],
        "operationId": "cancelKeyRotation",
        "summary": "Cancel an in-progress rotation",
        "description": "**Scope:** `keys:write`.\n**Idempotency-Key** header required.\n\nDiscards the new secret and restores the original. 409 `no_rotation_in_progress` otherwise.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:write"
      }
    },
    "/keys/{id}/disable": {
      "post": {
        "tags": [
          "API keys"
        ],
        "operationId": "disableKey",
        "summary": "Disable an API key",
        "description": "**Scope:** `keys:write`.\n**Idempotency-Key** header required.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:write"
      }
    },
    "/keys/{id}/enable": {
      "post": {
        "tags": [
          "API keys"
        ],
        "operationId": "enableKey",
        "summary": "Enable an API key",
        "description": "**Scope:** `keys:write`.\n**Idempotency-Key** header required.\n\nA revoked (deleted) key cannot be enabled (409 `key_revoked`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "keys:write"
      }
    },
    "/usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "operationId": "getUsage",
        "summary": "Get usage and cost for a time window",
        "description": "**Scope:** `usage:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n\nAggregated usage and cost for the organization over `[from, to)`, broken down by one\ndimension (`group_by`). Quantities are in native units (tokens; `totals.units[]` gives\nper-unit quantities for images, seconds, characters …); money is integer nano-USD\n(`cost_nanousd`) plus its exact decimal-string rendering (`cost_usd`).\n\n**Invariant:** when `reconciled` is true (the normal case), for every field of `totals`\nexcept `units`, the sum over `breakdown[]` equals the total exactly. The `other` group holds\nthe tail beyond the top 20 groups and any usage that could not be attributed to a group (for\nexample requests with no key). `totals` are never adjusted to fit the breakdown. In rare\ncases the breakdown can briefly exceed the totals; the response then has\n`reconciled: false` and a `breakdown_note`. Retry for a consistent report.\n`group_by=day` returns one exact row per UTC calendar day (the first and last may be partial\ndays) and covers at most 31 days per call.\n\nNo request or response content is ever returned — only counts and money. Usage counts may\ntrail real time by up to a minute; `usage_stale` / `usage_as_of` say when. Money is exact.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Inclusive lower bound (RFC 3339). Default `to` − 30 days. The range may span at most 366 days.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Exclusive upper bound (RFC 3339). Default now.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "group_by",
            "in": "query",
            "required": false,
            "description": "One dimension per call. Several values (`model,day`) are 422 `unsupported_filter`.",
            "schema": {
              "type": "string",
              "enum": [
                "project",
                "model",
                "key",
                "day"
              ],
              "default": "model"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "required": false,
            "description": "Only usage of this project.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "key_id",
            "in": "query",
            "required": false,
            "description": "Only usage of this API key.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "model",
            "in": "query",
            "required": false,
            "description": "Only usage of this model (`provider/model`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageReport"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "usage:read"
      }
    },
    "/usage/export": {
      "get": {
        "tags": [
          "Usage"
        ],
        "operationId": "exportUsage",
        "summary": "Export per-request usage records",
        "description": "**Scope:** `usage:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n\nStreams one `UsageRecord` per metered request in `[from, to)`, newest first, as JSON Lines\nor CSV. Records carry counts, money and identifiers only — never prompt or completion\ncontent, error text or client addresses. **At most 10,000 records per call**: a wider match\nis refused with 422 `export_too_large` before anything streams — narrow `from`/`to` and\nexport in windows. The export is itself audited (`usage_export`, with `row_count`).\n\n**Truncation.** An export can stop early after the 200 status has been sent. A truncated\nexport is therefore not an error response; it is a stream that ends with a marker line\ninstead of a record — JSON Lines:\n`{\"truncated\":true,\"rows\":N,\"reason\":\"row_cap\"|\"upstream_error\"}`; CSV: a last line\n`# truncated after N rows (<reason>)` — and the `X-Export-Truncated: true` HTTP trailer\n(declared in `Trailer`; proxies may drop trailers, so check the marker). A stream without\nthe marker is complete. On `upstream_error` re-run the export; on `row_cap` narrow the window.\n\nRecords are read newest first in pages of 200 with a cursor on (`created_at`, `id`), so\nrecords that share the same timestamp are all exported, each exactly once.",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "jsonl",
                "csv"
              ],
              "default": "jsonl"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Inclusive lower bound (RFC 3339). Default `to` − 30 days; at most 366 days.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Exclusive upper bound (RFC 3339). Default now.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "key_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "model",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The export stream.",
            "headers": {
              "Trailer": {
                "description": "Always `X-Export-Truncated` — the trailer that may follow the body.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Export-Truncated": {
                "description": "Sent as an HTTP trailer (after the body), `true`, only when the stream was cut short; see the truncation marker.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string",
                  "description": "One UsageRecord JSON object per line; a stream cut short ends with the `ExportTruncation` object instead."
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Header row: id,created_at,project_id,key_id,model,provider,status,unit,input_tokens,output_tokens,total_tokens,cached_input_tokens,cache_write_tokens,reasoning_tokens,quantity_in,quantity_out,cost_nanousd,cost_usd,cost_available,latency_ms,streaming. A stream cut short ends with the line `# truncated after N rows (<reason>)`."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "usage:read"
      }
    },
    "/billing/balance": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "getBalance",
        "summary": "Get the prepaid credit balance",
        "description": "**Scope:** `billing:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).",
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "billing:read"
      }
    },
    "/billing/grants": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "listGrants",
        "summary": "List credit grants and top-ups",
        "description": "**Scope:** `billing:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n\nCredits added to the organization (grants, top-ups, refunds as negative amounts).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Grant"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "billing:read"
      }
    },
    "/billing/invoices": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "listInvoices",
        "summary": "List invoices",
        "description": "**Scope:** `billing:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Invoice"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "billing:read"
      }
    },
    "/billing/invoices/{id}": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "getInvoice",
        "summary": "Get an invoice",
        "description": "**Scope:** `billing:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "billing:read"
      }
    },
    "/audit": {
      "get": {
        "tags": [
          "Audit"
        ],
        "operationId": "listAudit",
        "summary": "List audit events",
        "description": "**Scope:** `audit:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n\nNewest first. Writes made with a personal access token carry `metadata.credential = \"pat\"`, `pat_id`, `pat_name` and `scope`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "actor",
            "in": "query",
            "required": false,
            "description": "Actor user id or email (case-insensitive).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "description": "Exact action name, e.g. `key_create`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Inclusive lower bound (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Exclusive upper bound (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/AuditEvent"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "audit:read"
      }
    },
    "/audit/export": {
      "get": {
        "tags": [
          "Audit"
        ],
        "operationId": "exportAudit",
        "summary": "Export audit events",
        "description": "**Scope:** `audit:read`.\n**Role:** the token owner must currently be an organization **admin** (403 `insufficient_scope` otherwise).\n\nStreams every matching event, newest first, as JSON Lines (one `AuditEvent` per line) or CSV. **At most 10,000 events per call**: a wider match is refused with 422 `export_too_large` — narrow `from`/`to` and export in windows. The export is itself audited (`audit_export`, with `row_count`).",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "jsonl",
                "csv"
              ],
              "default": "jsonl"
            }
          },
          {
            "name": "actor",
            "in": "query",
            "required": false,
            "description": "Actor user id or email (case-insensitive).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "description": "Exact action name, e.g. `key_create`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Inclusive lower bound (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Exclusive upper bound (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The export stream.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string",
                  "description": "One AuditEvent JSON object per line."
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Header row: id,created_at,actor_user_id,actor_email,action,resource_type,resource_id,ip_address,metadata"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "audit:read"
      }
    },
    "/catalog/models": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listCatalogModels",
        "summary": "List the models the organization can call",
        "description": "**Scope:** `catalog:read`. Any organization member.\n\nThe live model catalog as the portal's Models page shows it: enabled models only (never\ndisabled or retired ones). Each entry is the public model card — the same object the\ninference API's `GET /v1/models` returns — priced at the default-region client rate (what\nthe organization is billed, USD per one unit as decimal strings), plus `mode`, `status`,\n`capabilities` and `regions`. `id` is the name to send as `model` on the inference API.\nOrdered by `id` descending (the catalog has no creation time); `limit`/`cursor` page it\nlike every other list.\n\nChanged in 0.16.1 (pre-production, no deprecation window): the earlier `provider`,\n`max_completion_tokens`, `input_modalities`, `output_modalities` and\n`pricing.currency`/`pricing.rates` were removed in favour of the card's fields.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CatalogModel"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "catalog:read"
      }
    },
    "/catalog/regions": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listCatalogRegions",
        "summary": "List the regions models are served in",
        "description": "**Scope:** `catalog:read`. Any organization member.\n\nDerived from the model list: the distinct regions of the organization's models, with how\nmany models each serves.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CatalogRegion"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "x-tf-scope": "catalog:read"
      }
    },
    "/me/tokens": {
      "get": {
        "tags": [
          "Tokens"
        ],
        "operationId": "listMyTokens",
        "summary": "List your personal access tokens",
        "description": "**Scope:** none — any valid personal access token.\n\nYour own tokens in this organization, masked (the secret is shown only once, at creation in the portal).",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Token state (expiry is derived from `expires_at`).",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "revoked"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ListEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Token"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-tf-scope": "none"
      }
    },
    "/me/tokens/{id}": {
      "delete": {
        "tags": [
          "Tokens"
        ],
        "operationId": "revokeMyToken",
        "summary": "Revoke one of your personal access tokens",
        "description": "**Scope:** none — any valid personal access token.\n**Idempotency-Key** header required.\n\nImmediate. Revoking the token making the call is allowed.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Done (no body).",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-tf-scope": "none"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "personalAccessToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "tf-pat_",
        "description": "A personal access token (`tf-pat_…`) minted in Settings → API Tokens."
      }
    },
    "parameters": {
      "Id": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Object id (opaque string; a malformed id is a 404).",
        "schema": {
          "type": "string"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size, 1–200.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "Opaque `next_cursor` from the previous page.",
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Unique per logical operation (e.g. a UUID), ≤255 chars. Reuse it to retry safely: same token + same key + same method, path and body within 24 h replays the stored response; same key + different request is 409 `idempotency_conflict`. Keys are scoped to the personal access token that sent them — the same key value from another token is a new request. A replay is served only after the route's scope and your current rights are checked again. Stored responses are deleted after 24 h.",
        "schema": {
          "type": "string",
          "maxLength": 255
        },
        "example": "00000000-0000-4000-8000-000000000000"
      }
    },
    "headers": {
      "X-Request-Id": {
        "description": "Request id — `req_` followed by 32 hex characters; treat it as an opaque string. The same value is `error.request_id` on errors. An `X-Request-Id` you send is ignored.",
        "schema": {
          "type": "string",
          "example": "req_6f1c2d9e8a4b4c3d9e2f1a2b3c4d5e6f"
        }
      },
      "X-RateLimit-Limit": {
        "description": "The token's sustained rate in requests per minute (the bucket's refill rate). Authenticated responses only.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Whole requests left in the token's bucket after this one (never more than the burst). Authenticated responses only.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix time (seconds) when the bucket is full again if no more requests are sent. Authenticated responses only.",
        "schema": {
          "type": "integer"
        }
      },
      "Idempotent-Replayed": {
        "description": "`true` when this response is a replay of an earlier request with the same Idempotency-Key.",
        "schema": {
          "type": "string",
          "enum": [
            "true"
          ]
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Malformed request: invalid body/field (`invalid_request`, `param` names it), missing Idempotency-Key (`idempotency_key_required`), bad `limit`/`cursor`.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Credential problem: `missing_credential`, `credential_type_mismatch` (an API key or session was sent), `invalid_credential`, `token_expired`, `token_revoked`. No `X-RateLimit-*` headers (the token was not accepted).",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "Forbidden": {
        "description": "`insufficient_scope`: the token lacks the route's scope (`param` = the scope), or the token owner's current role or project access does not include the action (the message names it).",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "NotFound": {
        "description": "`not_found`: the object does not exist **or belongs to another organization** — the two are indistinguishable.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "Conflict": {
        "description": "A business rule or idempotency conflict: `idempotency_conflict`, `idempotency_replay_unavailable` (a key create/rotate already succeeded under this Idempotency-Key but its one-time secret is not kept for replay — retry with a new key; the secret was delivered once), `last_admin`, `owner_protected`, `cannot_act_on_self`, `default_project_protected`, `name_taken`, `slug_taken`, `key_revoked`, `no_rotation_in_progress`, `sessions_unavailable`, `conflict`.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "`unsupported_filter` (an unknown query parameter; `param` names it — filters are never silently ignored), `validation_failed` (a filter value), `export_too_large`.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "RateLimited": {
        "description": "`rate_limit_exceeded`: the per-token rate limit was hit. Retry after `Retry-After` seconds.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait.",
            "example": 1
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "message": "rate limit exceeded for this token; retry after 1 s",
                "type": "rate_limit_error",
                "code": "rate_limit_exceeded",
                "param": null,
                "action": "Wait Retry-After seconds, then retry.",
                "request_id": "req_9b2e4d1f6a3c4e8bb7d50c1a2f3e4d5c"
              }
            }
          }
        }
      },
      "ServerError": {
        "description": "`internal_error` (`api_error`): retry; quote `request_id` to support if it persists.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      },
      "BadGateway": {
        "description": "`upstream_unavailable`: a service this API depends on is temporarily unavailable; retry (with the same Idempotency-Key for a write).",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorCode": {
        "type": "string",
        "description": "Stable machine code. Codes are never repurposed within v1.",
        "enum": [
          "missing_credential",
          "credential_type_mismatch",
          "invalid_credential",
          "token_expired",
          "token_revoked",
          "rate_limit_exceeded",
          "insufficient_scope",
          "invalid_request",
          "idempotency_key_required",
          "idempotency_conflict",
          "idempotency_replay_unavailable",
          "not_found",
          "conflict",
          "last_admin",
          "owner_protected",
          "cannot_act_on_self",
          "sessions_unavailable",
          "default_project_protected",
          "name_taken",
          "slug_taken",
          "key_revoked",
          "no_rotation_in_progress",
          "unsupported_filter",
          "validation_failed",
          "export_too_large",
          "upstream_unavailable",
          "internal_error"
        ]
      },
      "ErrorEnvelope": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "message",
              "type",
              "code",
              "param",
              "request_id"
            ],
            "properties": {
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "permission_error",
                  "not_found_error",
                  "conflict_error",
                  "validation_error",
                  "rate_limit_error",
                  "api_error"
                ]
              },
              "code": {
                "$ref": "#/components/schemas/ErrorCode"
              },
              "param": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The offending parameter, field or scope, when there is one."
              },
              "action": {
                "type": "string",
                "description": "What to do about it, when not obvious."
              },
              "request_id": {
                "type": "string",
                "description": "Equals the X-Request-Id response header. Quote it to support."
              }
            }
          }
        },
        "example": {
          "error": {
            "message": "this token does not carry the projects:write scope",
            "type": "permission_error",
            "code": "insufficient_scope",
            "param": "projects:write",
            "action": "Mint a token that includes projects:write in Settings → API Tokens.",
            "request_id": "req_3f6c2a9e8b1d4c7a9e215d0b7f4a1c38"
          }
        }
      },
      "ListEnvelope": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {}
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "OrganizationIdentity": {
        "type": "object",
        "additionalProperties": false,
        "description": "The member-safe organization record `GET /org` returns to a non-admin token owner. Exactly these fields.",
        "required": [
          "id",
          "name",
          "slug",
          "region",
          "is_active",
          "created_at",
          "role"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "Display name. Free text and not unique — several organizations may share a name."
          },
          "slug": {
            "type": "string",
            "description": "Unique URL-safe handle, generated from the name at creation (lowercase ASCII, `-` separated; a numeric suffix such as `acme-2` is added when taken). Use `id` as the stable identifier."
          },
          "region": {
            "type": "string"
          },
          "is_active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "member"
            ],
            "description": "The token owner's own role in the organization."
          }
        }
      },
      "Organization": {
        "type": "object",
        "additionalProperties": true,
        "description": "The organization plus its settings (`GET /org` for an admin, `GET /org/settings`, `PATCH /org`). Settings keys appear once set.",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "Display name. Free text and not unique — several organizations may share a name."
          },
          "slug": {
            "type": "string",
            "description": "Unique URL-safe handle, generated from the name at creation (lowercase ASCII, `-` separated; a numeric suffix such as `acme-2` is added when taken). Use `id` as the stable identifier."
          },
          "is_active": {
            "type": "boolean"
          },
          "billing_mode": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "spend_ceiling": {
            "type": "number",
            "description": "Org-level spend bound (USD); absent = unbounded."
          },
          "default_model_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "default_rpm_limit": {
            "type": "integer"
          },
          "default_daily_cap": {
            "type": "number"
          },
          "default_monthly_cap": {
            "type": "number"
          },
          "monthly_budget": {
            "type": "number"
          },
          "budget_behavior": {
            "type": "string",
            "enum": [
              "alert_only",
              "hard_stop"
            ]
          },
          "email_otp_enabled": {
            "type": "boolean"
          }
        }
      },
      "OrganizationPatch": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "New display name. Not unique; renaming never changes the slug."
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 48,
            "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
            "description": "New unique handle, same rules as a generated slug: lowercase letters, digits and single hyphens, no leading or trailing hyphen, at most 48 characters, not a reserved word (for example `default`, `admin`, `api`, `portal`, `mgmt`). A slug that breaks these rules is rejected with 400 `invalid_request` (param `slug`); one another organization already uses is rejected with 409 `slug_taken`."
          },
          "default_model_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "default_rpm_limit": {
            "type": "integer"
          },
          "default_daily_cap": {
            "type": "number"
          },
          "default_monthly_cap": {
            "type": "number"
          },
          "monthly_budget": {
            "type": "number"
          },
          "budget_behavior": {
            "type": "string",
            "enum": [
              "alert_only",
              "hard_stop"
            ]
          },
          "email_otp_enabled": {
            "type": "boolean"
          },
          "spend_ceiling": {
            "type": "number",
            "minimum": 0,
            "description": "0 clears the bound."
          }
        }
      },
      "Member": {
        "type": "object",
        "required": [
          "id",
          "email",
          "role",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "member"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "email_verified": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_login_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "key_count": {
            "type": "integer",
            "description": "API keys this member created."
          },
          "project_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Present on single-member responses."
          }
        }
      },
      "RemovedMember": {
        "type": "object",
        "required": [
          "id",
          "email",
          "projects_recorded",
          "projects",
          "removed_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The removal's id (the person's member id no longer exists)."
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_role": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "admin",
              "member",
              null
            ],
            "description": "Their organization role when removed; null when not recorded."
          },
          "projects_recorded": {
            "type": "boolean",
            "description": "False for removals made before project memberships were recorded."
          },
          "projects": {
            "type": "array",
            "description": "Recorded projects that still exist in the organization.",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "removed_at": {
            "type": "string",
            "format": "date-time"
          },
          "removed_by": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "invite_pending": {
            "type": "boolean",
            "description": "A restore or new invitation was sent and not accepted yet. The person stays removed until they accept it; a revoked or expired invitation leaves them removed."
          }
        }
      },
      "RestoredMember": {
        "type": "object",
        "required": [
          "status",
          "email",
          "role",
          "project_ids",
          "invite_id"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "restored"
            ]
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "member"
            ]
          },
          "project_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "invite_id": {
            "type": "string",
            "description": "The pending invitation the person accepts by signing in."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "MemberIdentity": {
        "type": "object",
        "additionalProperties": false,
        "description": "The member-safe row `GET /members` returns to a non-admin token owner. Exactly these fields.",
        "required": [
          "id",
          "email",
          "name",
          "role",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "member"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "MemberPatch": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "member"
            ]
          },
          "name": {
            "type": "string"
          }
        }
      },
      "MemberProjects": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "project_ids"
        ],
        "properties": {
          "project_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "MemberRemove": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "delete_keys": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "Invite": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "member"
            ]
          },
          "project_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "pending"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "InviteCreateResult": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "created",
              "already_member",
              "already_pending"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role": {
            "type": "string"
          },
          "project_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "is_active": {
            "type": "boolean"
          }
        }
      },
      "Guardrails": {
        "type": "object",
        "properties": {
          "model_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Empty = every model the plan allows."
          },
          "rpm_limit": {
            "type": [
              "integer",
              "null"
            ],
            "description": "null = no project limit."
          },
          "spend_limit_usd": {
            "type": [
              "number",
              "null"
            ],
            "description": "null = no project cap. Cannot exceed the org's spend_ceiling."
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "CIDRs; empty = no restriction."
          }
        }
      },
      "GuardrailsInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "model_allowlist": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "rpm_limit": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "spend_limit_usd": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0
          },
          "ip_allowlist": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Project": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "is_default": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "monthly_spend_usd": {
            "type": "number",
            "description": "Trailing 30 days."
          },
          "active_key_count": {
            "type": "integer",
            "description": "List rows only."
          },
          "guardrails": {
            "$ref": "#/components/schemas/Guardrails"
          }
        }
      },
      "ProjectCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "region_id": {
            "type": "string"
          },
          "guardrails": {
            "$ref": "#/components/schemas/GuardrailsInput"
          }
        }
      },
      "ProjectPatch": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "guardrails": {
            "$ref": "#/components/schemas/GuardrailsInput"
          }
        }
      },
      "ApiKey": {
        "type": "object",
        "required": [
          "id",
          "project_id",
          "name",
          "key_prefix",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "project_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "key_prefix": {
            "type": "string",
            "description": "Masked key identifier; never the secret."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled",
              "revoked"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "requests_7d": {
            "type": "integer"
          },
          "allowed_models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rpm_limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "spend_cap": {
            "type": [
              "object",
              "null"
            ],
            "description": "Legacy key-level spend cap, read-only. Spend limits are set on the project; new key caps cannot be set through this API, and a cap stored earlier is still shown (and enforced) here.",
            "properties": {
              "amount_usd": {
                "type": "number"
              },
              "reset_period": {
                "type": "string",
                "enum": [
                  "daily",
                  "weekly",
                  "monthly",
                  "never"
                ]
              }
            }
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rotation": {
            "type": [
              "object",
              "null"
            ],
            "description": "Present while the previous secret is still accepted.",
            "properties": {
              "grace_expires_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "created_by": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      },
      "ApiKeyWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiKey"
          },
          {
            "type": "object",
            "required": [
              "secret"
            ],
            "properties": {
              "secret": {
                "type": "string",
                "description": "The full API key. Shown once — store it now."
              }
            }
          }
        ]
      },
      "ApiKeyCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1
          },
          "description": {
            "type": "string"
          },
          "allowed_models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rpm_limit": {
            "type": "integer",
            "minimum": 1,
            "description": "Requests per minute for this key. Omit it for no per-key limit; a value below 1 is rejected with 400 `invalid_request` (param `rpm_limit`)."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ApiKeyPatch": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ip_allowlist": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ApiKeyRevoke": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "confirmed_leak": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "RotateRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "grace_hours": {
            "type": "integer",
            "minimum": 1,
            "maximum": 168,
            "default": 24
          }
        }
      },
      "Balance": {
        "type": "object",
        "properties": {
          "available_nanousd": {
            "type": "integer",
            "description": "Integer nano-USD (1e-9 USD)."
          },
          "available_usd": {
            "type": "number"
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "wallet_present": {
            "type": "boolean",
            "description": "false when the organization has never been granted credit."
          }
        }
      },
      "Grant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "source": {
            "type": "string"
          },
          "memo": {
            "type": "string"
          },
          "amount_nanousd": {
            "type": "integer",
            "description": "Negative for refunds/reversals."
          },
          "amount_usd": {
            "type": "number"
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Invoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "stripe_invoice_id": {
            "type": "string"
          },
          "amount_cents": {
            "type": "integer"
          },
          "currency": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "period_start": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "period_end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "pdf_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AuditEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "actor": {
            "type": "object",
            "properties": {
              "user_id": {
                "type": "string"
              },
              "email": {
                "type": "string"
              }
            }
          },
          "action": {
            "type": "string"
          },
          "resource_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "resource_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "ip_address": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UsageQuantities": {
        "type": "object",
        "required": [
          "requests",
          "errors",
          "input_tokens",
          "output_tokens",
          "total_tokens",
          "cached_input_tokens",
          "cache_write_tokens",
          "reasoning_tokens",
          "cost_nanousd",
          "cost_usd"
        ],
        "properties": {
          "requests": {
            "type": "integer"
          },
          "errors": {
            "type": "integer",
            "description": "Requests that ended in an error status."
          },
          "input_tokens": {
            "type": "integer"
          },
          "output_tokens": {
            "type": "integer"
          },
          "total_tokens": {
            "type": "integer"
          },
          "cached_input_tokens": {
            "type": "integer",
            "description": "Prompt-cache read tokens (a subset of input_tokens)."
          },
          "cache_write_tokens": {
            "type": "integer",
            "description": "Prompt-cache write tokens (a subset of input_tokens)."
          },
          "reasoning_tokens": {
            "type": "integer",
            "description": "Reasoning tokens (a subset of output_tokens)."
          },
          "cost_nanousd": {
            "type": "integer",
            "description": "Billed cost in integer nano-USD (1e-9 USD). Sums are exact."
          },
          "cost_usd": {
            "type": "string",
            "description": "The same cost as a decimal string, e.g. `\"12.345678901\"` (at least two fraction digits)."
          }
        }
      },
      "UsageUnit": {
        "type": "object",
        "description": "Native-unit quantity for one billing unit. Quantities of different units are never summed together.",
        "properties": {
          "unit": {
            "type": "string",
            "description": "token, image, second, character, document …"
          },
          "requests": {
            "type": "integer"
          },
          "quantity_in": {
            "type": "integer"
          },
          "quantity_out": {
            "type": "integer"
          },
          "cost_nanousd": {
            "type": "integer"
          },
          "cost_usd": {
            "type": "string"
          }
        }
      },
      "UsageTotals": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UsageQuantities"
          },
          {
            "type": "object",
            "properties": {
              "units": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/UsageUnit"
                }
              }
            }
          }
        ]
      },
      "UsageGroup": {
        "allOf": [
          {
            "type": "object",
            "required": [
              "key"
            ],
            "properties": {
              "key": {
                "type": "string",
                "description": "The project id, API key id, model (`provider/model`) or UTC date (`YYYY-MM-DD`), per `group_by`; `other` for the tail and unattributed usage."
              }
            }
          },
          {
            "$ref": "#/components/schemas/UsageQuantities"
          }
        ]
      },
      "UsageReport": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "format": "date-time"
          },
          "to": {
            "type": "string",
            "format": "date-time"
          },
          "group_by": {
            "type": "string",
            "enum": [
              "project",
              "model",
              "key",
              "day"
            ]
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "totals": {
            "$ref": "#/components/schemas/UsageTotals"
          },
          "breakdown": {
            "type": "array",
            "description": "Sums to `totals` exactly, field by field, when `reconciled` is true.",
            "items": {
              "$ref": "#/components/schemas/UsageGroup"
            }
          },
          "reconciled": {
            "type": "boolean",
            "description": "true when `breakdown` sums to `totals` exactly (always, for `group_by=day`). false in the rare case the breakdown briefly exceeds the totals; `breakdown_note` then explains. Retry for a consistent report."
          },
          "breakdown_note": {
            "type": "string",
            "description": "Present only when `reconciled` is false."
          },
          "usage_stale": {
            "type": "boolean",
            "description": "true when usage counts may be incomplete for the most recent minutes. Money is always exact."
          },
          "usage_as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Usage counts are complete up to this instant (null when unknown)."
          }
        },
        "example": {
          "from": "2026-09-01T00:00:00Z",
          "to": "2026-09-08T00:00:00Z",
          "group_by": "model",
          "currency": "USD",
          "totals": {
            "requests": 105,
            "errors": 2,
            "input_tokens": 1500,
            "output_tokens": 700,
            "total_tokens": 2200,
            "cached_input_tokens": 40,
            "cache_write_tokens": 0,
            "reasoning_tokens": 0,
            "cost_nanousd": 3123456789,
            "cost_usd": "3.123456789",
            "units": [
              {
                "unit": "token",
                "requests": 105,
                "quantity_in": 1500,
                "quantity_out": 700,
                "cost_nanousd": 3123456789,
                "cost_usd": "3.123456789"
              }
            ]
          },
          "breakdown": [
            {
              "key": "openai/gpt-4o",
              "requests": 60,
              "errors": 0,
              "input_tokens": 1000,
              "output_tokens": 500,
              "total_tokens": 1500,
              "cached_input_tokens": 0,
              "cache_write_tokens": 0,
              "reasoning_tokens": 0,
              "cost_nanousd": 2000000000,
              "cost_usd": "2.00"
            },
            {
              "key": "other",
              "requests": 45,
              "errors": 2,
              "input_tokens": 500,
              "output_tokens": 200,
              "total_tokens": 700,
              "cached_input_tokens": 40,
              "cache_write_tokens": 0,
              "reasoning_tokens": 0,
              "cost_nanousd": 1123456789,
              "cost_usd": "1.123456789"
            }
          ],
          "reconciled": true,
          "usage_stale": false,
          "usage_as_of": "2026-09-24T09:59:15Z"
        }
      },
      "ExportTruncation": {
        "type": "object",
        "description": "The last line of an export stream that stopped before the end of the window.",
        "required": [
          "truncated",
          "rows",
          "reason"
        ],
        "properties": {
          "truncated": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "rows": {
            "type": "integer",
            "description": "Records written before the cut."
          },
          "reason": {
            "type": "string",
            "enum": [
              "row_cap",
              "upstream_error"
            ]
          }
        },
        "example": {
          "truncated": true,
          "rows": 10000,
          "reason": "row_cap"
        }
      },
      "UsageRecord": {
        "type": "object",
        "description": "One metered request. Counts, money and identifiers only — never content, error text or client address.",
        "properties": {
          "id": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "project_id": {
            "type": "string"
          },
          "key_id": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "unit": {
            "type": "string"
          },
          "input_tokens": {
            "type": "integer"
          },
          "output_tokens": {
            "type": "integer"
          },
          "total_tokens": {
            "type": "integer"
          },
          "cached_input_tokens": {
            "type": "integer"
          },
          "cache_write_tokens": {
            "type": "integer"
          },
          "reasoning_tokens": {
            "type": "integer"
          },
          "quantity_in": {
            "type": "integer",
            "description": "Native input quantity for non-token units (images, seconds …)."
          },
          "quantity_out": {
            "type": "integer"
          },
          "cost_nanousd": {
            "type": "integer"
          },
          "cost_usd": {
            "type": "string"
          },
          "cost_available": {
            "type": "boolean",
            "description": "false when this record's cost could not be read (cost fields are then 0, not a real zero)."
          },
          "latency_ms": {
            "type": "integer"
          },
          "streaming": {
            "type": "boolean"
          }
        }
      },
      "CatalogModelPricing": {
        "type": "object",
        "description": "Client list price of the model at the default region — the rate Token Factory bills the\norganization — as decimal strings in USD per **one** unit (no exponent, trailing zeros\ntrimmed, `\"0\"` for a real free component). The same object as `pricing` on the inference\nAPI's `GET /v1/models`. `unit` decides the fields: `token` (chat, embedding) → `prompt`,\n`completion`, `input_cache_read`, `input_cache_write` per token; `character` (TTS) →\n`prompt` per input character; `image` → `image_output` per image; `second` → `prompt` per\naudio second (STT) or `video_output` per video second (video); `document` (rerank) →\n`prompt` per document. A field appears only when the model has that rate (an embedding\nmodel has no `completion`; absent cache prices mean cache reads/writes bill at `prompt`).\nThe whole object is omitted when the price is unknown (no price row, or a row that cannot\nbe billed); never a guessed 0. Prices are the stored rate rounded once to nano-USD per 1M\nunits (token, character) or per unit; each request is billed from the exact rate with one\nrounding, so `prompt × tokens` can differ from the bill by under 1 nano-USD per 1M tokens.",
        "required": [
          "unit"
        ],
        "properties": {
          "unit": {
            "type": "string",
            "enum": [
              "token",
              "character",
              "image",
              "second",
              "document"
            ]
          },
          "prompt": {
            "type": "string",
            "pattern": "^[0-9]+(\\.[0-9]+)?$",
            "description": "USD per input token (token), input character (character), audio second (second, STT) or document (document)."
          },
          "completion": {
            "type": "string",
            "pattern": "^[0-9]+(\\.[0-9]+)?$",
            "description": "USD per output token."
          },
          "input_cache_read": {
            "type": "string",
            "pattern": "^[0-9]+(\\.[0-9]+)?$",
            "description": "USD per prompt-cache read token."
          },
          "input_cache_write": {
            "type": "string",
            "pattern": "^[0-9]+(\\.[0-9]+)?$",
            "description": "USD per prompt-cache write token."
          },
          "image_output": {
            "type": "string",
            "pattern": "^[0-9]+(\\.[0-9]+)?$",
            "description": "USD per generated image."
          },
          "video_output": {
            "type": "string",
            "pattern": "^[0-9]+(\\.[0-9]+)?$",
            "description": "USD per second of generated video (Token Factory field)."
          }
        },
        "additionalProperties": false
      },
      "CatalogModel": {
        "type": "object",
        "description": "One model the organization can call: the public model card (catalog ADR-0002 — the same\nobject the inference API's `GET /v1/models` returns per model, an OpenAI model object and an\nOpenRouter `/api/v1/models` entry in one) plus the Management-only fields `mode`, `status`,\n`capabilities` and `regions`. Optional card fields are omitted when the catalogue has no\nvalue; they are never estimated.\n\n**Changed in 0.16.1** (before the Management API reached production, so with no\ndeprecation window): the earlier `provider`, `max_completion_tokens`, `input_modalities`,\n`output_modalities` and `pricing.currency` / `pricing.rates` (per-1M rate map) were\nremoved. Read `architecture.input_modalities` / `output_modalities`, `max_output` (=\n`top_provider.max_completion_tokens`) and the per-unit `pricing` instead.",
        "required": [
          "id",
          "name",
          "object",
          "created",
          "owned_by",
          "architecture",
          "top_provider",
          "mode",
          "status",
          "capabilities",
          "regions"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The model name to send as `model` on the inference API (`provider/model`)."
          },
          "canonical_slug": {
            "type": "string",
            "description": "OpenRouter canonical slug (catalogue metadata)."
          },
          "hugging_face_id": {
            "type": "string",
            "description": "Hugging Face model id (catalogue metadata)."
          },
          "name": {
            "type": "string",
            "description": "Display name: the operator-set display name, else the `id`."
          },
          "object": {
            "type": "string",
            "const": "model"
          },
          "created": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix seconds the model was added to the catalogue."
          },
          "owned_by": {
            "type": "string",
            "const": "Token Factory"
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          },
          "context_length": {
            "type": "integer",
            "minimum": 1,
            "description": "Context window in tokens (OpenRouter name). Omitted when the catalogue has no value."
          },
          "context_window": {
            "type": "integer",
            "minimum": 1,
            "description": "Same value as `context_length` (product name)."
          },
          "max_output": {
            "type": "integer",
            "minimum": 1,
            "description": "Output-token ceiling (= `top_provider.max_completion_tokens`). Omitted when the catalogue has no value."
          },
          "architecture": {
            "type": "object",
            "required": [
              "modality",
              "input_modalities",
              "output_modalities"
            ],
            "properties": {
              "modality": {
                "type": "string",
                "examples": [
                  "text+image->text"
                ],
                "description": "`<in>+<in>-><out>`; authored, else derived from the lists."
              },
              "input_modalities": {
                "type": "array",
                "minItems": 1,
                "items": {
                  "type": "string"
                }
              },
              "output_modalities": {
                "type": "array",
                "minItems": 1,
                "items": {
                  "type": "string"
                }
              },
              "tokenizer": {
                "type": "string"
              },
              "instruct_type": {
                "type": "string"
              }
            },
            "additionalProperties": false
          },
          "pricing": {
            "$ref": "#/components/schemas/CatalogModelPricing"
          },
          "top_provider": {
            "type": "object",
            "description": "The model's limits as served. Never names a provider.",
            "required": [
              "is_moderated"
            ],
            "properties": {
              "context_length": {
                "type": "integer",
                "minimum": 1
              },
              "max_completion_tokens": {
                "type": "integer",
                "minimum": 1
              },
              "is_moderated": {
                "type": "boolean"
              }
            },
            "additionalProperties": false
          },
          "supported_parameters": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The operator-authored list when set, else (chat models only) derived from the catalogue capability flags. Sorted, unique."
          },
          "default_parameters": {
            "type": "object",
            "description": "Sampling defaults; only the listed keys, numeric values.",
            "properties": {
              "temperature": {
                "type": "number"
              },
              "top_p": {
                "type": "number"
              },
              "top_k": {
                "type": "number"
              },
              "frequency_penalty": {
                "type": "number"
              },
              "presence_penalty": {
                "type": "number"
              },
              "repetition_penalty": {
                "type": "number"
              },
              "min_p": {
                "type": "number"
              }
            },
            "additionalProperties": false
          },
          "supported_voices": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "TTS voices."
          },
          "knowledge_cutoff": {
            "type": "string"
          },
          "expiration_date": {
            "type": "string",
            "description": "Announced end-of-service date, when one is set."
          },
          "mode": {
            "type": "string",
            "description": "Management API field: the catalog mode — chat, embedding, image, tts, stt, video, rerank."
          },
          "status": {
            "type": "string",
            "description": "Management API field: provisioning status of the model, lowercased (e.g. `ready`)."
          },
          "capabilities": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            },
            "description": "Management API field: catalog capability flags, boolean only, e.g. `{\"vision\": true, \"tools\": true}`."
          },
          "regions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Management API field: regions the model is served and priced in (`[\"default\"]` today; `pricing` is the default-region price)."
          }
        },
        "additionalProperties": false,
        "example": {
          "id": "openai/gpt-4o",
          "name": "GPT-4o",
          "object": "model",
          "created": 1715558400,
          "owned_by": "Token Factory",
          "description": "OpenAI's multimodal flagship.",
          "context_length": 128000,
          "context_window": 128000,
          "max_output": 16384,
          "architecture": {
            "modality": "text+image->text",
            "input_modalities": [
              "text",
              "image"
            ],
            "output_modalities": [
              "text"
            ]
          },
          "pricing": {
            "unit": "token",
            "prompt": "0.0000025",
            "completion": "0.00001",
            "input_cache_read": "0.00000125"
          },
          "top_provider": {
            "context_length": 128000,
            "max_completion_tokens": 16384,
            "is_moderated": false
          },
          "supported_parameters": [
            "max_tokens",
            "stop",
            "temperature",
            "tool_choice",
            "tools",
            "top_p"
          ],
          "knowledge_cutoff": "2023-10",
          "mode": "chat",
          "status": "ready",
          "capabilities": {
            "vision": true,
            "tools": true
          },
          "regions": [
            "default"
          ]
        }
      },
      "CatalogRegion": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "model_count": {
            "type": "integer"
          }
        }
      },
      "Token": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "Masked, e.g. tf-pat_AbCdE...a91f."
          },
          "scopes": {
            "type": "array",
            "description": "The scopes the token was created with (see `Scope`).",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "revoked"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_by": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "email": {
                "type": "string"
              }
            }
          }
        }
      },
      "Scope": {
        "type": "string",
        "enum": [
          "org:read",
          "org:write",
          "members:read",
          "members:write",
          "projects:read",
          "projects:write",
          "keys:read",
          "keys:write",
          "usage:read",
          "billing:read",
          "audit:read",
          "catalog:read"
        ],
        "description": "Personal access token scopes. `org:write`, `members:write`, `projects:write` are sensitive."
      }
    }
  }
}
