{
  "openapi": "3.1.0",
  "info": {
    "title": "Stackure API",
    "summary": "Passwordless auth for B2B apps.",
    "version": "1.0.0",
    "description": "Two APIs. The Sign-in API under `/api/public` signs people in to your apps. The Management API under `/api/internal` runs your organization without the web app.\n\nEach region is its own deployment with its own base URL. Use the region where your organization was created.\n\nBodies are JSON unless an operation says otherwise. Send them with `Content-Type: application/json`. Parameters such as `charset` are fine. Each deployment sets the largest JSON body it takes, 1 MB by default. A larger body returns 400 `request too large`. An empty list is `[]`. User, team, app, organization, signup, support request and AI client connection IDs are UUIDs. An ID that isn't one returns 400. Errors look like `{\"error\": \"<message>\"}`. A method an endpoint doesn't support returns 405 `method not allowed`.\n\nPaged lists take `cursor` and `limit`. The `X-Next-Cursor` response header holds the cursor for the next page and is absent on the last one."
  },
  "servers": [
    {
      "url": "/",
      "description": "The region serving this file"
    }
  ],
  "security": [
    {
      "platformSession": [

      ]
    },
    {
      "platformSessionCookie": [

      ]
    }
  ],
  "tags": [
    {
      "name": "Sign-in API",
      "description": "Sign people in to your app, check their sessions and connect AI clients. Each operation lists the credentials it takes:\n\n- `X-App-Secret`: your app's secret, on calls your server makes for your app.\n- A session token as `Authorization: Bearer <token>` or a `session` cookie. Session checks and the directory take the app session token your app got when the person signed in. Sign-out takes that or a platform session token.\n- An AI client's access token as `Authorization: Bearer <token>`, on session checks that carry the `mcp` parameter.\n- `X-Org-Secret`: the parent organization's secret, on signups.\n\nExchanging a sign-in token and the MCP endpoints take none. The MCP endpoints follow OAuth 2.1 for public clients: no client secret, PKCE with `S256`."
    },
    {
      "name": "Management API",
      "description": "Run your organization without the web app: users, teams, roles, permissions, apps and their secrets, partners, partner signups, AI access, AI clients, support requests and activity. You can also transfer ownership, rotate your organization's secret and see its limits. The signup list shows each organization's name, status and date. `GET /api/internal/signup` shows one signup in full.\n\nEvery call needs a platform session token as `Authorization: Bearer <token>` or a `session` cookie. When you send both, the cookie is used. To get a token, request a sign-in link with `POST /api/public/auth/magic-link/send` without `app_id`, take the `token` from the link in the email and exchange it at `POST /api/public/auth/magic-link/verify`. The token ends when it expires, when you sign out or when you sign in again, since each person has one session at a time. Request a new link when calls return 401 `invalid session`.\n\nApp session tokens and AI client tokens don't work here.\n\n- No token: 401 `missing authorization header`.\n- A token that isn't a live platform session: 401 `invalid session`.\n- Your organization's access has expired: 403 `forbidden` on every call except your own support requests. You can still send them to the organization above yours, list them and read them with `/api/internal/support-requests` and `/api/internal/support-request`.\n\nWhat you can see and change depends on your roles."
    }
  ],
  "paths": {
    "/api/public/signup": {
      "post": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "Apply for an organization",
        "operationId": "submitSignup",
        "description": "Applies for a new organization under a parent organization. The parent's approvers and the applicant each get an email.\n\nYou get the same 200 when a signup with this email or organization name is already waiting or the email already belongs to a user. The applicant then gets an email saying why it can't go ahead.\n\nRate limited per email and IP address.",
        "security": [
          {
            "orgSecret": [

            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signup received.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignupReceived"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "`invalid org secret`: `X-Org-Secret` is missing or doesn't match the parent organization. An unknown `parent_id` gets the same 401, so the response doesn't reveal which organizations exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/auth/magic-link/send": {
      "post": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "Send a sign-in link",
        "operationId": "sendSignInLink",
        "description": "Emails a sign-in link if the email belongs to a user. The response is the same either way.\n\nWith `app_id`, also send your app's secret in `X-App-Secret`. The link then signs the person in to your app.\n\nWithout `app_id`, every request gets 200 unless its JSON is invalid, its `Content-Type` is wrong or it's rate limited.",
        "security": [
          {
          },
          {
            "appSecret": [

            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MagicLinkSendRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Request handled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MagicLinkSendResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "`invalid app secret`: you sent `app_id` and `X-App-Secret` is missing or wrong.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/auth/magic-link/verify": {
      "post": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "Exchange a sign-in token",
        "operationId": "verifySignInToken",
        "description": "Exchanges the `token` from a sign-in link for a session token. A link requested without `app_id` gives a platform session token for the Management API. A link requested with `app_id` gives a session token for that app.\n\nIf the organization's access has expired, a link requested without `app_id` gives `token_scope` `support_only`: the session can only contact support, and `redirect_url` points to the support page. A link requested with `app_id` returns 403 `forbidden` instead.\n\nLinks that connect an AI client don't work here.",
        "security": [

        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MagicLinkVerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signed in.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MagicLinkVerifyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "`token invalid` when the token isn't 64 characters. `authentication failed` when the link is unknown, used, expired or connects an AI client.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden`: the link was for an app the person can't open, or their organization's access has expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "description": "`too many verification attempts` from this IP address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/auth/session/validate": {
      "get": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "Check a session",
        "operationId": "validateSession",
        "description": "Tells your server who is signed in to your app. Call it from your server on every protected request.\n\nSend your app's secret in `X-App-Secret` and the person's app session token as `Authorization: Bearer <token>` or a `session` cookie. A missing, expired or signed-out token returns `authenticated: false` with a `sign_in_url`.\n\nFor an MCP endpoint, add `mcp` and forward the AI client's `Authorization: Bearer` credential. When the client isn't signed in, the response adds `www_authenticate`: answer the client with 401 and that value, unchanged, as the `WWW-Authenticate` header.\n\nRate limited per app. Failed calls are also limited per app and IP address, 10 a minute by default. Past that, a failed call returns 429 with `Retry-After: 60` instead of its error.",
        "security": [
          {
            "appSecret": [

            ],
            "appSession": [

            ]
          },
          {
            "appSecret": [

            ],
            "appSessionCookie": [

            ]
          },
          {
            "appSecret": [

            ],
            "mcpCredential": [

            ]
          },
          {
            "appSecret": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "app_id",
            "in": "query",
            "required": true,
            "description": "Your app's ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "mcp",
            "in": "query",
            "required": false,
            "description": "The public URL of your MCP endpoint the request arrived at, with no query string. When present, the token is checked as an AI client credential for your app.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The session's state.",
            "headers": {
              "Cache-Control": {
                "description": "`no-store` when `authenticated` is `true`. Not sent otherwise.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionValidation"
                }
              }
            }
          },
          "400": {
            "description": "`app_id required` or `invalid app_id format`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "`invalid app secret`: `X-App-Secret` is missing or wrong.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/directory/users": {
      "get": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "List who can open your app",
        "operationId": "listDirectoryUsers",
        "description": "Lists the users in the signed-in person's organization who can open your app, for pickers and sharing. Sorted by first name, then last name. `q` matches name, email and job title.\n\nWe define no permissions inside your app. You decide what these users and teams may do.\n\nSend `X-App-Secret` and the person's app session token as `Authorization: Bearer <token>` or a `session` cookie. AI client credentials aren't accepted. Rate limited per app. Failed calls are also limited per app and IP address, 10 a minute by default. Past that, a failed call returns 429 with `Retry-After: 60` instead of its error.",
        "security": [
          {
            "appSecret": [

            ],
            "appSession": [

            ]
          },
          {
            "appSecret": [

            ],
            "appSessionCookie": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "app_id",
            "in": "query",
            "required": true,
            "description": "Your app's ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Only these IDs, for checking or naming people or teams you already have. Repeat it for up to 200.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "maxItems": 200,
              "items": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of users.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              },
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DirectoryUser"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid app_id format` when `app_id` is missing or isn't a UUID, `invalid input: q`, `invalid input: limit`, `invalid input: cursor` or `invalid input: id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "`invalid app secret` when `X-App-Secret` is missing or wrong. `invalid session` when there's no live session for this app.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/directory/teams": {
      "get": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "List teams that have your app",
        "operationId": "listDirectoryTeams",
        "description": "Lists the teams in the signed-in person's organization that have your app, for pickers and sharing: every team when the app is available to everyone, otherwise the teams it's shared with. Sorted by name. `q` matches the team name.\n\nWe define no permissions inside your app. You decide what these users and teams may do.\n\nSend `X-App-Secret` and the person's app session token as `Authorization: Bearer <token>` or a `session` cookie. AI client credentials aren't accepted. Rate limited per app. Failed calls are also limited per app and IP address, 10 a minute by default. Past that, a failed call returns 429 with `Retry-After: 60` instead of its error.",
        "security": [
          {
            "appSecret": [

            ],
            "appSession": [

            ]
          },
          {
            "appSecret": [

            ],
            "appSessionCookie": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "app_id",
            "in": "query",
            "required": true,
            "description": "Your app's ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Only these IDs, for checking or naming people or teams you already have. Repeat it for up to 200.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "maxItems": 200,
              "items": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of teams.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              },
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SDKTeam"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid app_id format` when `app_id` is missing or isn't a UUID, `invalid input: q`, `invalid input: limit`, `invalid input: cursor` or `invalid input: id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "`invalid app secret` when `X-App-Secret` is missing or wrong. `invalid session` when there's no live session for this app.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/auth/sign-out": {
      "post": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "Sign out",
        "operationId": "signOut",
        "description": "Signs the person out everywhere. Every session on every app and device ends. Their AI clients are disconnected.\n\nSend a platform or app session token as `Authorization: Bearer <token>` or a `session` cookie. You get 200 even when the token is missing or no longer valid.",
        "security": [
          {
            "platformSession": [

            ]
          },
          {
            "platformSessionCookie": [

            ]
          },
          {
            "appSession": [

            ]
          },
          {
            "appSessionCookie": [

            ]
          },
          {
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `signed out successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/auth/mcp/token": {
      "post": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "Get an AI client token",
        "operationId": "mcpToken",
        "description": "The OAuth token endpoint for AI clients connecting over MCP, to us or to your app.\n\nThe authorize step is `GET /mcp/authorize` for our MCP server or `GET /mcp/{app_id}/authorize` for your app. Clients find every OAuth URL at `/.well-known/oauth-authorization-server/mcp` or `/.well-known/oauth-authorization-server/mcp/{app_id}`.\n\n- `authorization_code` redeems the code from the authorize step with its PKCE `code_verifier`.\n- `refresh_token` returns a new access token and refresh token. Always use the newest refresh token. Reusing an old one can end the connection.\n\nAccess ends when the person signs out, disconnects the client or loses access. It also ends after a period without use.",
        "security": [

        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/MCPTokenRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tokens issued.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MCPTokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "`error` is `unsupported_grant_type`, `invalid_grant`, `invalid_client` or `invalid_target`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "`too many requests, please try again later`: the connection holds too many live access tokens.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/auth/mcp/register": {
      "post": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "Register an AI client",
        "operationId": "mcpRegister",
        "description": "OAuth dynamic client registration for AI clients. Returns the `client_id` to use at the authorize and token steps. Rate limited per IP address. This endpoint sets its own body limit, 16 KB by default. A larger body returns 400 `invalid_client_metadata`.\n\nEach redirect URI must be one of these:\n\n- HTTPS with a lowercase host\n- `http` on `localhost` or `127.0.0.1`\n- A custom URL scheme for a native app",
        "security": [

        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MCPRegisterRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client registered.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MCPRegisterResponse"
                }
              }
            }
          },
          "400": {
            "description": "`error` is `invalid_client_metadata` or `invalid_redirect_uri`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/public/auth/mcp/revoke": {
      "post": {
        "tags": [
          "Sign-in API"
        ],
        "summary": "Revoke an AI client token",
        "operationId": "mcpRevoke",
        "description": "OAuth token revocation. A live access token or refresh token ends its whole connection. You get 200 and `{}` whether or not the token was valid.",
        "security": [

        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/MCPRevokeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "maxProperties": 0
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/users": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List users",
        "operationId": "listUsers",
        "description": "Users in your organization you can see, sorted by first name, then last name.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of users.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/UserListItem"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Invite users",
        "operationId": "inviteUsers",
        "description": "Adds people to your organization. Each new user gets an email with a link to sign in.\n\n201 when at least 1 user was created and none failed. 207 when any failed. 409 when every user already exists. `details` has one entry per person.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "minItems": 1,
                "items": {
                  "$ref": "#/components/schemas/InviteUser"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Users created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteResult"
                }
              }
            }
          },
          "207": {
            "description": "Some or all failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteResult"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json` when the body isn't a JSON array of users, `no users to invite` or `bulk operation failed, all users must have valid data` when no entry is valid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "Every user already exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteResult"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/user": {
      "parameters": [
        {
          "$ref": "#/components/parameters/UserId"
        }
      ],
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a user",
        "operationId": "getUser",
        "responses": {
          "200": {
            "description": "The user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDetail"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: user_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "tags": [
          "Management API"
        ],
        "summary": "Update a user",
        "operationId": "updateUser",
        "description": "Changes only the fields you send. An empty value leaves that field as it is. You can change `user_timezone` only for yourself.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `user updated successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: user_id` when it's missing or isn't a UUID, `invalid json`, `input too long` when `user_first_name`, `user_last_name` or `user_position` is over 100 characters, `invalid input: user_first_name`, `invalid input: user_last_name` or `invalid input: user_position` when that field has a control character such as a line break, `invalid email` when `user_email` isn't a valid address of 255 characters or fewer or `invalid timezone` when `user_timezone` isn't an IANA time zone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden`: your roles don't allow this, you sent `user_timezone` for someone else or your organization's access has expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`email already exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Delete a user",
        "operationId": "deleteUser",
        "description": "You can't delete yourself, the owner or a team's last admin.",
        "responses": {
          "200": {
            "description": "`message` is `user deleted successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: user_id` when it's missing or isn't a UUID, `cannot delete self`, `cannot delete account owner` or `cannot delete the last admin of a team`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/user/apps": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List a user's apps",
        "operationId": "listUserApps",
        "description": "Apps the user can open that you can see, sorted by name. 403 when you can't see apps.",
        "parameters": [
          {
            "$ref": "#/components/parameters/UserId"
          }
        ],
        "responses": {
          "200": {
            "description": "The user and their apps. `user` has only `user_id`, `user_first_name` and `user_last_name` filled in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "user",
                    "apps"
                  ],
                  "properties": {
                    "user": {
                      "$ref": "#/components/schemas/User"
                    },
                    "apps": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/App"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: user_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/user/teams": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List a user's teams",
        "operationId": "listUserTeams",
        "description": "Teams the user is on that you can see, sorted by name. 403 when you can't see teams.",
        "parameters": [
          {
            "$ref": "#/components/parameters/UserId"
          }
        ],
        "responses": {
          "200": {
            "description": "The user and their teams. `user` has only `user_id`, `user_first_name` and `user_last_name` filled in. `teams` is `[]` when there are none.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "user",
                    "teams"
                  ],
                  "properties": {
                    "user": {
                      "$ref": "#/components/schemas/User"
                    },
                    "teams": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Team"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: user_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/user/access": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a user's roles and permissions",
        "operationId": "getUserAccess",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "User ID. Leave it out for yourself.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The user's roles and what each one allows.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserAccess"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: user_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/user/roles": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Give roles to a user",
        "operationId": "grantUserRoles",
        "description": "Gives the user every role in `roles`. You can't give `account_owner`: transfer ownership instead.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRolesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `roles assigned to ` followed by the `user_email` you sent, trimmed and lowercased, or else the `user_id` you sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: user_id` when you send neither `user_id` nor `user_email` or `user_id` isn't a UUID, `invalid email` when `user_email` isn't a valid address of 255 characters or fewer, `role required` when `roles` is empty, or `invalid input: roles` when a role key isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`user not found for role` or `role not found: ` followed by the unknown role keys.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Remove a role from a user",
        "operationId": "revokeUserRole",
        "parameters": [
          {
            "$ref": "#/components/parameters/UserId"
          },
          {
            "$ref": "#/components/parameters/RoleKey"
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `role revoked from user`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: user_id` when it's missing or isn't a UUID. `invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`role not found` or `user does not hold this role`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/user/ai-clients": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List a user's AI clients",
        "operationId": "listUserAIClients",
        "description": "Live AI client connections, newest first. To see another user's connections, you need permission to edit that user.",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "User ID. Leave it out for yourself.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The connections.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIClients"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: user_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Disconnect an AI client",
        "operationId": "disconnectUserAIClient",
        "description": "Ends one AI client connection. To end another user's connection, you need permission to edit that user.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AIClientDisconnect"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Disconnected.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "disconnected"
                  ],
                  "properties": {
                    "disconnected": {
                      "type": "boolean",
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: user_id` or `invalid input: connection_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`connection not found`, also when you aren't allowed to end it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/roles": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List roles",
        "operationId": "listRoles",
        "description": "Default roles and your organization's custom roles, sorted by name. Needs permission to edit users.",
        "responses": {
          "200": {
            "description": "The roles.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Role"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/role": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a role",
        "operationId": "getRole",
        "description": "Needs permission to edit users.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoleKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The role, with `user_count` when anyone holds it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Role"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Create a role",
        "operationId": "createRole",
        "description": "Creates a custom role for your organization. Add permissions to it with `POST /api/internal/role/permissions`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `custom role created: ` followed by the role name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores, `role_name required` when `role_name` is missing or blank or `input too long` when `role_name` is over 100 characters or `role_description` is over 500.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`role already exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "tags": [
          "Management API"
        ],
        "summary": "Update a role",
        "operationId": "updateRole",
        "description": "Renames a custom role or changes its description. Fields you leave out stay as they are.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `custom role updated successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores, `invalid input: nothing to change` when neither `role_name` nor `role_description` is sent, `role_name required` when `role_name` is blank or `input too long` when `role_name` is over 100 characters or `role_description` is over 500.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Delete a role",
        "operationId": "deleteRole",
        "description": "Deletes a custom role. Default roles can't be deleted.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoleKey"
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `custom role deleted successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/permissions": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List permissions",
        "operationId": "listPermissions",
        "description": "Every permission you can put in a role, sorted by name. Needs permission to edit users.",
        "responses": {
          "200": {
            "description": "The permissions. Each has only `permission_key` and `permission_name`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Permission"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/permission": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a permission",
        "operationId": "getPermission",
        "description": "Needs permission to edit users. Without it you get 404.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PermissionKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The permission, with how many roles have it and how many users you can see hold it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Permission"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: permission_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/role/permissions": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List a role's permissions",
        "operationId": "listRolePermissions",
        "description": "Needs permission to edit users.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoleKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The role's permissions, sorted by name, each with only `permission_key` and `permission_name`. `[]` when the role has none.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Permission"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Add permissions to a role",
        "operationId": "addRolePermissions",
        "description": "Adds permissions to a custom role, along with any view permissions they need.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RolePermissionsChange"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `permissions added successfully`. When view permissions were added too, it goes on with `; also added the view permissions they need: ` and their keys.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores, `permission required` when `permission_keys` is empty or `invalid input: permission_keys` when one of them isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`role not found` or `permission not found: ` followed by the unknown keys.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Remove permissions from a role",
        "operationId": "removeRolePermissions",
        "description": "Removes permissions from a custom role. This one takes a JSON body.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RolePermissionsChange"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `permissions removed successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores, `permission required` when `permission_keys` is empty or `invalid input: permission_keys` when one of them isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`role not found`, `permission not found` or `permission not found: ` followed by the unknown keys.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`another permission in this role requires it`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/role/users": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List users with a role",
        "operationId": "listRoleUsers",
        "description": "Users with the role that you can see. Needs permission to edit users.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RoleKey"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The role and one page of its users. `users` is `[]` when there are none.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleUsers"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: role_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores, `invalid input: q`, `invalid input: limit` or `invalid input: cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/permission/roles": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List roles with a permission",
        "operationId": "listPermissionRoles",
        "description": "Default roles first, then your custom roles. Needs permission to edit users. You get 404 without it or when no role has the permission.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PermissionKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The permission and its roles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermissionRoles"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: permission_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/permission/users": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List users with a permission",
        "operationId": "listPermissionUsers",
        "description": "Users you can see who hold the permission through any role. Needs permission to edit users. Without it you get 404.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PermissionKey"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The permission and one page of users. `users` is `[]` when there are none.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermissionUsers"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: permission_key` when it's missing or isn't 1 to 100 lowercase letters, digits or underscores, `invalid input: q`, `invalid input: limit` or `invalid input: cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/teams": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List teams",
        "operationId": "listTeams",
        "description": "Teams you can see, sorted by name. If you can assign partners to teams, you also get every other team by name only.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "`empty` lists only teams with at most 1 member that you can add people to.",
            "schema": {
              "type": "string",
              "enum": [
                "empty"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of teams.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TeamListItem"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/team": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a team",
        "operationId": "getTeam",
        "description": "Returns the team and its counts. For members and what you can do with them, use `GET /api/internal/team/members`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamId"
          }
        ],
        "responses": {
          "200": {
            "description": "The team. `team_members` is left out.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamDetail"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: team_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Create a team",
        "operationId": "createTeam",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `team created successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamCreated"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `team_name required`, `input too long` when `team_name` is over 255 characters, `team_admin_id required` or `team admin invalid` when `team_admin_id` isn't a person in your organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden`, `team quota exceeded` or `team membership quota exceeded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`team already exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "tags": [
          "Management API"
        ],
        "summary": "Update a team",
        "operationId": "updateTeam",
        "description": "Changes the name or settings. Change admins with `PUT /api/internal/team/member`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `team updated successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: team_id` or `input too long` when `team_name` is over 255 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`team not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`team already exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Delete a team",
        "operationId": "deleteTeam",
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamId"
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `team deleted successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: team_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/team/members": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List team members",
        "operationId": "listTeamMembers",
        "description": "The team and one page of its members, sorted by first name, then last name.",
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamId"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The team with `team_members`. `team_app_count` and `team_managed_partner_count` are left out here. `team_members` is `[]` when no member matches.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamDetail"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: team_id` when it's missing or isn't a UUID, `invalid input: q`, `invalid input: limit` or `invalid input: cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Add team members",
        "operationId": "addTeamMembers",
        "description": "Adds people from your organization to the team. 200 when none failed, 207 when any did. `details` has one entry per ID.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddTeamMembersRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `team members added successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddTeamMembersResult"
                }
              }
            }
          },
          "207": {
            "description": "Some or all failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddTeamMembersResult"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: team_id`, `required parameters missing` when `member_ids` is empty or `invalid input: member_ids` when one of them isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`team not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/team/member": {
      "parameters": [
        {
          "$ref": "#/components/parameters/TeamId"
        },
        {
          "$ref": "#/components/parameters/UserId"
        }
      ],
      "put": {
        "tags": [
          "Management API"
        ],
        "summary": "Make or remove a team admin",
        "operationId": "setTeamAdmin",
        "description": "Makes a member a team admin or removes their admin role. A team always keeps at least 1 admin.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamAdminChange"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `team admin added` or `team admin removed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: team_id` or `invalid input: user_id` when that parameter is missing or isn't a UUID. `invalid json` or `cannot remove the last admin of a team`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`user not found`: the user isn't on this team.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`team admin unchanged`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Remove a team member",
        "operationId": "removeTeamMember",
        "responses": {
          "200": {
            "description": "`message` is `team member removed successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: team_id` or `invalid input: user_id` when that parameter is missing or isn't a UUID. `cannot remove the last admin of a team`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not found` or `user is not a member of this team`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/team/apps": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List a team's apps",
        "operationId": "listTeamApps",
        "description": "Apps shared with the team that you can see, sorted by name. 403 when you can't see apps.",
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamId"
          }
        ],
        "responses": {
          "200": {
            "description": "The team and its apps. `team` has only `team_id` and `team_name`. `apps` is `[]` when there are none.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "team",
                    "apps"
                  ],
                  "properties": {
                    "team": {
                      "$ref": "#/components/schemas/Team"
                    },
                    "apps": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/App"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: team_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/team/partners": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List a team's partners",
        "operationId": "listTeamPartners",
        "description": "Partner organizations the team manages, sorted by name.",
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamId"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of partners.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Organization"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: team_id` when it's missing or isn't a UUID, `invalid input: q`, `invalid input: limit` or `invalid input: cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/team/partner": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Assign a partner to a team",
        "operationId": "assignTeamPartner",
        "description": "The team then manages that partner organization.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamPartnerAssign"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `partner assigned to team successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: team_id` or `invalid input: partner_account_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`team not found` or `account not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`already exists`: the team already manages this partner.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Unassign a partner from a team",
        "operationId": "unassignTeamPartner",
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamId"
          },
          {
            "$ref": "#/components/parameters/PartnerAccountId"
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `partner unassigned from team successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: team_id` or `invalid input: partner_account_id` when that parameter is missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`partner not found` or `team not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/apps": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List apps",
        "operationId": "listApps",
        "description": "Apps your organization registered or received that you can see, sorted by name.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "`organization`: available to everyone. `unassigned` or `undistributed`: not yet available to everyone or any team. `received`: shared with your organization by another one.",
            "schema": {
              "type": "string",
              "enum": [
                "organization",
                "unassigned",
                "undistributed",
                "received"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of apps. Each has `app_id`, `account_id`, `app_name`, `app_url`, `app_logo`, `app_logo_type` and `share_state` filled in.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/App"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not found`: `state=unassigned` with no `q` or `cursor` found nothing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/app": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get an app",
        "operationId": "getApp",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          }
        ],
        "responses": {
          "200": {
            "description": "The app and what you can do with it.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "app"
                  ],
                  "properties": {
                    "app": {
                      "$ref": "#/components/schemas/AppDetail"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Register an app",
        "operationId": "createApp",
        "description": "Registers an app for your organization. The response is the only time you see `app_secret`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `app registered successfully`.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppCreated"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden` or `app quota exceeded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`app already exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "tags": [
          "Management API"
        ],
        "summary": "Update an app",
        "operationId": "updateApp",
        "description": "Changes only the fields you send. Send at least 1.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `app updated successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID, `invalid json`, `input too long` when `app_name` is over 255 characters, `invalid app url`, `invalid app mcp url` or `required parameters missing` when nothing changes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`app already exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Delete an app",
        "operationId": "deleteApp",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `app deleted successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/app/secret": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Rotate an app secret",
        "operationId": "rotateAppSecret",
        "description": "Creates a new secret for an app your organization registered. The old one stops working at once, so every SDK still using it fails until you update it. The response is the only time you see the new one. Needs permission to edit the app.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          }
        ],
        "responses": {
          "200": {
            "description": "The new secret.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "app_secret"
                  ],
                  "properties": {
                    "app_secret": {
                      "type": "string",
                      "minLength": 64,
                      "maxLength": 64
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/app/teams": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List an app's teams",
        "operationId": "listAppTeams",
        "description": "Teams in your organization the app is shared with, sorted by name.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The app and one page of teams. `app` has only `app_id` and `app_name`.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppTeams"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID, `invalid input: q`, `invalid input: limit` or `invalid input: cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/app/users": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List who can open an app",
        "operationId": "listAppUsers",
        "description": "People you can see who can open an app your organization registered. App admins can open every app. Others get it through a team. `users` is empty when the app is available to everyone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The app and one page of users. `app` has only `app_id` and `app_name`.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppUsers"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID, `invalid input: q`, `invalid input: limit` or `invalid input: cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`app not found`, also for apps your organization received from another one.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/app/partners": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List an app's partners",
        "operationId": "listAppPartners",
        "description": "Partner organizations you can see that an app your organization registered is shared with, sorted by name.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The app and one page of partners. `app` has only `app_id` and `app_name`.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppPartners"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID, `invalid input: q`, `invalid input: limit` or `invalid input: cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`app not found`, also for apps your organization received from another one.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/app/account": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Make an app available to everyone",
        "operationId": "shareAppWithEveryone",
        "description": "Everyone in your organization can then open the app.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppShareEveryone"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `app shared with account successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: app_id` or `invalid input` when `account_id` isn't your organization's ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`app not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`app already shared with the organization`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Stop sharing an app with everyone",
        "operationId": "unshareAppFromEveryone",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          },
          {
            "name": "account_id",
            "in": "query",
            "required": false,
            "description": "Your organization's ID. Any other value returns 400.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `app unshared from account successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID. `invalid input` when `account_id` isn't your organization's ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`app not found` or `app is not shared there`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/app/team": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Share an app with a team",
        "operationId": "shareAppWithTeam",
        "description": "Members of the team can then open the app.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppShareTeam"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `app shared with team successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: app_id` or `invalid input: team_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`app not found` or `team not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Stop sharing an app with a team",
        "operationId": "unshareAppFromTeam",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          },
          {
            "$ref": "#/components/parameters/TeamId"
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `app unshared from team successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` or `invalid input: team_id` when that parameter is missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`app not found` or `app is not shared there`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/app/partner": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Share an app with a partner",
        "operationId": "shareAppWithPartner",
        "description": "Shares an app your organization registered with a partner organization. Its members see the app only after its app admins distribute it.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppSharePartner"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `app shared with account successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`. `invalid input: app_id` when it's missing or isn't a UUID. `invalid input: partner_id` when `partner_id` is missing, your own organization or not a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`app not found` or `partner not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Management API"
        ],
        "summary": "Stop sharing an app with a partner",
        "operationId": "unshareAppFromPartner",
        "parameters": [
          {
            "$ref": "#/components/parameters/AppId"
          },
          {
            "$ref": "#/components/parameters/PartnerAccountId"
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `app unshared from account successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: app_id` when it's missing or isn't a UUID. `invalid input: partner_account_id` when it's missing, your own organization or not a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`app not found`, `partner not found` or `app is not shared there`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/partners": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List partners",
        "operationId": "listPartners",
        "description": "Partner organizations directly below yours that you can see.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "`active` (the default) sorts by name. `expiring` lists partners close to expiry, soonest first. `closed` lists closed partners, most recently closed first. It needs permission to see every partner.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "expiring",
                "closed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of partners.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PartnerListItem"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/partner": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a partner",
        "operationId": "getPartner",
        "description": "A partner organization directly below yours, open or closed.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PartnerId"
          }
        ],
        "responses": {
          "200": {
            "description": "The partner. `total_available_apps` counts the apps your organization shared with it that you can see. A closed partner has no owner or totals. Its `account_updated` is when it closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerDetail"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: partner_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/partner/close": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Close a partner",
        "operationId": "closePartner",
        "description": "Closes a partner organization and removes everything under it. This is final.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PartnerId"
          }
        ],
        "responses": {
          "200": {
            "description": "`message` is `partner closed successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: partner_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/partner/expiry": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Extend a partner's expiry",
        "operationId": "extendPartnerExpiry",
        "description": "Moves a partner organization's expiry to a later date.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PartnerId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartnerExpiryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `partner expiry extended successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json` or `invalid input: partner_id` when it's missing or isn't a UUID. `extension must be between 1 and 3 months` when `target_expiry_date` is missing, isn't `YYYY-MM-DD` or isn't later than both today and the current expiry. `extension would exceed maximum allowed expiry date` when it's more than 90 days from now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The expiry can't be extended yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/partner/apps": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List apps shared with a partner",
        "operationId": "listPartnerApps",
        "description": "Apps your organization shared with the partner that you can see, sorted by name. `share_state` shows how far the partner has distributed each one.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PartnerId"
          }
        ],
        "responses": {
          "200": {
            "description": "The partner's name and its apps.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerApps"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: partner_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/partner/limits": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a partner's limits",
        "operationId": "getPartnerLimits",
        "parameters": [
          {
            "$ref": "#/components/parameters/PartnerId"
          }
        ],
        "responses": {
          "200": {
            "description": "The partner's plan, limits and use.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Limits"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: partner_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/partner/teams": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List teams managing a partner",
        "operationId": "listPartnerTeams",
        "description": "Teams in your organization that manage the partner, sorted by name.",
        "parameters": [
          {
            "$ref": "#/components/parameters/PartnerId"
          }
        ],
        "responses": {
          "200": {
            "description": "The teams.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ManagingTeam"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: partner_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/signups": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List signups",
        "operationId": "listSignups",
        "description": "Signups for new organizations under yours, newest first. Needs permission to see signups.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Leave it out or send `all` for every signup.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "pending",
                "rejected"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of signups.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SignupListItem"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/signup": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a signup",
        "operationId": "getSignup",
        "description": "One signup for a new organization under yours, with who sent it and what stops its approval. Needs permission to see signups.",
        "parameters": [
          {
            "name": "signup_id",
            "in": "query",
            "required": true,
            "description": "Signup ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The signup.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignupDetail"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: signup_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`signup not found`, also when you can't see it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/signup/approve": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Approve a signup",
        "operationId": "approveSignup",
        "description": "Creates the organization and its owner.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignupDecision"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The new organization and its owner.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignupApproved"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json` or `invalid input: signup_id` when it's missing or isn't a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden` or `subaccount quota exceeded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`email already exists`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/support-requests": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List support requests",
        "operationId": "listSupportRequests",
        "description": "Support requests you sent, newest first. With `box` set to `inbox`, the requests that organizations directly below yours sent to your organization. The inbox needs permission to see every partner, in an organization that isn't a subpartner. While your organization's access has expired you can list only your own requests. `inbox` gets 403.",
        "parameters": [
          {
            "name": "box",
            "in": "query",
            "required": false,
            "description": "`mine` for requests you sent. `inbox` for requests sent to your organization.",
            "schema": {
              "type": "string",
              "enum": [
                "mine",
                "inbox"
              ],
              "default": "mine"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Leave it out for every status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "responded",
                "closed"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Leave it out for every type.",
            "schema": {
              "type": "string",
              "enum": [
                "Account & Billing",
                "Access",
                "Integration",
                "Quota",
                "Bug Report",
                "Feature Request",
                "Other"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Search text. Every word must match the subject, type or organization name.",
            "schema": {
              "type": "string",
              "maxLength": 256
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of support requests.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              },
              "X-Total-Count": {
                "$ref": "#/components/headers/TotalCount"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SupportRequestListItem"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Send a support request",
        "operationId": "createSupportRequest",
        "description": "Sends a support request from you to the organization directly above yours. It replies by email. You can send up to 5 in 1 hour. This works while your organization's access has expired.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SupportRequestCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The new request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "support_request_id",
                    "status"
                  ],
                  "properties": {
                    "support_request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "const": "pending"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`. `invalid input` when `request_type` isn't one of the types, `subject` is under 3 characters or `message` is under 10. `input too long` when `subject` is over 150 characters or `message` is over 5000.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "description": "`too many requests, please try again later`: you sent 5 in the last hour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/support-request": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get a support request",
        "operationId": "getSupportRequest",
        "description": "One support request with its message: one you sent, or one in your organization's inbox. The inbox needs permission to see every partner. Replies go by email. To mark a request responded or closed, use `POST /api/internal/support-request/status`. While your organization's access has expired you can read only requests you sent.",
        "parameters": [
          {
            "name": "support_request_id",
            "in": "query",
            "required": true,
            "description": "Support request ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupportRequest"
                }
              }
            }
          },
          "400": {
            "description": "`invalid input: support_request_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`support request not found`, also when you can't see it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/support-request/status": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Update a support request",
        "operationId": "updateSupportRequestStatus",
        "description": "Marks a support request from an organization below yours as responded or closed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SupportRequestStatus"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `support request marked responded` or `support request marked closed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: support_request_id` or `status must be responded or closed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`support request already closed` or `support request already responded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/signup/reject": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Reject a signup",
        "operationId": "rejectSignup",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignupRejection"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Rejected. No body."
          },
          "400": {
            "description": "`invalid json`. `invalid input: signup_id` when it's missing or isn't a UUID. `invalid input` when `reason` is under 3 or over 500 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/account": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get your organization",
        "operationId": "getOrganization",
        "description": "Needs permission to see the organization.",
        "responses": {
          "200": {
            "description": "Your organization. `total_available_apps` counts apps available to everyone. The owner's ID, email and job title are left out when you can't see the owner.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/account/owner": {
      "put": {
        "tags": [
          "Management API"
        ],
        "summary": "Transfer ownership",
        "operationId": "transferOwnership",
        "description": "Makes another user in your organization the owner. Only the owner can do this. You keep the role you name.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransferOwnership"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`message` is `ownership transferred successfully`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: new_owner_user_id` when it's missing or isn't a UUID, `new owner must be account member` when `new_owner_user_id` isn't another person in your organization, `invalid input: previous_owner_role_key` when it's missing, `account_owner` or isn't 1 to 100 lowercase letters, digits or underscores.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`only owner can transfer ownership` or `account expired`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`role not found`: `previous_owner_role_key` isn't a role you can take.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/account/secret": {
      "post": {
        "tags": [
          "Management API"
        ],
        "summary": "Rotate the organization secret",
        "operationId": "rotateOrganizationSecret",
        "description": "Creates a new organization secret for `X-Org-Secret` on `POST /api/public/signup`. The previous one stops working. The response is the only time you see it.",
        "responses": {
          "200": {
            "description": "The new secret.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "org_secret"
                  ],
                  "properties": {
                    "org_secret": {
                      "type": "string",
                      "minLength": 64,
                      "maxLength": 64
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/account/ai-access": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get AI access",
        "operationId": "getAIAccess",
        "description": "What AI clients can do in your organization through the platform's MCP server, and which AI client hosts can connect. Only the owner can see this.",
        "responses": {
          "200": {
            "description": "The current settings.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIAccess"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not found`: this region doesn't offer AI clients.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "tags": [
          "Management API"
        ],
        "summary": "Change AI access",
        "operationId": "setAIAccess",
        "description": "Changes 1 setting per call: send `ai_access` or `ai_clients`, not both. Only the owner can do this.\n\n- `ai_access` set to `off` disconnects every AI client connected to the platform in your organization.\n- A list of hosts in `ai_clients` disconnects AI clients from other hosts and unverified ones. An empty list allows any AI client.\n\nAI clients connected to individual apps stay connected.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AIAccessUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The setting you changed and its value before.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "previous"
                  ],
                  "properties": {
                    "ai_access": {
                      "type": "string",
                      "enum": [
                        "off",
                        "read",
                        "write"
                      ],
                      "description": "When you sent `ai_access`."
                    },
                    "ai_clients": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "When you sent `ai_clients`. Sorted, without duplicates."
                    },
                    "previous": {
                      "type": [
                        "string",
                        "array"
                      ],
                      "items": {
                        "type": "string"
                      },
                      "description": "The value before, in the same form."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid json`, `invalid input: send ai_access or ai_clients`, `invalid input: ai_access` or `invalid input: hosts`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not found`: this region doesn't offer AI clients.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/limits": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "Get your organization's limits",
        "operationId": "getOrganizationLimits",
        "description": "Needs permission to see limits.",
        "responses": {
          "200": {
            "description": "Your plan, limits and use.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Limits"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/internal/activity": {
      "get": {
        "tags": [
          "Management API"
        ],
        "summary": "List activity",
        "operationId": "listActivity",
        "description": "Your organization's audit log, newest first. You see your own actions and those on things you can see. Emails, changes, IP addresses and user agents appear only for people who can see the whole audit log.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Search text. Every word must match. `search` works too.",
            "schema": {
              "type": "string",
              "maxLength": 256
            }
          },
          {
            "name": "org",
            "in": "query",
            "required": false,
            "description": "A closed organization whose audit log you can still read.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "actor",
            "in": "query",
            "required": false,
            "description": "Only events by this user.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "thing",
            "in": "query",
            "required": false,
            "description": "Only events about this user, team, app or other thing.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "description": "Only this action, such as `auth.sign_out`.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z_]+\\.[a-z_]+$",
              "maxLength": 40
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day to include, in your time zone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day to include, in your time zone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `X-Next-Cursor` value from the previous page. `before` works too.",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of events.",
            "headers": {
              "X-Next-Cursor": {
                "$ref": "#/components/headers/NextCursor"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ActivityEntry"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid input` or `invalid search query`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`partner not found`: you can't read the audit log of the organization in `org`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "platformSession": {
        "type": "http",
        "scheme": "bearer",
        "description": "A platform session token, from `POST /api/public/auth/magic-link/verify` with a link requested without `app_id`. Send `Authorization: Bearer <token>` with `Bearer` written exactly like that."
      },
      "platformSessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "session",
        "description": "The same platform session token in a cookie named `session`. When you send a cookie and a header, the cookie is used."
      },
      "appSession": {
        "type": "http",
        "scheme": "bearer",
        "description": "A session token issued for one app when a person signs in to it. It works only with that app's `app_id` and never on the Management API. Send `Authorization: Bearer <token>` with `Bearer` written exactly like that."
      },
      "appSessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "session",
        "description": "The same app session token in a cookie named `session`. When you send a cookie and a header, the cookie is used."
      },
      "mcpCredential": {
        "type": "http",
        "scheme": "bearer",
        "description": "An access token an AI client got from `POST /api/public/auth/mcp/token` for your app. Accepted only with the `mcp` query parameter. Send `Authorization: Bearer <token>` with `Bearer` written exactly like that."
      },
      "appSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "X-App-Secret",
        "description": "Your app's secret, 64 characters. You see it when you register the app and each time you rotate it."
      },
      "orgSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Org-Secret",
        "description": "The parent organization's secret, 64 characters, from `POST /api/internal/account/secret`."
      }
    },
    "parameters": {
      "UserId": {
        "name": "user_id",
        "in": "query",
        "required": true,
        "description": "User ID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "TeamId": {
        "name": "team_id",
        "in": "query",
        "required": true,
        "description": "Team ID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "AppId": {
        "name": "app_id",
        "in": "query",
        "required": true,
        "description": "App ID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "RoleKey": {
        "name": "role_key",
        "in": "query",
        "required": true,
        "description": "Role key, such as `user_admin`.",
        "schema": {
          "type": "string",
          "maxLength": 100
        }
      },
      "PermissionKey": {
        "name": "permission_key",
        "in": "query",
        "required": true,
        "description": "Permission key, such as `view_any_user`.",
        "schema": {
          "type": "string"
        }
      },
      "PartnerId": {
        "name": "partner_id",
        "in": "query",
        "required": true,
        "description": "Partner organization ID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "PartnerAccountId": {
        "name": "partner_account_id",
        "in": "query",
        "required": true,
        "description": "Partner organization ID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "Q": {
        "name": "q",
        "in": "query",
        "required": false,
        "description": "Search text. Every word must match.",
        "schema": {
          "type": "string",
          "maxLength": 256
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "The `X-Next-Cursor` value from the previous page.",
        "schema": {
          "type": "string"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size. Values above 200 count as 200.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 100
        }
      }
    },
    "headers": {
      "NextCursor": {
        "description": "Send it as `cursor` to get the next page. Absent on the last page.",
        "schema": {
          "type": "string"
        }
      },
      "TotalCount": {
        "description": "Total matches. Sent on the first page when the total is 10,000 or less.",
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before trying again.",
        "schema": {
          "type": "integer"
        }
      },
      "NoStore": {
        "description": "Don't cache this response.",
        "schema": {
          "type": "string",
          "const": "no-store"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request isn't valid. `error` says why, for example `invalid json` or `invalid input: user_id`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "`missing authorization header` or `invalid session`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "`forbidden`: your roles don't allow this or your organization's access has expired.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "It doesn't exist or you can't see it. `error` says what, for example `user not found`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "`unsupported media type`: send `Content-Type: application/json`. Parameters such as `charset` are fine.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "`too many requests, please try again later`. Some limits also send `Retry-After`.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InternalError": {
        "description": "`internal server error`: something failed on our side. Try again.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "What went wrong."
          }
        }
      },
      "Message": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          }
        }
      },
      "SignupRequest": {
        "type": "object",
        "required": [
          "account_name",
          "account_country",
          "account_timezone",
          "account_type",
          "account_plan",
          "user_first_name",
          "user_last_name",
          "user_email",
          "user_position"
        ],
        "properties": {
          "parent_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization to apply under. Leave it out for the top organization of this region."
          },
          "account_name": {
            "type": "string",
            "maxLength": 255,
            "description": "Name of the new organization."
          },
          "account_country": {
            "type": "string",
            "maxLength": 50,
            "description": "Country name, such as `Germany`."
          },
          "account_timezone": {
            "type": "string",
            "description": "IANA time zone, such as `Europe/Berlin`."
          },
          "account_type": {
            "type": "string",
            "maxLength": 100,
            "description": "What kind of organization it is."
          },
          "account_plan": {
            "type": "string",
            "enum": [
              "free",
              "pilot",
              "premium"
            ],
            "description": "Plan. Any case works."
          },
          "user_first_name": {
            "type": "string",
            "maxLength": 100
          },
          "user_last_name": {
            "type": "string",
            "maxLength": 100
          },
          "user_email": {
            "type": "string",
            "format": "email",
            "maxLength": 255,
            "description": "The applicant's email. They become the owner when the signup is approved."
          },
          "user_position": {
            "type": "string",
            "maxLength": 100,
            "description": "The applicant's job title."
          },
          "signup_message": {
            "type": "string",
            "maxLength": 1000,
            "description": "A note for the approvers."
          }
        }
      },
      "SignupReceived": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "const": "We got your signup. We read every one and reply by email.",
            "description": "Always `We got your signup. We read every one and reply by email.`"
          },
          "signup_id": {
            "type": "string",
            "format": "uuid",
            "description": "Only in local development."
          }
        }
      },
      "MagicLinkSendRequest": {
        "type": "object",
        "properties": {
          "user_email": {
            "type": "string",
            "format": "email"
          },
          "app_id": {
            "type": "string",
            "format": "uuid",
            "description": "Your app's ID. Requires `X-App-Secret`."
          }
        }
      },
      "MagicLinkSendResponse": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "token": {
            "type": "string",
            "description": "The sign-in link's token. Only in local development."
          }
        }
      },
      "MagicLinkVerifyRequest": {
        "type": "object",
        "required": [
          "token"
        ],
        "properties": {
          "token": {
            "type": "string",
            "minLength": 64,
            "maxLength": 64,
            "description": "The `token` query parameter of the sign-in link."
          }
        }
      },
      "MagicLinkVerifyResponse": {
        "type": "object",
        "required": [
          "session_token",
          "token_scope"
        ],
        "properties": {
          "session_token": {
            "type": "string",
            "format": "uuid",
            "description": "The platform session token. When the link was for an app, the app session token."
          },
          "token_scope": {
            "type": "string",
            "enum": [
              "full",
              "support_only"
            ]
          },
          "app_id": {
            "type": "string",
            "format": "uuid",
            "description": "The app the token is for. Only for app links."
          },
          "redirect_url": {
            "type": "string",
            "format": "uri",
            "description": "The support page. Only when `token_scope` is `support_only`."
          },
          "account_status": {
            "type": "string",
            "const": "expired",
            "description": "Only when `token_scope` is `support_only`."
          }
        }
      },
      "SessionValidation": {
        "type": "object",
        "required": [
          "authenticated"
        ],
        "properties": {
          "authenticated": {
            "type": "boolean"
          },
          "user": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SDKUser"
              }
            ],
            "description": "Only when `authenticated` is `true`."
          },
          "sign_in_url": {
            "type": "string",
            "format": "uri",
            "description": "Where to send the person to sign in. Only when `authenticated` is `false`."
          },
          "www_authenticate": {
            "type": "string",
            "description": "The `WWW-Authenticate` value for your 401 to the AI client. Only with `mcp` and when `authenticated` is `false`."
          }
        }
      },
      "SDKUser": {
        "type": "object",
        "required": [
          "user_id",
          "account_id",
          "user_email",
          "user_first_name",
          "user_last_name",
          "user_is_app_admin",
          "user_teams"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The person's organization."
          },
          "user_email": {
            "type": "string",
            "format": "email"
          },
          "user_first_name": {
            "type": "string"
          },
          "user_last_name": {
            "type": "string"
          },
          "user_is_app_admin": {
            "type": "boolean",
            "description": "The person is an app admin or the owner in their organization. Your app decides what that means."
          },
          "user_teams": {
            "type": "array",
            "description": "Teams the person is on in their organization, sorted by name. Empty when none.",
            "items": {
              "$ref": "#/components/schemas/SDKTeam"
            }
          }
        }
      },
      "SDKTeam": {
        "type": "object",
        "required": [
          "team_id",
          "team_name"
        ],
        "properties": {
          "team_id": {
            "type": "string",
            "format": "uuid"
          },
          "team_name": {
            "type": "string"
          }
        }
      },
      "DirectoryUser": {
        "type": "object",
        "required": [
          "user_id",
          "user_email",
          "user_first_name",
          "user_last_name"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "user_email": {
            "type": "string",
            "format": "email"
          },
          "user_first_name": {
            "type": "string"
          },
          "user_last_name": {
            "type": "string"
          }
        }
      },
      "MCPTokenRequest": {
        "type": "object",
        "required": [
          "grant_type"
        ],
        "properties": {
          "grant_type": {
            "type": "string",
            "enum": [
              "authorization_code",
              "refresh_token"
            ]
          },
          "code": {
            "type": "string",
            "minLength": 64,
            "maxLength": 64,
            "description": "For `authorization_code`."
          },
          "code_verifier": {
            "type": "string",
            "minLength": 43,
            "maxLength": 128,
            "description": "For `authorization_code`. The PKCE verifier."
          },
          "redirect_uri": {
            "type": "string",
            "description": "For `authorization_code`. The one used at the authorize step."
          },
          "resource": {
            "type": "string",
            "format": "uri",
            "description": "For `authorization_code`. The MCP endpoint URL. Must match the one from the authorize step."
          },
          "refresh_token": {
            "type": "string",
            "minLength": 64,
            "maxLength": 64,
            "description": "For `refresh_token`."
          },
          "client_id": {
            "type": "string",
            "description": "Your `client_id` from registration or the HTTPS URL of your client metadata document."
          }
        }
      },
      "MCPTokenResponse": {
        "type": "object",
        "required": [
          "access_token",
          "token_type",
          "expires_in",
          "refresh_token"
        ],
        "properties": {
          "access_token": {
            "type": "string",
            "format": "uuid"
          },
          "token_type": {
            "type": "string",
            "const": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "description": "Seconds until the access token expires."
          },
          "refresh_token": {
            "type": "string"
          },
          "scope": {
            "type": "string",
            "enum": [
              "stackure.read",
              "stackure.read stackure.write"
            ],
            "description": "Left out for connections to an app."
          }
        }
      },
      "MCPRegisterRequest": {
        "type": "object",
        "required": [
          "redirect_uris"
        ],
        "properties": {
          "redirect_uris": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "items": {
              "type": "string",
              "maxLength": 2048
            }
          },
          "client_name": {
            "type": "string",
            "description": "Shown to people when they connect. Only letters, digits, spaces and hyphens are kept. Defaults to `MCP client`."
          }
        }
      },
      "MCPRegisterResponse": {
        "type": "object",
        "required": [
          "client_id",
          "client_id_issued_at",
          "client_name",
          "redirect_uris",
          "token_endpoint_auth_method",
          "grant_types",
          "response_types"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "format": "uuid"
          },
          "client_id_issued_at": {
            "type": "integer",
            "description": "Unix time in seconds."
          },
          "client_name": {
            "type": "string"
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "const": "none"
          },
          "grant_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "authorization_code",
                "refresh_token"
              ]
            }
          },
          "response_types": {
            "type": "array",
            "items": {
              "type": "string",
              "const": "code"
            }
          }
        }
      },
      "MCPRevokeRequest": {
        "type": "object",
        "required": [
          "token"
        ],
        "properties": {
          "token": {
            "type": "string",
            "description": "An access token or refresh token."
          },
          "client_id": {
            "type": "string",
            "description": "When sent, the token must belong to this client."
          }
        }
      },
      "User": {
        "type": "object",
        "description": "A user. Fields an endpoint doesn't load are empty or left out. Dates it doesn't load are `0001-01-01T00:00:00Z`.",
        "required": [
          "user_first_name",
          "user_last_name",
          "user_position",
          "user_email",
          "user_created",
          "user_updated"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The user's organization."
          },
          "user_first_name": {
            "type": "string"
          },
          "user_last_name": {
            "type": "string"
          },
          "user_position": {
            "type": "string",
            "description": "Job title."
          },
          "user_email": {
            "type": "string",
            "format": "email"
          },
          "user_settings": {
            "type": "object",
            "description": "Stored settings, such as `timezone`."
          },
          "user_timezone": {
            "type": "string",
            "description": "IANA time zone, such as `Europe/Berlin`."
          },
          "user_created": {
            "type": "string",
            "format": "date-time"
          },
          "user_updated": {
            "type": "string",
            "format": "date-time"
          },
          "user_created_by": {
            "type": "string",
            "format": "uuid",
            "description": "The user who invited this one."
          }
        }
      },
      "UserListItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/User"
          },
          {
            "type": "object",
            "required": [
              "HasAccess"
            ],
            "properties": {
              "HasAccess": {
                "type": "boolean",
                "const": true,
                "description": "Always `true`."
              }
            }
          }
        ]
      },
      "UserDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/User"
          },
          {
            "type": "object",
            "required": [
              "creator"
            ],
            "properties": {
              "creator": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/User"
                  }
                ],
                "description": "The user who invited this one. Email and job title are empty when you can't see them."
              },
              "user_is_account_owner": {
                "type": "boolean",
                "description": "Present and `true` when this user owns the organization."
              },
              "user_app_count": {
                "type": "integer",
                "description": "Apps this user can open that you can see. Left out when 0."
              },
              "user_team_count": {
                "type": "integer",
                "description": "Teams this user is on that you can see. Left out when 0."
              },
              "user_role_count": {
                "type": "integer",
                "description": "Roles this user holds. Left out when 0."
              }
            }
          }
        ]
      },
      "InviteUser": {
        "type": "object",
        "required": [
          "user_first_name",
          "user_last_name",
          "user_email",
          "user_position"
        ],
        "properties": {
          "user_first_name": {
            "type": "string",
            "maxLength": 100
          },
          "user_last_name": {
            "type": "string",
            "maxLength": 100
          },
          "user_email": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "user_position": {
            "type": "string",
            "maxLength": 100,
            "description": "Job title."
          },
          "user_settings": {
            "type": "object"
          }
        }
      },
      "InviteResult": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "enum": [
              "all users invited successfully",
              "some users invited successfully",
              "some users invited successfully, some failed",
              "all users failed to be invited",
              "all users already exist"
            ]
          },
          "details": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "user_id",
                "user_email",
                "status"
              ],
              "properties": {
                "user_id": {
                  "type": "string",
                  "description": "Empty when no user was created."
                },
                "user_email": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "description": "`created`, `duplicate_skipped` when the email already exists, or why it failed, such as `user_email required` or `invalid email`."
                }
              }
            }
          }
        }
      },
      "UserUpdate": {
        "type": "object",
        "properties": {
          "user_first_name": {
            "type": "string",
            "maxLength": 100
          },
          "user_last_name": {
            "type": "string",
            "maxLength": 100
          },
          "user_email": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "user_position": {
            "type": "string",
            "maxLength": 100,
            "description": "Job title."
          },
          "user_timezone": {
            "type": "string",
            "description": "IANA time zone, such as `Europe/Berlin`. Only for yourself."
          }
        }
      },
      "UserAccess": {
        "type": "object",
        "required": [
          "user_id",
          "user_first_name",
          "user_last_name",
          "role_actions",
          "roles"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "user_first_name": {
            "type": "string"
          },
          "user_last_name": {
            "type": "string"
          },
          "role_actions": {
            "type": "object",
            "description": "Permission keys by role key. Roles without permissions are left out.",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccessRole"
            }
          }
        }
      },
      "AccessRole": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Role"
          },
          {
            "type": "object",
            "required": [
              "can_remove",
              "permissions"
            ],
            "properties": {
              "can_remove": {
                "type": "boolean",
                "description": "You can remove this role from the user."
              },
              "permissions": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Permission"
                }
              }
            }
          }
        ]
      },
      "UserRolesRequest": {
        "type": "object",
        "required": [
          "roles"
        ],
        "description": "Send `user_id` or `user_email`.",
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "user_email": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "roles": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "maxLength": 100
            }
          }
        }
      },
      "AIClients": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AIClient"
            }
          }
        }
      },
      "AIClient": {
        "type": "object",
        "required": [
          "id",
          "host",
          "target",
          "grant",
          "created",
          "used",
          "expires",
          "is_current",
          "untrusted"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Connection ID."
          },
          "host": {
            "type": "string",
            "description": "Host of the client's HTTPS client ID. `unverified` when it has none."
          },
          "target": {
            "type": "string",
            "description": "The app the client connects to. For platform connections, our platform's name."
          },
          "grant": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "read",
              "write",
              null
            ],
            "description": "`read` or `write` for platform connections. `null` for app connections."
          },
          "created": {
            "type": "string",
            "format": "date-time"
          },
          "used": {
            "type": "string",
            "format": "date-time"
          },
          "expires": {
            "type": "string",
            "format": "date-time"
          },
          "is_current": {
            "type": "boolean",
            "const": false,
            "description": "Always `false` here."
          },
          "untrusted": {
            "type": "object",
            "required": [
              "client"
            ],
            "properties": {
              "client": {
                "type": "string",
                "description": "The name the client gave itself. Not verified."
              }
            }
          }
        }
      },
      "AIClientDisconnect": {
        "type": "object",
        "required": [
          "connection_id"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Whose connection. Leave it out for yourself."
          },
          "connection_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "AIAccess": {
        "type": "object",
        "required": [
          "ai_access",
          "ai_clients"
        ],
        "properties": {
          "ai_access": {
            "type": "string",
            "enum": [
              "off",
              "read",
              "write"
            ],
            "description": "`off`: AI clients can't connect. `read`: view only. `write`: view and change."
          },
          "ai_clients": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string"
            },
            "description": "AI client hosts allowed to connect, such as `claude.ai`, sorted. Empty allows any AI client."
          }
        }
      },
      "AIAccessUpdate": {
        "type": "object",
        "description": "Send exactly 1 of the 2 fields.",
        "properties": {
          "ai_access": {
            "type": "string",
            "enum": [
              "off",
              "read",
              "write"
            ],
            "description": "`off`: AI clients can't connect. `read`: view only. `write`: view and change."
          },
          "ai_clients": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string",
              "minLength": 1
            },
            "description": "Host names such as `claude.ai`, up to 253 characters each. A URL counts as its host. Duplicates are dropped. Empty allows any AI client."
          }
        },
        "oneOf": [
          {
            "required": [
              "ai_access"
            ]
          },
          {
            "required": [
              "ai_clients"
            ]
          }
        ]
      },
      "Role": {
        "type": "object",
        "required": [
          "role_key",
          "role_name"
        ],
        "properties": {
          "role_key": {
            "type": "string"
          },
          "role_name": {
            "type": "string"
          },
          "role_description": {
            "type": "string"
          },
          "role_type": {
            "type": "string",
            "enum": [
              "default",
              "custom"
            ]
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization a custom role belongs to."
          },
          "user_count": {
            "type": "integer",
            "description": "Users in your organization with this role. Left out when 0."
          }
        }
      },
      "Permission": {
        "type": "object",
        "required": [
          "permission_key",
          "permission_name"
        ],
        "properties": {
          "permission_id": {
            "type": "string",
            "format": "uuid"
          },
          "permission_key": {
            "type": "string"
          },
          "permission_name": {
            "type": "string"
          },
          "permission_description": {
            "type": "string"
          },
          "permission_role_count": {
            "type": "integer",
            "description": "Roles with this permission. Left out when 0."
          },
          "permission_user_count": {
            "type": "integer",
            "description": "Users you can see who hold it. Left out when 0."
          }
        }
      },
      "RoleCreate": {
        "type": "object",
        "required": [
          "role_key",
          "role_name"
        ],
        "properties": {
          "role_key": {
            "type": "string",
            "pattern": "^[a-z0-9_]{1,100}$"
          },
          "role_name": {
            "type": "string",
            "maxLength": 100
          },
          "role_description": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "RoleUpdate": {
        "type": "object",
        "required": [
          "role_key"
        ],
        "properties": {
          "role_key": {
            "type": "string",
            "maxLength": 100
          },
          "role_name": {
            "type": "string",
            "maxLength": 100
          },
          "role_description": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "RolePermissionsChange": {
        "type": "object",
        "required": [
          "role_key",
          "permission_keys"
        ],
        "properties": {
          "role_key": {
            "type": "string",
            "maxLength": 100
          },
          "permission_keys": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "maxLength": 100
            }
          }
        }
      },
      "RoleUsers": {
        "type": "object",
        "required": [
          "role",
          "users"
        ],
        "properties": {
          "role": {
            "$ref": "#/components/schemas/Role"
          },
          "users": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/User"
            }
          }
        }
      },
      "PermissionRoles": {
        "type": "object",
        "required": [
          "permission",
          "roles"
        ],
        "properties": {
          "permission": {
            "$ref": "#/components/schemas/Permission"
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Role"
            }
          }
        }
      },
      "PermissionUsers": {
        "type": "object",
        "required": [
          "permission",
          "users"
        ],
        "properties": {
          "permission": {
            "$ref": "#/components/schemas/Permission"
          },
          "users": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/User"
            }
          }
        }
      },
      "Team": {
        "type": "object",
        "description": "A team. Fields an endpoint doesn't load are left out.",
        "required": [
          "team_name"
        ],
        "properties": {
          "team_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The team's organization."
          },
          "team_name": {
            "type": "string"
          },
          "team_settings": {
            "type": "object"
          },
          "team_created": {
            "type": "string",
            "format": "date-time"
          },
          "team_updated": {
            "type": "string",
            "format": "date-time"
          },
          "team_created_by": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "TeamListItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Team"
          },
          {
            "type": "object",
            "description": "Teams you can see only by name have just `team_id`, `team_name` and `team_you_are_admin`.",
            "required": [
              "team_you_are_admin"
            ],
            "properties": {
              "team_you_are_admin": {
                "type": "boolean"
              }
            }
          }
        ]
      },
      "TeamDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Team"
          },
          {
            "type": "object",
            "required": [
              "team_admin_count",
              "team_you_are_admin",
              "user_can_add_users_to_this_team",
              "user_can_manage_admins"
            ],
            "properties": {
              "team_member_count": {
                "type": "integer",
                "description": "Left out when 0."
              },
              "team_app_count": {
                "type": "integer",
                "description": "Apps shared with the team that you can see. Left out when 0."
              },
              "team_managed_partner_count": {
                "type": "integer",
                "description": "Partners the team manages that you can see. Left out when 0."
              },
              "team_admin_count": {
                "type": "integer"
              },
              "team_you_are_admin": {
                "type": "boolean"
              },
              "user_can_add_users_to_this_team": {
                "type": "boolean",
                "description": "Whether you can add people to this team."
              },
              "user_can_manage_admins": {
                "type": "boolean",
                "description": "Whether you can make and remove this team's admins."
              },
              "team_members": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TeamMember"
                }
              }
            }
          }
        ]
      },
      "TeamMember": {
        "allOf": [
          {
            "$ref": "#/components/schemas/User"
          },
          {
            "type": "object",
            "required": [
              "user_is_team_admin",
              "assigned_at",
              "user_can_remove_this_user_from_this_team",
              "user_can_make_admin",
              "user_can_remove_admin",
              "user_can_view"
            ],
            "properties": {
              "user_is_team_admin": {
                "type": "boolean"
              },
              "assigned_at": {
                "type": "string",
                "format": "date-time",
                "description": "When they joined the team."
              },
              "user_can_remove_this_user_from_this_team": {
                "type": "boolean"
              },
              "user_can_make_admin": {
                "type": "boolean"
              },
              "user_can_remove_admin": {
                "type": "boolean"
              },
              "user_can_view": {
                "type": "boolean",
                "description": "You can open this user's page."
              }
            }
          }
        ]
      },
      "TeamCreate": {
        "type": "object",
        "required": [
          "team_name",
          "team_admin_id"
        ],
        "properties": {
          "team_name": {
            "type": "string",
            "maxLength": 255
          },
          "team_admin_id": {
            "type": "string",
            "format": "uuid",
            "description": "The team's first admin."
          },
          "team_settings": {
            "type": "object"
          }
        }
      },
      "TeamCreated": {
        "type": "object",
        "required": [
          "message",
          "team_id"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "team_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "TeamUpdate": {
        "type": "object",
        "required": [
          "team_id"
        ],
        "properties": {
          "team_id": {
            "type": "string",
            "format": "uuid"
          },
          "team_name": {
            "type": "string",
            "maxLength": 255
          },
          "team_settings": {
            "type": "object"
          }
        }
      },
      "AddTeamMembersRequest": {
        "type": "object",
        "required": [
          "team_id",
          "member_ids"
        ],
        "properties": {
          "team_id": {
            "type": "string",
            "format": "uuid"
          },
          "member_ids": {
            "type": "array",
            "minItems": 1,
            "description": "User IDs.",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "AddTeamMembersResult": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "enum": [
              "team members added successfully",
              "some team members added successfully, some failed",
              "all team members failed to be added"
            ]
          },
          "details": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "user_id",
                "status"
              ],
              "properties": {
                "user_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "status": {
                  "type": "string",
                  "description": "`assigned`, `already_member`, `duplicate_input_skipped`, `user_not_found` or why it failed."
                }
              }
            }
          }
        }
      },
      "TeamAdminChange": {
        "type": "object",
        "required": [
          "is_admin"
        ],
        "properties": {
          "is_admin": {
            "type": "boolean",
            "description": "`true` makes the member an admin. `false` removes their admin role."
          }
        }
      },
      "TeamPartnerAssign": {
        "type": "object",
        "required": [
          "team_id",
          "partner_account_id"
        ],
        "properties": {
          "team_id": {
            "type": "string",
            "format": "uuid"
          },
          "partner_account_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "App": {
        "type": "object",
        "description": "An app. Fields an endpoint doesn't load are left out. Dates it doesn't load are `0001-01-01T00:00:00Z`.",
        "required": [
          "app_created",
          "app_updated"
        ],
        "properties": {
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization that registered the app."
          },
          "app_name": {
            "type": "string"
          },
          "app_url": {
            "type": "string",
            "format": "uri"
          },
          "app_logo": {
            "type": "string"
          },
          "app_logo_type": {
            "type": "string"
          },
          "app_created": {
            "type": "string",
            "format": "date-time"
          },
          "app_updated": {
            "type": "string",
            "format": "date-time"
          },
          "app_created_by": {
            "type": "string",
            "format": "uuid"
          },
          "share_state": {
            "type": "string",
            "enum": [
              "pending",
              "teams",
              "organization"
            ],
            "description": "How far your organization has distributed the app: `pending` (not yet), `teams` (chosen teams) or `organization` (everyone)."
          },
          "app_mcp_url": {
            "type": "string",
            "format": "uri",
            "description": "The app's MCP endpoint, when set."
          }
        }
      },
      "AppDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/App"
          },
          {
            "type": "object",
            "required": [
              "creator_is_you",
              "user_can_view_this_app",
              "user_can_edit_this_app",
              "user_can_delete_this_app",
              "user_can_share_this_app",
              "user_can_share_to_account",
              "user_can_share_to_teams",
              "user_can_share_to_partners",
              "user_can_unshare_this_app",
              "user_can_view_this_app_users",
              "user_can_view_this_app_teams",
              "user_can_view_this_app_partners",
              "user_can_view_creator",
              "is_shared_with_user_account",
              "is_received"
            ],
            "properties": {
              "creator_id": {
                "type": "string",
                "format": "uuid"
              },
              "creator_first_name": {
                "type": "string"
              },
              "creator_last_name": {
                "type": "string"
              },
              "creator_is_you": {
                "type": "boolean"
              },
              "app_users_count": {
                "type": "integer",
                "description": "People in your organization who can open it. Left out when 0."
              },
              "app_teams_count": {
                "type": "integer",
                "description": "Teams in your organization it's shared with. Left out when 0."
              },
              "app_partners_count": {
                "type": "integer",
                "description": "Partners it's shared with. Left out when 0."
              },
              "user_can_view_this_app": {
                "type": "boolean",
                "const": true
              },
              "user_can_edit_this_app": {
                "type": "boolean"
              },
              "user_can_delete_this_app": {
                "type": "boolean"
              },
              "user_can_share_this_app": {
                "type": "boolean",
                "description": "You can share it with everyone, teams or partners."
              },
              "user_can_share_to_account": {
                "type": "boolean",
                "description": "You can make it available to everyone."
              },
              "user_can_share_to_teams": {
                "type": "boolean"
              },
              "user_can_share_to_partners": {
                "type": "boolean"
              },
              "user_can_unshare_this_app": {
                "type": "boolean"
              },
              "user_can_view_this_app_users": {
                "type": "boolean"
              },
              "user_can_view_this_app_teams": {
                "type": "boolean"
              },
              "user_can_view_this_app_partners": {
                "type": "boolean"
              },
              "user_can_view_creator": {
                "type": "boolean"
              },
              "is_shared_with_user_account": {
                "type": "boolean",
                "description": "The app is available to everyone in your organization."
              },
              "is_received": {
                "type": "boolean",
                "description": "Another organization registered the app and shared it with yours."
              },
              "owner_name": {
                "type": "string",
                "description": "Name of the organization that registered the app."
              }
            }
          }
        ]
      },
      "AppCreate": {
        "type": "object",
        "required": [
          "app_name",
          "app_url",
          "app_logo",
          "app_logo_type"
        ],
        "properties": {
          "app_name": {
            "type": "string",
            "maxLength": 255
          },
          "app_url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS URL of the app. Saved in lowercase."
          },
          "app_logo": {
            "type": "string"
          },
          "app_logo_type": {
            "type": "string"
          },
          "app_mcp_url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS URL of the app's MCP endpoint, if it has one."
          }
        }
      },
      "AppCreated": {
        "type": "object",
        "required": [
          "message",
          "app_id",
          "app_secret"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "app_secret": {
            "type": "string",
            "minLength": 64,
            "maxLength": 64,
            "description": "Shown only here. Store it now."
          }
        }
      },
      "AppUpdate": {
        "type": "object",
        "properties": {
          "app_name": {
            "type": "string",
            "maxLength": 255
          },
          "app_url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS URL of the app."
          },
          "app_logo": {
            "type": "string"
          },
          "app_logo_type": {
            "type": "string"
          },
          "app_mcp_url": {
            "type": "string",
            "description": "HTTPS URL of the app's MCP endpoint. An empty string removes it."
          }
        }
      },
      "AppTeams": {
        "type": "object",
        "required": [
          "app",
          "teams"
        ],
        "properties": {
          "app": {
            "$ref": "#/components/schemas/App"
          },
          "teams": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "team_id",
                "team_name",
                "access_view_this_team",
                "access_stop_sharing_app_with_this_team"
              ],
              "properties": {
                "team_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "team_name": {
                  "type": "string"
                },
                "access_view_this_team": {
                  "type": "boolean"
                },
                "access_stop_sharing_app_with_this_team": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      },
      "AppUsers": {
        "type": "object",
        "required": [
          "app",
          "users"
        ],
        "properties": {
          "app": {
            "$ref": "#/components/schemas/App"
          },
          "users": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "user_id",
                "user_first_name",
                "user_last_name",
                "user_email",
                "user_position",
                "access_view_this_user"
              ],
              "properties": {
                "user_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "user_first_name": {
                  "type": "string"
                },
                "user_last_name": {
                  "type": "string"
                },
                "user_email": {
                  "type": "string",
                  "format": "email"
                },
                "user_position": {
                  "type": "string"
                },
                "access_view_this_user": {
                  "type": "boolean",
                  "const": true
                }
              }
            }
          }
        }
      },
      "AppPartners": {
        "type": "object",
        "required": [
          "app",
          "partners"
        ],
        "properties": {
          "app": {
            "$ref": "#/components/schemas/App"
          },
          "partners": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "account_id",
                "account_name",
                "access_stop_sharing_app_with_this_partner"
              ],
              "properties": {
                "account_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "account_name": {
                  "type": "string"
                },
                "access_stop_sharing_app_with_this_partner": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      },
      "AppShareEveryone": {
        "type": "object",
        "required": [
          "app_id"
        ],
        "properties": {
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "Your organization's ID. Any other value returns 400."
          }
        }
      },
      "AppShareTeam": {
        "type": "object",
        "required": [
          "app_id",
          "team_id"
        ],
        "properties": {
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "team_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "AppSharePartner": {
        "type": "object",
        "required": [
          "partner_id"
        ],
        "properties": {
          "partner_id": {
            "type": "string",
            "format": "uuid",
            "description": "Partner organization ID."
          }
        }
      },
      "Organization": {
        "type": "object",
        "required": [
          "account_name",
          "account_country",
          "account_level",
          "account_type",
          "account_plan",
          "account_created",
          "account_updated",
          "account_expiry"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "parent_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization directly above."
          },
          "account_name": {
            "type": "string"
          },
          "account_country": {
            "type": "string"
          },
          "account_level": {
            "type": "string",
            "enum": [
              "root",
              "partner",
              "subpartner"
            ]
          },
          "account_type": {
            "type": "string"
          },
          "account_plan": {
            "type": "string",
            "enum": [
              "free",
              "pilot",
              "premium",
              "root"
            ]
          },
          "account_settings": {
            "type": "object"
          },
          "account_created": {
            "type": "string",
            "format": "date-time"
          },
          "account_updated": {
            "type": "string",
            "format": "date-time"
          },
          "account_expiry": {
            "type": "string",
            "format": "date-time",
            "description": "When the organization's access ends."
          }
        }
      },
      "OrganizationDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Organization"
          },
          {
            "type": "object",
            "description": "Owner fields and totals are left out when empty or 0.",
            "properties": {
              "owner_id": {
                "type": "string",
                "format": "uuid"
              },
              "owner_first_name": {
                "type": "string"
              },
              "owner_last_name": {
                "type": "string"
              },
              "owner_position": {
                "type": "string"
              },
              "owner_email": {
                "type": "string",
                "format": "email"
              },
              "total_teams": {
                "type": "integer"
              },
              "total_users": {
                "type": "integer"
              },
              "total_owned_apps": {
                "type": "integer",
                "description": "Apps the organization registered."
              },
              "total_available_apps": {
                "type": "integer"
              }
            }
          }
        ]
      },
      "PartnerDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/OrganizationDetail"
          },
          {
            "type": "object",
            "required": [
              "managed_by"
            ],
            "properties": {
              "managed_by": {
                "type": "array",
                "description": "Teams in your organization that manage this partner.",
                "items": {
                  "$ref": "#/components/schemas/ManagingTeam"
                }
              }
            }
          }
        ]
      },
      "ManagingTeam": {
        "type": "object",
        "required": [
          "team_id",
          "team_name"
        ],
        "properties": {
          "team_id": {
            "type": "string",
            "format": "uuid"
          },
          "team_name": {
            "type": "string"
          }
        }
      },
      "PartnerListItem": {
        "type": "object",
        "required": [
          "account_id",
          "account_name",
          "account_expiry"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_name": {
            "type": "string"
          },
          "account_expiry": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PartnerApps": {
        "type": "object",
        "required": [
          "partner_name",
          "apps"
        ],
        "properties": {
          "partner_name": {
            "type": "string"
          },
          "apps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/App"
            }
          }
        }
      },
      "PartnerExpiryRequest": {
        "type": "object",
        "required": [
          "target_expiry_date"
        ],
        "properties": {
          "target_expiry_date": {
            "type": "string",
            "format": "date",
            "description": "The new expiry date, such as `2026-12-31`."
          }
        }
      },
      "Limits": {
        "type": "object",
        "required": [
          "account_id",
          "account_name",
          "account_plan",
          "limits"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_name": {
            "type": "string"
          },
          "account_plan": {
            "type": "string"
          },
          "limits": {
            "type": "object",
            "required": [
              "users",
              "teams",
              "apps",
              "partners"
            ],
            "properties": {
              "users": {
                "$ref": "#/components/schemas/LimitUsage"
              },
              "teams": {
                "$ref": "#/components/schemas/LimitUsage"
              },
              "apps": {
                "$ref": "#/components/schemas/LimitUsage"
              },
              "partners": {
                "$ref": "#/components/schemas/LimitUsage"
              }
            }
          }
        }
      },
      "LimitUsage": {
        "type": "object",
        "required": [
          "current",
          "max",
          "remaining"
        ],
        "properties": {
          "current": {
            "type": "integer"
          },
          "max": {
            "type": "integer"
          },
          "remaining": {
            "type": "integer",
            "description": "`-1` when `max` is 0 or `current` is over `max`."
          }
        }
      },
      "SignupListItem": {
        "type": "object",
        "description": "Only `signup_id`, `account_name`, `signup_status` and `signup_created` are filled in. The other fields are empty strings. `signup_updated` is `0001-01-01T00:00:00Z`.",
        "required": [
          "signup_id",
          "account_name",
          "signup_status",
          "signup_created"
        ],
        "properties": {
          "signup_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_name": {
            "type": "string"
          },
          "signup_status": {
            "type": "string",
            "enum": [
              "pending",
              "rejected"
            ]
          },
          "signup_created": {
            "type": "string",
            "format": "date-time"
          },
          "signup_updated": {
            "type": "string",
            "format": "date-time"
          },
          "account_country": {
            "type": "string"
          },
          "account_level": {
            "type": "string"
          },
          "account_type": {
            "type": "string"
          },
          "account_plan": {
            "type": "string"
          },
          "account_timezone": {
            "type": "string"
          },
          "user_first_name": {
            "type": "string"
          },
          "user_last_name": {
            "type": "string"
          },
          "user_email": {
            "type": "string"
          },
          "user_position": {
            "type": "string"
          }
        }
      },
      "SignupDetail": {
        "type": "object",
        "required": [
          "signup_id",
          "account_name",
          "account_country",
          "account_type",
          "account_plan",
          "user_first_name",
          "user_last_name",
          "user_email",
          "user_position",
          "signup_status",
          "signup_message",
          "signup_reviewer_notes",
          "signup_created",
          "signup_updated",
          "can_approve",
          "can_reject",
          "approve_blocked"
        ],
        "properties": {
          "signup_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_name": {
            "type": "string",
            "description": "Name of the new organization."
          },
          "account_country": {
            "type": "string"
          },
          "account_type": {
            "type": "string",
            "description": "What kind of organization it is."
          },
          "account_plan": {
            "type": "string",
            "enum": [
              "free",
              "pilot",
              "premium"
            ]
          },
          "user_first_name": {
            "type": "string"
          },
          "user_last_name": {
            "type": "string"
          },
          "user_email": {
            "type": "string",
            "format": "email",
            "description": "They become the owner when the signup is approved."
          },
          "user_position": {
            "type": "string",
            "description": "Job title."
          },
          "signup_status": {
            "type": "string",
            "enum": [
              "pending",
              "rejected"
            ],
            "description": "An approved signup becomes the organization and is no longer listed."
          },
          "signup_message": {
            "type": "string",
            "description": "The note for the approvers. Empty when there is none."
          },
          "signup_reviewer_notes": {
            "type": "string",
            "description": "The reason given when it was rejected. Empty until then."
          },
          "signup_created": {
            "type": "string",
            "format": "date-time"
          },
          "signup_updated": {
            "type": "string",
            "format": "date-time"
          },
          "can_approve": {
            "type": "boolean",
            "description": "Whether you can approve it now with `POST /api/internal/signup/approve`. `false` while `approve_blocked` is set."
          },
          "can_reject": {
            "type": "boolean",
            "description": "Whether you can reject it now with `POST /api/internal/signup/reject`."
          },
          "approve_blocked": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "email_taken",
              "name_taken",
              "partner_limit",
              null
            ],
            "description": "What stops approval: `email_taken` when the email already belongs to a user, `name_taken` when an organization with this name and country exists, `partner_limit` when you have as many partners as your plan allows. `null` when nothing does or you can't approve it."
          }
        }
      },
      "SignupDecision": {
        "type": "object",
        "required": [
          "signup_id"
        ],
        "properties": {
          "signup_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "SignupApproved": {
        "type": "object",
        "required": [
          "account_id",
          "user_id"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The new organization."
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Its owner."
          }
        }
      },
      "SignupRejection": {
        "type": "object",
        "required": [
          "signup_id",
          "reason"
        ],
        "properties": {
          "signup_id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string",
            "minLength": 3,
            "maxLength": 500
          }
        }
      },
      "SupportRequestStatus": {
        "type": "object",
        "required": [
          "support_request_id",
          "status"
        ],
        "properties": {
          "support_request_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "responded",
              "closed"
            ]
          }
        }
      },
      "SupportRequestListItem": {
        "type": "object",
        "required": [
          "support_request_id",
          "account_id",
          "account_name",
          "request_type",
          "subject",
          "status",
          "support_request_created",
          "support_request_updated"
        ],
        "properties": {
          "support_request_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization that sent it. Yours in `mine`."
          },
          "account_name": {
            "type": "string"
          },
          "request_type": {
            "type": "string",
            "enum": [
              "Account & Billing",
              "Access",
              "Integration",
              "Quota",
              "Bug Report",
              "Feature Request",
              "Other"
            ]
          },
          "subject": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "responded",
              "closed"
            ]
          },
          "support_request_created": {
            "type": "string",
            "format": "date-time"
          },
          "support_request_updated": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SupportRequest": {
        "type": "object",
        "required": [
          "support_request_id",
          "account_id",
          "account_name",
          "user_id",
          "user_first_name",
          "user_last_name",
          "user_email",
          "request_type",
          "subject",
          "message",
          "status",
          "resolved_at",
          "support_request_created",
          "support_request_updated",
          "mine",
          "can_resolve"
        ],
        "properties": {
          "support_request_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization that sent it."
          },
          "account_name": {
            "type": "string"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "The person who sent it."
          },
          "user_first_name": {
            "type": "string"
          },
          "user_last_name": {
            "type": "string"
          },
          "user_email": {
            "type": "string",
            "format": "email"
          },
          "request_type": {
            "type": "string",
            "enum": [
              "Account & Billing",
              "Access",
              "Integration",
              "Quota",
              "Bug Report",
              "Feature Request",
              "Other"
            ]
          },
          "subject": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "responded",
              "closed"
            ],
            "description": "`pending` can change to `responded` or `closed`, and `responded` to `closed`. No change can be undone."
          },
          "resolved_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was closed. `null` until then."
          },
          "support_request_created": {
            "type": "string",
            "format": "date-time"
          },
          "support_request_updated": {
            "type": "string",
            "format": "date-time"
          },
          "mine": {
            "type": "boolean",
            "description": "Whether you sent it."
          },
          "can_resolve": {
            "type": "boolean",
            "description": "Whether you can change its status now with `POST /api/internal/support-request/status`."
          }
        }
      },
      "SupportRequestCreate": {
        "type": "object",
        "required": [
          "request_type",
          "subject",
          "message"
        ],
        "properties": {
          "request_type": {
            "type": "string",
            "enum": [
              "Account & Billing",
              "Access",
              "Integration",
              "Quota",
              "Bug Report",
              "Feature Request",
              "Other"
            ]
          },
          "subject": {
            "type": "string",
            "minLength": 3,
            "maxLength": 150
          },
          "message": {
            "type": "string",
            "minLength": 10,
            "maxLength": 5000
          }
        }
      },
      "TransferOwnership": {
        "type": "object",
        "required": [
          "new_owner_user_id",
          "previous_owner_role_key"
        ],
        "properties": {
          "new_owner_user_id": {
            "type": "string",
            "format": "uuid"
          },
          "previous_owner_role_key": {
            "type": "string",
            "maxLength": 100,
            "description": "The role you keep, such as `user_admin`. Not `account_owner`."
          }
        }
      },
      "ActivityEntry": {
        "type": "object",
        "required": [
          "event_id",
          "occurred_at",
          "action",
          "sentence",
          "actor_type",
          "target_type"
        ],
        "description": "One event. IDs and names of things you can't see are left out.",
        "properties": {
          "event_id": {
            "type": "integer",
            "format": "int64"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "action": {
            "type": "string",
            "description": "Such as `auth.sign_out`."
          },
          "sentence": {
            "type": "string",
            "description": "What happened, with `{target}` and `{related}` standing for those things."
          },
          "actor_type": {
            "type": "string"
          },
          "actor_id": {
            "type": "string",
            "format": "uuid"
          },
          "actor_name": {
            "type": "string"
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "description": "Only for people who can see the whole audit log."
          },
          "actor_link": {
            "type": "string",
            "description": "Path in the web app."
          },
          "target_type": {
            "type": "string"
          },
          "target_id": {
            "type": "string",
            "format": "uuid"
          },
          "target_name": {
            "type": "string"
          },
          "target_link": {
            "type": "string",
            "description": "Path in the web app."
          },
          "related_type": {
            "type": "string"
          },
          "related_id": {
            "type": "string",
            "format": "uuid"
          },
          "related_name": {
            "type": "string"
          },
          "related_link": {
            "type": "string",
            "description": "Path in the web app."
          },
          "changes": {
            "type": "object",
            "description": "Old and new value by field. Only for people who can see the whole audit log.",
            "additionalProperties": {
              "type": "array",
              "minItems": 2,
              "maxItems": 2
            }
          },
          "via": {
            "type": "string",
            "description": "The AI client that made the change, when one did."
          },
          "ip": {
            "type": "string",
            "description": "Only for people who can see the whole audit log."
          },
          "user_agent": {
            "type": "string",
            "description": "Only for people who can see the whole audit log."
          }
        }
      }
    }
  }
}
