# Code generated by generate_bundle.go; DO NOT EDIT. # Source: openapi-split.yaml components: securitySchemes: bearer: bearerFormat: bearer token description: |- Unkey uses bearer tokens for authentication. Public integrations use root keys, while the dashboard proxy uses short-lived JWTs. To authenticate, include the token in the Authorization header of each request: ``` Authorization: Bearer unkey_123 ``` Root keys have specific permissions attached to them, controlling what operations they can perform. Legacy permissions use tuple strings like `api.*.create_key`; resource permissions use Unkey Resource Names plus actions, like `unkey:v1:ws_123:keyspaces/*#create_key`. Security best practices: - Keep root keys secure and never expose them in client-side code - Use different root keys for different environments - Rotate keys periodically, especially after team member departures - Create keys with minimal necessary permissions following least privilege principle - Monitor key usage with audit logs. scheme: bearer type: http x-speakeasy-name-override: rootKey portalSession: description: |- Browser session cookie for the Customer Portal. Set by `portal.exchangeSession` and sent automatically by the browser on `portal.*` requests. Portal sessions are scoped to a single end user (external identity) and can only access the `portal.*` routes. in: cookie name: portal_session type: apiKey schemas: V2AnalyticsGetRatelimitsRequestBody: type: object required: - query properties: query: type: string description: | SQL query to execute against your rate limit analytics data. Queries may reference only the five public aliases: `ratelimits_v1`, `ratelimits_per_minute_v1`, `ratelimits_per_hour_v1`, `ratelimits_per_day_v1`, or `ratelimits_per_month_v1`. Physical `default.*` table names are unsupported. CTEs, subqueries, UNION, and EXCEPT are supported. Queries are always restricted to the authenticated workspace. Wildcard analytics permission can read every namespace in that workspace; namespace-scoped permissions automatically restrict results to the permitted namespace IDs. Workspace retention and query limits apply. example: "SELECT namespace_id, COUNT(*) AS total FROM ratelimits_v1 WHERE namespace_id = 'rlns_123' GROUP BY namespace_id" V2AnalyticsGetRatelimitsResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2AnalyticsGetRatelimitsResponseData" BadRequestErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BadRequestErrorDetails" description: Error response for invalid requests that cannot be processed due to client-side errors. This typically occurs when request parameters are missing, malformed, or fail validation rules. The response includes detailed information about the specific errors in the request, including the location of each error and suggestions for fixing it. When receiving this error, check the 'errors' array in the response for specific validation issues that need to be addressed before retrying. UnauthorizedErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when authentication has failed or credentials are missing. This occurs when: - No authentication token is provided in the request - The provided token is invalid, expired, or malformed - The token format doesn't match expected patterns To resolve this error, ensure you're including a valid root key in the Authorization header. ForbiddenErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when the provided credentials are valid but lack sufficient permissions for the requested operation. This occurs when: - The root key doesn't have the required permissions for this endpoint - The operation requires elevated privileges that the current key lacks - Access to the requested resource is restricted based on workspace settings To resolve this error, ensure your root key has the necessary permissions or contact your workspace administrator. PreconditionFailedErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when one or more conditions specified in the request headers are not met. This typically occurs when: - Using conditional requests with If-Match or If-None-Match headers - The resource version doesn't match the expected value - Optimistic concurrency control detects a conflict To resolve this error, fetch the latest version of the resource and retry with updated conditions. UnprocessableEntityErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when the request is syntactically valid but cannot be processed due to semantic constraints or resource limitations. This occurs when: - A query exceeds execution time limits - A query uses more memory than allowed - A query scans too many rows - A query result exceeds size limits The request syntax is correct, but the operation cannot be completed due to business rules or resource constraints. Review the error details for specific limitations and adjust your request accordingly. TooManyRequestsErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when the client has sent too many requests in a given time period. This occurs when you've exceeded a rate limit or quota for the resource you're accessing. The rate limit resets automatically after the time window expires. To avoid this error: - Implement exponential backoff when retrying requests - Cache results where appropriate to reduce request frequency - Check the error detail message for specific quota information - Contact support if you need a higher quota for your use case InternalServerErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when an unexpected error occurs on the server. This indicates a problem with Unkey's systems rather than your request. When you encounter this error: - The request ID in the response can help Unkey support investigate the issue - The error is likely temporary and retrying may succeed - If the error persists, contact Unkey support with the request ID ServiceUnavailableErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when a required service is temporarily unavailable. This indicates that the service exists but cannot be reached or is not responding. When you encounter this error: - The service is likely experiencing temporary issues - Retrying the request after a short delay may succeed - If the error persists, the service may be undergoing maintenance - Contact Unkey support if the issue continues V2AnalyticsGetVerificationsRequestBody: type: object required: - query properties: query: type: string description: | SQL query to execute against your analytics data. Queries may reference only the five public aliases: `key_verifications_v1`, `key_verifications_per_minute_v1`, `key_verifications_per_hour_v1`, `key_verifications_per_day_v1`, or `key_verifications_per_month_v1`. Physical `default.*` table names are unsupported. Only SELECT queries are allowed. CTEs, subqueries, UNION, and EXCEPT are supported. example: "SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY" V2AnalyticsGetVerificationsResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2AnalyticsGetVerificationsResponseData" V2ApisCreateApiRequestBody: type: object required: - name properties: name: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z][a-zA-Z0-9._-]*$" description: | Unique identifier for this API namespace within your workspace. Use descriptive names like 'payment-service-prod' or 'user-api-dev' to clearly identify purpose and environment. example: payment-service-production additionalProperties: false V2ApisCreateApiResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2ApisCreateApiResponseData" additionalProperties: false V2ApisDeleteApiRequestBody: type: object required: - apiId properties: apiId: type: string minLength: 8 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which API namespace to permanently delete from your workspace. Must be a valid API ID that begins with 'api_' and exists within your workspace. Before proceeding, ensure you have the correct API ID and understand that this action cannot be undone. If you need to migrate functionality, create replacement keys in a new API namespace and update client applications before deletion. example: api_1234abcd additionalProperties: false V2ApisDeleteApiResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/EmptyResponse" additionalProperties: false NotFoundErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when the requested resource cannot be found. This occurs when: - The specified resource ID doesn't exist in your workspace - The resource has been deleted or moved - The resource exists but is not accessible with current permissions To resolve this error, verify the resource ID is correct and that you have access to it. V2ApisGetApiRequestBody: type: object required: - apiId properties: apiId: type: string minLength: 8 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which API to retrieve by its unique identifier. Must be a valid API ID that begins with 'api_' and exists within your workspace. example: api_1234abcd additionalProperties: false V2ApisGetApiResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2ApisGetApiResponseData" additionalProperties: false V2ApisListKeysRequestBody: type: object required: - apiId properties: apiId: type: string minLength: 1 description: | The API namespace whose keys you want to list. Returns all keys in this API, subject to pagination and filters. example: api_1234abcd limit: type: integer description: | Maximum number of keys to return per request. Balance between response size and number of pagination calls needed. default: 100 minimum: 1 maximum: 100 cursor: type: string description: | Pagination cursor from previous response to fetch next page. Use when `hasMore: true` in previous response. example: key_1234abcd externalId: type: string minLength: 1 description: | Filter keys by external ID to find keys for a specific user or entity. Must exactly match the externalId set during key creation. example: user_1234abcd decrypt: type: boolean description: |- When true, attempts to include the plaintext key value in the response. SECURITY WARNING: - This requires special permissions on the calling root key - Only works for keys created with 'recoverable: true' - Exposes sensitive key material in the response - Should only be used in secure administrative contexts - Never enable this in user-facing applications default: false revalidateKeysCache: type: boolean default: false description: |- EXPERIMENTAL: Skip the cache and fetch the keys directly from the database. This ensures you see the most recent state, including keys created moments ago. Use this when: - You've just created a key and need to display it immediately - You need absolute certainty about the current key state - You're debugging cache consistency issues This parameter comes with a performance cost and should be used sparingly. additionalProperties: false V2ApisListKeysResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2ApisListKeysResponseData" pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2AppsCreateAppRequestBody: type: object required: - project - name - slug properties: project: "$ref": "#/components/schemas/ResourceIdentifier" name: type: string minLength: 1 maxLength: 256 description: | Human-readable name for this app. Use a descriptive name like 'Payments API' to identify its purpose. example: Payments API slug: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2AppsCreateAppResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2AppsCreateAppResponseData" additionalProperties: false ConflictErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when the request conflicts with the current state of the resource. This occurs when: - Attempting to create a resource that already exists - Modifying a resource that has been changed by another operation - Violating unique constraints or business rules To resolve this error, check the current state of the resource and adjust your request accordingly. V2AppsDeleteAppRequestBody: type: object required: - project - app properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2AppsDeleteAppResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2AppsGetAppRequestBody: type: object required: - project - app properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2AppsGetAppResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/App" additionalProperties: false V2AppsListAppsRequestBody: type: object required: - project properties: project: "$ref": "#/components/schemas/ResourceIdentifier" limit: type: integer description: | Maximum number of apps to return per request. Balance between response size and number of pagination calls needed. default: 100 minimum: 1 maximum: 100 cursor: type: string description: | Pagination cursor from a previous response to fetch the next page. Use when `hasMore: true` in the previous response. example: app_1234abcd search: type: string maxLength: 256 description: Free-form text to filter apps. Returns apps whose ID, name, or slug contains the search string. Matching is case-insensitive. example: checkout additionalProperties: false V2AppsListAppsResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: type: array maxItems: 100 items: "$ref": "#/components/schemas/App" description: Array of apps in the project, ordered by app id. pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2AppsUpdateAppRequestBody: type: object required: - project - app properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" name: type: string minLength: 1 maxLength: 256 description: | New human-readable name for the app. Omit this field to leave the current name unchanged. example: Payments API slug: "$ref": "#/components/schemas/ResourceIdentifier" defaultBranch: type: string minLength: 1 maxLength: 256 description: | New default git branch deployments track for this app. Omit this field to leave the current branch unchanged. example: main deleteProtection: type: boolean description: | Enable or disable delete protection for the app. Omit this field to leave the current setting unchanged. example: true additionalProperties: false V2AppsUpdateAppResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/App" additionalProperties: false V2DeployCreateDeploymentRequestBody: type: object required: - project - app - branch - environmentSlug - dockerImage properties: project: type: string minLength: 1 description: Project slug example: "my-project" app: type: string minLength: 1 description: App slug within the project example: "default" keyspaceId: type: string description: Optional keyspace ID for authentication context example: "key_abc123" branch: type: string minLength: 1 description: Git branch name example: "main" environmentSlug: type: string minLength: 1 description: Environment slug (e.g., "production", "staging") example: "production" dockerImage: type: string minLength: 1 description: Docker image reference to deploy example: "ghcr.io/user/app:v1.0.0" gitCommit: $ref: "#/components/schemas/V2DeployGitCommit" description: Create a deployment from a pre-built Docker image V2DeployCreateDeploymentResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2DeployCreateDeploymentResponseData" V2DeployGetDeploymentRequestBody: type: object required: - deploymentId properties: deploymentId: type: string minLength: 1 description: Unique deployment identifier to retrieve example: "d_abc123xyz" pattern: "^d_[a-zA-Z0-9]+$" V2DeployGetDeploymentResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2DeployGetDeploymentResponseData" V2DeploymentsCreateDeploymentRequestBody: type: object required: - project - app - environment properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" git: "$ref": "#/components/schemas/DeploymentSourceGit" image: "$ref": "#/components/schemas/DeploymentSourceImage" deployment: "$ref": "#/components/schemas/DeploymentSourceDeployment" additionalProperties: false oneOf: - required: - image - required: - git - required: - deployment description: Create a deployment. Provide exactly one of git, image, or deployment. V2DeploymentsCreateDeploymentResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2DeploymentsCreateDeploymentResponseData" V2DeploymentsGetDeploymentRequestBody: type: object required: - deploymentId properties: deploymentId: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false description: Retrieve a single deployment, including its status and runtime configuration. V2DeploymentsGetDeploymentResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/Deployment" V2DeploymentsListDeploymentsRequestBody: type: object properties: project: "$ref": "#/components/schemas/ResourceIdentifier" description: | Restrict results to a single project, identified by its ID or slug. Required when filtering by `app` or `environment`. app: "$ref": "#/components/schemas/ResourceIdentifier" description: | Restrict results to a single app, identified by its ID or slug. Requires `project` to also be set. environment: "$ref": "#/components/schemas/ResourceIdentifier" description: | Restrict results to a single environment, identified by its ID or slug. Requires `project` and `app` to also be set. status: type: array maxItems: 13 items: "$ref": "#/components/schemas/DeploymentStatus" description: | Restrict results to deployments in any of the given lifecycle statuses. Omit to return deployments in every status. example: ["ready", "failed"] limit: type: integer description: | Maximum number of deployments to return per request. Balance between response size and number of pagination calls needed. default: 100 minimum: 1 maximum: 100 cursor: type: string description: | Pagination cursor from a previous response to fetch the next page. Use when `hasMore: true` in the previous response. additionalProperties: false description: | Filter deployments within a workspace. All filters are optional; with none set, every deployment in the workspace is returned, newest first. V2DeploymentsListDeploymentsResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: type: array maxItems: 100 items: "$ref": "#/components/schemas/Deployment" description: Array of deployments, ordered newest first. pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2DeploymentsPromoteDeploymentRequestBody: type: object required: - deploymentId properties: deploymentId: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false description: Promote a ready deployment to become the current deployment for its environment. V2DeploymentsPromoteDeploymentResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2DeploymentsRollbackDeploymentRequestBody: type: object required: - deploymentId properties: deploymentId: "$ref": "#/components/schemas/ResourceIdentifier" description: | The deployment to roll back TO. Its app's current deployment is used as the rollback source automatically. additionalProperties: false description: Roll live traffic back to a previous deployment. V2DeploymentsRollbackDeploymentResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2DeploymentsStartDeploymentRequestBody: type: object required: - deploymentId properties: deploymentId: "$ref": "#/components/schemas/ResourceIdentifier" description: The stopped deployment to start. additionalProperties: false description: Start a stopped preview deployment so it serves traffic again. V2DeploymentsStartDeploymentResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2DeploymentsStopDeploymentRequestBody: type: object required: - deploymentId properties: deploymentId: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false description: Stop a running preview deployment to free up resources. V2DeploymentsStopDeploymentResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2EnvironmentsGetEnvironmentRequestBody: type: object required: - project - app - environment properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2EnvironmentsGetEnvironmentResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/Environment" additionalProperties: false V2EnvironmentsListEnvironmentVariablesRequestBody: type: object required: - project - app - environment properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" limit: type: integer minimum: 1 maximum: 100 default: 100 description: Maximum number of variables to return per request. cursor: type: string minLength: 1 maxLength: 1024 description: | Pagination cursor from a previous response to fetch the next page. Use when `hasMore: true` in the previous response. additionalProperties: false V2EnvironmentsListEnvironmentVariablesResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: type: array items: "$ref": "#/components/schemas/EnvironmentVariable" pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2EnvironmentsListEnvironmentsRequestBody: type: object required: - project - app properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2EnvironmentsListEnvironmentsResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: type: array items: "$ref": "#/components/schemas/Environment" description: Array of environments in the app, ordered by environment id. additionalProperties: false V2EnvironmentsRemoveEnvironmentVariablesRequestBody: type: object required: - project - app - environment - variables properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" variables: type: array minItems: 1 maxItems: 50 items: type: string minLength: 1 maxLength: 256 pattern: "^[A-Za-z_][A-Za-z0-9_]*$" description: | The name of a variable to remove. Must be a POSIX shell name: letters, digits, and underscores only, and must not start with a digit. example: LOG_LEVEL description: | The names of the variables to remove. Keys that exist are deleted; keys that are not present are ignored, since their absence already matches the requested state. Duplicate keys collapse to a single removal. The whole operation is atomic: if any part fails the environment is left unchanged. Limited to 50 variables per request. additionalProperties: false V2EnvironmentsRemoveEnvironmentVariablesResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2EnvironmentsSetEnvironmentVariablesRequestBody: type: object required: - project - app - environment - variables properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" variables: type: array maxItems: 50 items: "$ref": "#/components/schemas/EnvironmentVariableInput" description: | The variables to upsert. Each entry is created if its key is new or fully overwritten if the key already exists. Existing variables whose keys are not in this list are left untouched, unless `prune` is true. Each entry is written exactly as sent, never merged with the current state. Only `value` is required; omitted optional fields (`kind`, `description`) fall back to their defaults rather than any previous value, so overwriting a variable without a `description` clears it. Each key may appear at most once; a duplicate key is rejected with a 400. The whole operation is atomic: if any part fails the environment is left unchanged. All values are encrypted at rest. Limited to 50 variables per request. prune: type: boolean default: false description: |- Optional. Defaults to false. When false, the variables above are upserted and any existing variable not in the list is kept. When true, this becomes a full replace: after upserting, every variable not in the list is deleted. Combined with an empty `variables` list, `prune: true` resets the entire environment by deleting every variable. additionalProperties: false V2EnvironmentsSetEnvironmentVariablesResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2EnvironmentsUpdateSettingsRequestBody: type: object required: - project - app - environment properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" dockerfile: type: - string - "null" minLength: 1 maxLength: 500 description: | Path to the Dockerfile used for builds. Omit to leave unchanged; set null to clear and fall back to Railpack. example: ./Dockerfile rootDirectory: type: string minLength: 1 maxLength: 500 description: | The directory your app lives in. Unkey builds from here. Use "." for the repository root, or set a subdirectory when your app is nested (e.g., services/api). Omit to leave unchanged. example: . buildCommand: type: - string - "null" minLength: 1 maxLength: 1000 description: | Overrides the build command auto-detected by Railpack. Omit to leave unchanged; set null to clear and fall back to auto-detection. example: pnpm --filter api build watchPaths: type: array maxItems: 10 items: type: string maxLength: 500 description: | Glob paths that trigger auto-deploys when changed. Omit to leave unchanged. autoDeploy: type: boolean description: | Whether pushes auto-deploy. Omit to leave unchanged. example: true port: type: integer minimum: 1 maximum: 65535 description: | Container port the app listens on. Omit to leave unchanged. example: 8080 vCpus: type: number format: double minimum: 0.25 multipleOf: 0.25 description: | CPU allocation in vCPUs. Minimum 0.25 (1/4 vCPU), in steps of 0.25. The upper bound is your workspace's per-instance quota; exceeding it returns 400. Omit to leave unchanged. example: 1 memoryMib: type: integer minimum: 256 multipleOf: 256 description: | Memory allocation in MiB. Minimum 256, in steps of 256. The upper bound is your workspace's per-instance quota; exceeding it returns 400. Omit to leave unchanged. example: 512 storageMib: type: integer minimum: 0 multipleOf: 512 description: | Ephemeral storage allocation in MiB, in steps of 512 (0 for none). The upper bound is your workspace's per-instance quota; exceeding it returns 400. Omit to leave unchanged. example: 1024 command: type: array maxItems: 10 items: type: string maxLength: 4096 description: | Override container entrypoint command. Omit to leave unchanged. healthcheck: description: | HTTP healthcheck configuration. Omit to leave unchanged; set null to remove. anyOf: - "$ref": "#/components/schemas/EnvironmentHealthcheck" - type: "null" shutdownSignal: "$ref": "#/components/schemas/EnvironmentShutdownSignal" description: | Signal sent to the container on shutdown. Omit to leave unchanged. upstreamProtocol: "$ref": "#/components/schemas/EnvironmentUpstreamProtocol" description: | Protocol used to reach the upstream container. Omit to leave unchanged. openapiSpecPath: type: - string - "null" minLength: 1 maxLength: 512 pattern: '^(/[\w\-]+)+(\.[\w]+)?$' description: | Path to the OpenAPI spec file within the build. Must start with a slash. Omit to leave unchanged; set null to clear. example: /openapi.yaml regions: type: array minItems: 1 maxItems: 5 items: "$ref": "#/components/schemas/EnvironmentRegion" description: | Desired set of regions with per-region replica bounds. Omit to leave regions unchanged; when present, this replaces the full set (regions absent from the list are removed). At least one region is required; an empty list is rejected because an environment cannot have zero regions. additionalProperties: false V2EnvironmentsUpdateSettingsResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2GatewayListPoliciesRequestBody: type: object required: - project - app - environment properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2GatewayListPoliciesResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2GatewayListPoliciesResponseData" additionalProperties: false V2GatewaySetPoliciesRequestBody: type: object required: - project - app - environment - policies properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" policies: type: array maxItems: 50 items: "$ref": "#/components/schemas/Policy" description: |- The environment's complete policy list, in evaluation order. Every call replaces all stored policies with exactly this list; an empty list removes every policy. The operation is atomic: if any policy is invalid, nothing is written. An environment can hold at most 50 policies. additionalProperties: false V2GatewaySetPoliciesResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2GatewayUpdatePolicyRequestBody: type: object required: - project - app - environment - policyId properties: project: "$ref": "#/components/schemas/ResourceIdentifier" app: "$ref": "#/components/schemas/ResourceIdentifier" environment: "$ref": "#/components/schemas/ResourceIdentifier" policyId: type: string minLength: 1 maxLength: 512 description: |- Id of the policy to update, as returned by `gateway.listPolicies`. Ids are regenerated whenever `gateway.setPolicies` replaces the list, so list the policies first if you are unsure the id is current. example: pol_9d2Fk1LmQ name: type: string minLength: 1 maxLength: 256 description: |- New human-readable name. Omit to keep the current name. enabled: type: boolean description: |- Enable or disable the policy. Disabled policies are stored but skipped during evaluation. Omit to keep the current setting. match: type: - array - "null" maxItems: 10 items: "$ref": "#/components/schemas/MatchExpr" description: |- Replaces all match expressions. Set null to remove them so the policy applies to every request. Omit to keep the current expressions. keyauth: "$ref": "#/components/schemas/KeyauthPolicy" ratelimit: "$ref": "#/components/schemas/RatelimitPolicy" firewall: "$ref": "#/components/schemas/FirewallPolicy" openapi: "$ref": "#/components/schemas/OpenapiPolicy" additionalProperties: false description: |- Partial update of a single policy. Omitted fields keep their stored values; at least one updatable field must be provided. Providing one of `keyauth`, `ratelimit`, `firewall` or `openapi` replaces the policy's rule entirely, including switching its type; at most one may be set. V2GatewayUpdatePolicyResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2IdentitiesCreateIdentityRequestBody: type: object required: - externalId properties: externalId: type: string minLength: 1 maxLength: 255 pattern: "^[a-zA-Z0-9_.-]+$" description: | Creates an identity using your system's unique identifier for a user, organization, or entity. Must be stable and unique across your workspace - duplicate externalIds return CONFLICT errors. This identifier links Unkey identities to your authentication system, database records, or tenant structure. Avoid changing externalIds after creation as this breaks the link between your systems. Use consistent identifier patterns across your application for easier management and debugging. Accepts letters, numbers, underscores, dots, and hyphens for flexible identifier formats. Essential for implementing proper multi-tenant isolation and user-specific rate limiting. example: user_123 meta: type: object additionalProperties: true maxProperties: 100 description: | Stores arbitrary JSON metadata returned during key verification for contextual information. Eliminates additional database lookups during verification, improving performance for stateless services. Avoid storing sensitive data here as it's returned in verification responses. Large metadata objects increase verification latency and should stay under 10KB total size. Use this for subscription details, feature flags, user preferences, and organization information. Metadata is returned as-is whenever keys associated with this identity are verified. ratelimits: type: array maxItems: 50 items: "$ref": "#/components/schemas/RatelimitRequest" description: | Defines shared rate limits that apply to all keys belonging to this identity. Prevents abuse by users with multiple keys by enforcing consistent limits across their entire key portfolio. Essential for implementing fair usage policies and tiered access levels in multi-tenant applications. Rate limit counters are shared across all keys with this identity, regardless of how many keys the user creates. During verification, specify which named limits to check for enforcement. Identity rate limits supplement any key-specific rate limits that may also be configured. - Each named limit can have different thresholds and windows When verifying keys, you can specify which limits you want to use and all keys attached to this identity will share the limits, regardless of which specific key is used. V2IdentitiesCreateIdentityResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2IdentitiesCreateIdentityResponseData" V2IdentitiesDeleteIdentityRequestBody: type: object properties: identity: type: string minLength: 1 description: The ID of the identity to delete. This can be either the externalId (from your own system that was used during identity creation) or the identityId (the internal ID returned by the identity service). example: user_123 additionalProperties: false required: - identity V2IdentitiesDeleteIdentityResponseBody: type: object description: Empty response object. A successful response indicates the identity was deleted successfully. properties: meta: "$ref": "#/components/schemas/Meta" required: - meta V2IdentitiesGetIdentityRequestBody: type: object properties: identity: type: string minLength: 1 description: The ID of the identity to retrieve. This can be either the externalId (from your own system that was used during identity creation) or the identityId (the internal ID returned by the identity service). example: user_abc123 additionalProperties: false required: - identity V2IdentitiesGetIdentityResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/Identity" V2IdentitiesListIdentitiesRequestBody: type: object properties: limit: type: integer minimum: 1 maximum: 100 default: 100 description: The maximum number of identities to return in a single request. Use this to control response size and loading performance. example: 50 cursor: type: string description: Pagination cursor from a previous response. Use this to fetch subsequent pages of results when the response contains a cursor value. example: cursor_eyJrZXkiOiJrZXlfMTIzNCJ9 search: type: string maxLength: 256 description: Free-form text to filter identities. Returns identities whose ID or external ID contains the search string. Matching is case-insensitive. example: user_123 additionalProperties: false V2IdentitiesListIdentitiesResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2IdentitiesListIdentitiesResponseData" pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2IdentitiesUpdateIdentityRequestBody: type: object properties: identity: type: string minLength: 1 description: The ID of the identity to update. Accepts either the externalId (your system-generated identifier) or the identityId (internal identifier returned by the identity service). example: user_123 meta: type: object additionalProperties: true maxProperties: 100 description: | Replaces all existing metadata with this new metadata object. Omitting this field preserves existing metadata, while providing an empty object clears all metadata. Avoid storing sensitive data here as it's returned in verification responses. Large metadata objects increase verification latency and should stay under 10KB total size. example: name: Alice Smith email: alice@example.com plan: premium ratelimits: type: array maxItems: 50 items: $ref: "#/components/schemas/RatelimitRequest" description: | Replaces all existing identity rate limits with this complete list of rate limits. Omitting this field preserves existing rate limits, while providing an empty array removes all rate limits. These limits are shared across all keys belonging to this identity, preventing abuse through multiple keys. Rate limit changes take effect immediately but may take up to 30 seconds to propagate across all regions. example: - name: requests limit: 1000 duration: 3600000 autoApply: true additionalProperties: false required: - identity V2IdentitiesUpdateIdentityResponseBody: type: object required: - data - meta properties: data: "$ref": "#/components/schemas/Identity" meta: "$ref": "#/components/schemas/Meta" V2KeysAddPermissionsRequestBody: type: object required: - keyId - permissions properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key receives the additional permissions using the database identifier returned from `keys.createKey`. Do not confuse this with the actual API key string that users include in requests. example: key_2cGKbMxRyIzhCxo1Idjz8q permissions: type: array minItems: 1 maxItems: 1000 description: | Grants additional permissions to the key through direct assignment or automatic creation. Duplicate permissions are ignored automatically, making this operation idempotent. Adding permissions never removes existing permissions or role-based permissions. Any permissions that do not exist will be auto created if the root key has permissions, otherwise this operation will fail with a 403 error. items: type: string minLength: 3 pattern: ^[a-zA-Z0-9_:\-\.\*]+$ description: Specify the permission by its slug. additionalProperties: false V2KeysAddPermissionsResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysAddPermissionsResponseData" V2KeysAddRolesRequestBody: type: object required: - keyId - roles properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key receives the additional roles using the database identifier returned from `createKey`. Do not confuse this with the actual API key string that users include in requests. Added roles supplement existing roles and permissions without replacing them. Role assignments take effect immediately but may take up to 30 seconds to propagate across all regions. example: key_2cGKbMxRyIzhCxo1Idjz8q roles: type: array minItems: 1 maxItems: 100 description: | Assigns additional roles to the key through direct assignment to existing workspace roles. Operations are idempotent - adding existing roles has no effect and causes no errors. All roles must already exist in the workspace - roles cannot be created automatically. Invalid roles cause the entire operation to fail atomically, ensuring consistent state. items: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z][a-zA-Z0-9._-]*$" description: Specify the role by name. additionalProperties: false V2KeysAddRolesResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysAddRolesResponseData" V2KeysCreateKeyRequestBody: type: object required: - apiId properties: apiId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The API namespace this key belongs to. Keys from different APIs cannot access each other. example: api_1234abcd prefix: type: string minLength: 1 maxLength: 16 pattern: "^[a-zA-Z0-9_]+$" description: | Adds a visual identifier to the beginning of the generated key for easier recognition in logs and dashboards. The prefix becomes part of the actual key string (e.g., `prod_xxxxxxxxx`). Avoid using sensitive information in prefixes as they may appear in logs and error messages. example: prod name: type: string minLength: 1 maxLength: 255 description: | Sets a human-readable identifier for internal organization and dashboard display. Never exposed to end users, only visible in management interfaces and API responses. Avoid generic names like "API Key" when managing multiple keys for the same user or service. example: Payment Service Production Key byteLength: type: integer minimum: 16 maximum: 255 default: 16 description: | Controls the cryptographic strength of the generated key in bytes. Higher values increase security but result in longer keys that may be more annoying to handle. The default 16 bytes provides 2^128 possible combinations, sufficient for most applications. Consider 32 bytes for highly sensitive APIs, but avoid values above 64 bytes unless specifically required. example: 24 externalId: type: string minLength: 1 maxLength: 255 pattern: "^[a-zA-Z0-9_.-]+$" description: | Links this key to a user or entity in your system using your own identifier. Returned during verification to identify the key owner without additional database lookups. Essential for user-specific analytics, billing, and multi-tenant key management. Use your primary user ID, organization ID, or tenant ID for best results. Accepts letters, numbers, underscores, dots, and hyphens for flexible identifier formats. example: user_1234abcd meta: type: object additionalProperties: true maxProperties: 100 description: | Stores arbitrary JSON metadata returned during key verification for contextual information. Eliminates additional database lookups during verification, improving performance for stateless services. Avoid storing sensitive data here as it's returned in verification responses. Large metadata objects increase verification latency and should stay under 10KB total size. example: plan: enterprise featureFlags: betaAccess: true concurrentConnections: 10 customerName: Acme Corp billing: tier: premium renewal: "2024-12-31" roles: type: array maxItems: 100 items: type: string minLength: 1 maxLength: 100 pattern: ^[a-zA-Z0-9_:\-\.\*]+$ description: | Assigns existing roles to this key for permission management through role-based access control. Roles must already exist in your workspace before assignment. During verification, all permissions from assigned roles are checked against requested permissions. Roles provide a convenient way to group permissions and apply consistent access patterns across multiple keys. example: - api_admin - billing_reader permissions: type: array maxItems: 1000 items: type: string minLength: 1 maxLength: 100 pattern: "^[a-zA-Z][a-zA-Z0-9._-]*$" description: | Grants specific permissions directly to this key without requiring role membership. Wildcard permissions like `documents.*` grant access to all sub-permissions including `documents.read` and `documents.write`. Direct permissions supplement any permissions inherited from assigned roles. example: - documents.read - documents.write - settings.view expires: type: integer format: int64 minimum: 0 maximum: 4102444800000 description: | Sets when this key automatically expires as a Unix timestamp in milliseconds. Verification fails with code=EXPIRED immediately after this time passes. Omitting this field creates a permanent key that never expires. Avoid setting timestamps in the past as they immediately invalidate the key. Keys expire based on server time, not client time, which prevents timezone-related issues. Essential for trial periods, temporary access, and security compliance requiring key rotation. example: 1704067200000 credits: "$ref": "#/components/schemas/KeyCreditsData" description: | Controls usage-based limits through credit consumption with optional automatic refills. Unlike rate limits which control frequency, credits control total usage with global consistency. Essential for implementing usage-based pricing, subscription tiers, and hard usage quotas. Omitting this field creates unlimited usage, while setting null is not allowed during creation. ratelimits: type: array maxItems: 50 items: "$ref": "#/components/schemas/RatelimitRequest" description: | Defines time-based rate limits that protect against abuse by controlling request frequency. Unlike credits which track total usage, rate limits reset automatically after each window expires. Multiple rate limits can control different operation types with separate thresholds and windows. Essential for preventing API abuse while maintaining good performance for legitimate usage. example: - name: requests limit: 100 duration: 60000 autoApply: true - name: heavy_operations limit: 10 duration: 3600000 autoApply: false enabled: type: boolean default: true description: | Controls whether the key is active immediately upon creation. When set to `false`, the key exists but all verification attempts fail with `code=DISABLED`. Useful for pre-creating keys that will be activated later or for keys requiring manual approval. Most keys should be created with `enabled=true` for immediate use. example: true recoverable: type: boolean default: false description: | Controls whether the plaintext key is stored in an encrypted vault for later retrieval. When true, allows recovering the actual key value using keys.getKey with decrypt=true. When false, the key value cannot be retrieved after creation for maximum security. Only enable for development keys or when key recovery is absolutely necessary. example: false additionalProperties: false V2KeysCreateKeyResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysCreateKeyResponseData" V2KeysDeleteKeyRequestBody: type: object required: - keyId properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key to delete using the database identifier returned from `createKey`. Do not confuse this with the actual API key string that users include in requests. Deletion immediately invalidates the key, causing all future verification attempts to fail with `code=NOT_FOUND`. Key deletion triggers cache invalidation across all regions but may take up to 30 seconds to fully propagate. example: key_2cGKbMxRyIzhCxo1Idjz8q permanent: type: boolean default: false description: | Controls deletion behavior between recoverable soft-deletion and irreversible permanent erasure. Soft deletion (default) preserves key data for potential recovery through direct database operations. Permanent deletion completely removes all traces including hash values and metadata with no recovery option. Use permanent deletion only for regulatory compliance (GDPR), resolving hash collisions, or when reusing identical key strings. Permanent deletion cannot be undone and may affect analytics data that references the deleted key. Most applications should use soft deletion to maintain audit trails and prevent accidental data loss. example: false additionalProperties: false V2KeysDeleteKeyResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2KeysGetKeyRequestBody: type: object properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key to retrieve using the database identifier returned from `keys.createKey`. Do not confuse this with the actual API key string that users include in requests. Key data includes metadata, permissions, usage statistics, and configuration but never the plaintext key value unless `decrypt=true`. Find this ID in creation responses, key listings, dashboard, or verification responses. example: key_1234abcd decrypt: type: boolean default: false description: | Controls whether to include the plaintext key value in the response for recovery purposes. Only works for keys created with `recoverable=true` and requires the `decrypt_key` permission. Returned keys must be handled securely, never logged, cached, or stored insecurely. Use only for legitimate recovery scenarios like user password resets or emergency access. Most applications should keep this false to maintain security best practices and avoid accidental key exposure. Decryption requests are audited and may trigger security alerts in enterprise environments. additionalProperties: false required: - keyId V2KeysGetKeyResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/KeyResponseData" V2KeysMigrateKeysRequestBody: type: object properties: migrationId: type: string minLength: 3 maxLength: 255 description: Identifier of the configured migration provider/strategy to use (e.g., "your_company"). You will receive this from Unkey's support staff. example: your_company apiId: type: string minLength: 3 maxLength: 255 description: The ID of the API that the keys should be inserted into example: api_123456789 keys: type: array minItems: 1 items: $ref: "#/components/schemas/V2KeysMigrateKeyData" additionalProperties: false required: - migrationId - apiId - keys V2KeysMigrateKeysResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysMigrateKeysResponseData" V2KeysRemovePermissionsRequestBody: type: object required: - keyId - permissions properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key to remove permissions from using the database identifier returned from `keys.createKey`. Do not confuse this with the actual API key string that users include in requests. example: key_2cGKbMxRyIzhCxo1Idjz8q permissions: type: array minItems: 1 maxItems: 1000 description: | Removes direct permissions from the key without affecting role-based permissions. You can either use a permission slug, or the permission ID. After removal, verification checks for these permissions will fail unless granted through roles. items: type: string minLength: 3 pattern: ^[a-zA-Z0-9_:\-\.\*]+$ description: Specify the permission by its slug. additionalProperties: false V2KeysRemovePermissionsResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysRemovePermissionsResponseData" V2KeysRemoveRolesRequestBody: type: object required: - keyId - roles properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key loses the roles using the database identifier returned from createKey. Do not confuse this with the actual API key string that users include in requests. Removing roles only affects direct assignments, not permissions inherited from other sources. Role changes take effect immediately but may take up to 30 seconds to propagate across all regions. example: key_2cGKbMxRyIzhCxo1Idjz8q roles: type: array minItems: 1 maxItems: 100 description: | Removes direct role assignments from the key without affecting other role sources or permissions. Operations are idempotent - removing non-assigned roles has no effect and causes no errors. After removal, the key loses access to permissions that were only granted through these roles. Invalid role references cause the entire operation to fail atomically, ensuring consistent state. items: type: string pattern: ^[a-zA-Z0-9_:\-\.\*]+$ minLength: 3 maxLength: 255 description: Specify the role by name. additionalProperties: false V2KeysRemoveRolesResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysRemoveRolesResponseData" V2KeysRerollKeyRequestBody: type: object required: - keyId - expiration properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The database identifier of the key to reroll. This is the unique ID returned when creating or listing keys, NOT the actual API key token. You can find this ID in: - The response from `keys.createKey` - Key verification responses - The Unkey dashboard - API key listing endpoints example: key_2cGKbMxRyIzhCxo1Idjz8q expiration: type: integer format: int64 minimum: 0 maximum: 4102444800000 description: | Duration in milliseconds until the ORIGINAL key is revoked, starting from now. This parameter controls the overlap period for key rotation: - Set to `0` to revoke the original key immediately - Positive values keep the original key active for the specified duration - Allows graceful migration by giving users time to update their credentials Common overlap periods: - Immediate revocation: 0 - 1 hour grace period: 3600000 - 24 hours grace period: 86400000 - 7 days grace period: 604800000 - 30 days grace period: 2592000000 example: 86400000 V2KeysRerollKeyResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysRerollKeyResponseData" V2KeysSetPermissionsRequestBody: type: object required: - keyId - permissions properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key receives the additional permissions using the database identifier returned from `keys.createKey`. Do not confuse this with the actual API key string that users include in requests. example: key_2cGKbMxRyIzhCxo1Idjz8q permissions: type: array description: |- The permissions to set for this key. This is a complete replacement operation - it overwrites all existing direct permissions with this new set. Key behaviors: - Providing an empty array removes all direct permissions from the key - This only affects direct permissions - permissions granted through roles are not affected - All existing direct permissions not included in this list will be removed Any permissions that do not exist will be auto created if the root key has permissions, otherwise this operation will fail with a 403 error. items: type: string minLength: 3 pattern: ^[a-zA-Z0-9_:\-\.\*]+$ description: Specify the permission by its slug. additionalProperties: false V2KeysSetPermissionsResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysSetPermissionsResponseData" V2KeysSetRolesRequestBody: type: object required: - keyId - roles properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key gets the complete role replacement using the database identifier returned from createKey. Do not confuse this with the actual API key string that users include in requests. This is a wholesale replacement operation that removes all existing roles not included in the request. Role changes take effect immediately but may take up to 30 seconds to propagate across all regions. example: key_2cGKbMxRyIzhCxo1Idjz8q roles: type: array maxItems: 100 description: | Replaces all existing role assignments with this complete list of roles. This is a wholesale replacement operation, not an incremental update like add/remove operations. Providing an empty array removes all direct role assignments from the key. All roles must already exist in the workspace - roles cannot be created automatically. Invalid role references cause the entire operation to fail atomically, ensuring consistent state. items: type: string pattern: ^[a-zA-Z0-9_:\-\.\*]+$ minLength: 3 maxLength: 255 description: Specify the role by name. additionalProperties: false V2KeysSetRolesResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysSetRolesResponseData" V2KeysUpdateCreditsRequestBody: type: object required: - keyId - operation properties: keyId: type: string description: The ID of the key to update (begins with `key_`). This is the database reference ID for the key, not the actual API key string that users authenticate with. This ID uniquely identifies which key's credits will be updated. example: key_2cGKbMxRyIzhCxo1Idjz8q minLength: 3 value: type: - integer - "null" format: int64 minimum: 0 maximum: 9223372036854776000 description: | The credit value to use with the specified operation. The meaning depends on the operation: for 'set', this becomes the new remaining credits value; for 'increment', this amount is added to current credits; for 'decrement', this amount is subtracted from current credits. Set to null when using 'set' operation to make the key unlimited (removes usage restrictions entirely). When decrementing, if the result would be negative, remaining credits are automatically set to zero. Credits are consumed during successful key verification, and when credits reach zero, verification fails with `code=USAGE_EXCEEDED`. Required when using 'increment' or 'decrement' operations. Optional for 'set' operation (null creates unlimited usage). example: 1000 operation: type: string enum: - set - increment - decrement x-speakeasy-unknown-values: allow description: | Defines how to modify the key's remaining credits. Use 'set' to replace current credits with a specific value or unlimited usage, 'increment' to add credits for plan upgrades or credit purchases, and 'decrement' to reduce credits for refunds or policy violations. example: set additionalProperties: false V2KeysUpdateCreditsResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/KeyCreditsData" additionalProperties: false V2KeysUpdateKeyRequestBody: type: object required: - keyId properties: keyId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | Specifies which key to update using the database identifier returned from `createKey`. Do not confuse this with the actual API key string that users include in requests. example: key_2cGKbMxRyIzhCxo1Idjz8q name: type: - string - "null" minLength: 1 maxLength: 255 description: | Sets a human-readable name for internal organization and identification. Omitting this field leaves the current name unchanged, while setting null removes it entirely. Avoid generic names like "API Key" when managing multiple keys per user or service. example: Payment Service Production Key externalId: type: - string - "null" minLength: 1 maxLength: 255 pattern: "^[a-zA-Z0-9_.-]+$" description: | Links this key to a user or entity in your system for ownership tracking during verification. Omitting this field preserves the current association, while setting null disconnects the key from any identity. Essential for user-specific analytics, billing, and key management across multiple users. Supports letters, numbers, underscores, dots, and hyphens for flexible identifier formats. example: user_912a841d meta: type: - object - "null" additionalProperties: true maxProperties: 100 description: | Stores arbitrary JSON metadata returned during key verification. Omitting this field preserves existing metadata, while setting null removes all metadata entirely. Avoid storing sensitive data here as it's returned in verification responses. Large metadata objects increase verification latency and should stay under 10KB total size. example: plan: enterprise limits: storage: 500GB compute: 1000 minutes/month features: [analytics, exports, webhooks] hasAcceptedTerms: true billing: cycle: monthly next_billing: "2024-01-15" preferences: timezone: "UTC" notifications: true lastBillingDate: "2023-10-15" expires: type: - integer - "null" format: int64 minimum: 0 maximum: 4102444800000 description: | Sets when this key automatically expires as a Unix timestamp in milliseconds. Verification fails with code=EXPIRED immediately after this time passes. Omitting this field preserves the current expiration, while setting null makes the key permanent. Avoid setting timestamps in the past as they immediately invalidate the key. Keys expire based on server time, not client time, which prevents timezone-related issues. Active sessions continue until their next verification attempt after expiry. example: 1704067200000 credits: "$ref": "#/components/schemas/UpdateKeyCreditsData" description: | Controls usage-based limits for this key through credit consumption. Omitting this field preserves current credit settings, while setting null enables unlimited usage. Cannot configure refill settings when credits is null, and refillDay requires monthly interval. Essential for implementing usage-based pricing and subscription quotas. ratelimits: type: array maxItems: 50 items: "$ref": "#/components/schemas/RatelimitRequest" description: | Defines time-based rate limits that protect against abuse by controlling request frequency. Omitting this field preserves existing rate limits, while setting null removes all rate limits. Unlike credits which track total usage, rate limits reset automatically after each window expires. Multiple rate limits can control different operation types with separate thresholds and windows. enabled: type: boolean description: | Controls whether the key is currently active for verification requests. When set to `false`, all verification attempts fail with `code=DISABLED` regardless of other settings. Omitting this field preserves the current enabled status. Useful for temporarily suspending access during billing issues, security incidents, or maintenance windows without losing key configuration. example: true roles: type: array maxItems: 100 items: type: string minLength: 1 maxLength: 100 pattern: ^[a-zA-Z0-9_:\-\.\*]+$ description: | Assigns existing roles to this key for permission management through role-based access control. Roles must already exist in your workspace before assignment. During verification, all permissions from assigned roles are checked against requested permissions. Roles provide a convenient way to group permissions and apply consistent access patterns across multiple keys. example: - api_admin - billing_reader permissions: type: array maxItems: 1000 items: type: string minLength: 3 maxLength: 100 pattern: ^[a-zA-Z0-9_:\-\.\*]+$ description: | Grants specific permissions directly to this key without requiring role membership. Wildcard permissions like `documents.*` grant access to all sub-permissions including `documents.read` and `documents.write`. Direct permissions supplement any permissions inherited from assigned roles. example: - documents.read - documents.write - settings.view additionalProperties: false V2KeysUpdateKeyResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2KeysVerifyKeyRequestBody: type: object additionalProperties: false required: - key properties: key: type: string minLength: 1 maxLength: 512 x-unkey-redact: true description: | The API key to verify, exactly as provided by your user. Include any prefix - even small changes will cause verification to fail. example: sk_1234abcdef tags: type: array items: type: string minLength: 1 maxLength: 512 maxItems: 20 description: | Attaches metadata tags for analytics and monitoring without affecting verification outcomes. Enables segmentation of API usage in dashboards by endpoint, client version, region, or custom dimensions. Use 'key=value' format for compatibility with most analytics tools and clear categorization. Avoid including sensitive data in tags as they may appear in logs and analytics reports. example: - endpoint=/users/profile - method=GET - region=us-east-1 - clientVersion=2.3.0 - feature=premium permissions: type: string minLength: 1 maxLength: 1000 description: | Checks if the key has the specified permission(s) using a query syntax. Supports single permissions, logical operators (AND, OR), and parentheses for grouping. Examples: - Single permission: "documents.read" - Multiple permissions: "documents.read AND documents.write" - Complex queries: "(documents.read OR documents.write) AND users.view" Verification fails if the key lacks the required permissions through direct assignment or role inheritance. example: "documents.read AND users.view" credits: "$ref": "#/components/schemas/KeysVerifyKeyCredits" ratelimits: type: array items: "$ref": "#/components/schemas/KeysVerifyKeyRatelimit" description: | Enforces time-based rate limiting during verification to prevent abuse and ensure fair usage. Omitting this field skips rate limit checks entirely, relying only on configured key rate limits. Multiple rate limits can be checked simultaneously, each with different costs and temporary overrides. Rate limit checks are optimized for performance but may allow brief bursts during high concurrency. migrationId: type: string maxLength: 256 description: Migrate keys on demand from your previous system. Reach out for migration support at support@unkey.dev example: "m_1234abcd" V2KeysVerifyKeyResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2KeysVerifyKeyResponseData" additionalProperties: false V2KeysWhoamiRequestBody: type: object properties: key: type: string minLength: 1 maxLength: 512 x-unkey-redact: true description: | The complete API key string provided by you, including any prefix. Never log, cache, or store API keys in your system as they provide full access to user resources. Include the full key exactly as provided - even minor modifications will cause a not found error. example: sk_1234abcdef5678 additionalProperties: false required: - key V2KeysWhoamiResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/KeyResponseData" V2LivenessResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2LivenessResponseData" V2PermissionsCreatePermissionRequestBody: type: object required: - name - slug properties: name: type: string minLength: 1 maxLength: 512 description: | Creates a permission with this human-readable name that describes its purpose. Names must be unique within your workspace to prevent conflicts during assignment. Use clear, semantic names that developers can easily understand when building authorization logic. Consider using hierarchical naming conventions like 'resource.action' for better organization. Examples: 'users.read', 'billing.write', 'analytics.view', 'admin.manage' example: "users.read" slug: type: string minLength: 1 maxLength: 128 pattern: "^[a-zA-Z][a-zA-Z0-9._-]*$" description: | Creates a URL-safe identifier for this permission that can be used in APIs and integrations. Must start with a letter and contain only letters, numbers, periods, underscores, and hyphens. Slugs are often used in REST endpoints, configuration files, and external integrations. Should closely match the name but in a format suitable for technical usage. Must be unique within your workspace to ensure reliable permission lookups. Keep slugs concise but descriptive for better developer experience. example: "users-read" description: type: string maxLength: 512 description: | Provides detailed documentation of what this permission grants access to. Include information about affected resources, allowed actions, and any important limitations. This internal documentation helps team members understand permission scope and security implications. Not visible to end users - designed for development teams and security audits. Consider documenting: - What resources can be accessed - What operations are permitted - Any conditions or limitations - Related permissions that might be needed example: "Grants read-only access to user profile information, account settings, and subscription status." additionalProperties: false V2PermissionsCreatePermissionResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2PermissionsCreatePermissionResponseData" additionalProperties: false V2PermissionsCreateRoleRequestBody: type: object required: - name properties: name: type: string minLength: 1 maxLength: 512 pattern: "^[a-zA-Z][a-zA-Z0-9._-]*$" description: | The unique name for this role. Must be unique within your workspace and clearly indicate the role's purpose. Use descriptive names like 'admin', 'editor', or 'billing_manager'. Examples: 'admin.billing', 'support.readonly', 'developer.api', 'manager.analytics' example: "support.readonly" description: type: string maxLength: 512 description: | Provides comprehensive documentation of what this role encompasses and what access it grants. Include information about the intended use case, what permissions should be assigned, and any important considerations. This internal documentation helps team members understand role boundaries and security implications. Not visible to end users - designed for administration teams and access control audits. Consider documenting: - The role's intended purpose and scope - What types of users should receive this role - What permissions are typically associated with it - Any security considerations or limitations - Related roles that might be used together example: "Provides read-only access for customer support representatives. Includes permissions to view user accounts, support tickets, and basic analytics. Does not include access to billing, admin functions, or data modification capabilities." additionalProperties: false V2PermissionsCreateRoleResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2PermissionsCreateRoleResponseData" additionalProperties: false V2PermissionsDeletePermissionRequestBody: type: object required: - permission properties: permission: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z][a-zA-Z0-9._-]*$" description: | Specifies which permission to permanently delete from your workspace. This can be a permission ID or a permission slug. WARNING: Deleting a permission has immediate and irreversible consequences: - All API keys with this permission will lose that access immediately - All roles containing this permission will have it removed - Any verification requests checking for this permission will fail - This action cannot be undone Before deletion, ensure you: - Have updated any keys or roles that depend on this permission - Have migrated to alternative permissions if needed - Have notified affected users about the access changes example: perm_1234567890abcdef additionalProperties: false V2PermissionsDeletePermissionResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2PermissionsDeleteRoleRequestBody: type: object required: - role properties: role: type: string pattern: ^[a-zA-Z0-9_:\-\.\*]+$ minLength: 3 maxLength: 255 description: | Unique identifier of the role to permanently delete from your workspace. Must either be a valid role ID that begins with 'role_' or the given role name and exists within your workspace. WARNING: Deletion is immediate and irreversible with significant consequences: - All API keys assigned this role will lose the associated permissions - Access to resources protected by this role's permissions will be denied - Any authorization logic depending on this role will start failing - Historical analytics referencing this role remain intact Before deletion, ensure: - You've updated any dependent authorization logic or code - You've migrated any keys to use alternative roles or direct permissions - You've notified relevant team members of the access changes example: role_dns_manager additionalProperties: false V2PermissionsDeleteRoleResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2PermissionsGetPermissionRequestBody: type: object required: - permission properties: permission: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z][a-zA-Z0-9._-]*$" description: | The unique identifier of the permission to retrieve. Must be a valid permission ID that begins with 'perm_' and exists within your workspace. example: perm_1234567890abcdef additionalProperties: false V2PermissionsGetPermissionResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/Permission" additionalProperties: false V2PermissionsGetRoleRequestBody: type: object required: - role properties: role: type: string minLength: 3 maxLength: 255 pattern: ^[a-zA-Z0-9_:\-\.\*]+$ description: | Unique identifier of the role to permanently delete from your workspace. Must either be a valid role ID that begins with 'role_' or the given role name and exists within your workspace. Use this endpoint to verify role details, check its current permissions, or retrieve metadata. Returns complete role information including all assigned permissions for comprehensive access review. example: role_1234567890abcdef additionalProperties: false V2PermissionsGetRoleResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/Role" additionalProperties: false V2PermissionsListPermissionsRequestBody: type: object properties: cursor: type: string maxLength: 1024 description: | Pagination cursor from a previous response to fetch the next page of permissions. Include this value when you need to retrieve additional permissions beyond the initial response. Each response containing more results than the requested limit includes a cursor for subsequent pages. Leave empty or omit this field to start from the beginning of the permission list. Cursors are temporary and may expire - always handle cases where a cursor becomes invalid. example: "eyJrZXkiOiJwZXJtXzEyMzQifQ==" limit: type: integer minimum: 1 maximum: 100 default: 100 description: Maximum number of permissions to return in a single response. example: 50 search: type: string maxLength: 256 description: Free-form text to filter permissions. Returns permissions whose ID, name, slug, or description contains the search string. Matching is case-insensitive. example: documents additionalProperties: false V2PermissionsListPermissionsResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2PermissionsListPermissionsResponseData" pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2PermissionsListRolesRequestBody: type: object properties: limit: type: integer minimum: 1 maximum: 100 default: 100 description: | Maximum number of roles to return in a single response. Use smaller values for faster response times and better UI performance. Use larger values when you need to process many roles efficiently. Results exceeding this limit will be paginated with a cursor for continuation. example: 50 cursor: type: string maxLength: 1024 description: | Pagination cursor from a previous response to fetch the next page of roles. Include this when you need to retrieve additional roles beyond the first page. Each response containing more results will include a cursor value that can be used here. Leave empty or omit this field to start from the beginning of the role list. example: "eyJrZXkiOiJyb2xlXzEyMzQifQ==" search: type: string maxLength: 256 description: Free-form text to filter roles. Returns roles whose ID, name, or description contains the search string. Matching is case-insensitive. example: admin additionalProperties: false V2PermissionsListRolesResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2PermissionsListRolesResponseData" pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2PortalCreateSessionRequestBody: type: object required: - slug - externalId - permissions properties: slug: type: string minLength: 3 maxLength: 64 pattern: "^[a-z0-9][a-z0-9-]*[a-z0-9]$" description: | The human-readable slug of the portal configuration to create the session against. Identifies which app's portal the end user will access. Must be 3-64 characters, lowercase alphanumeric and hyphens only, must not start or end with a hyphen, and must not contain consecutive hyphens. example: my-portal externalId: type: string minLength: 1 maxLength: 256 description: | The end user's identifier in the customer's system. Accepts arbitrary string values (user IDs, emails, UUIDs, etc.). example: user_123 permissions: type: array items: type: string enum: - "keys:read" - "keys:create" - "keys:reroll" - "analytics:read" minItems: 1 description: | The capabilities granted to the end user in the Portal, from a fixed vocabulary. All capabilities are scoped to this end user: key capabilities (`keys:*`) apply only to keys the end user owns within the keyspace configured on the portal configuration, and `analytics:read` returns only the end user's own verification events. An end user can never see another identity's keys or analytics. Tab visibility is derived from the capabilities: - Keys tab: any `keys:*` capability - Analytics tab: `analytics:read` - Docs tab: visible when any capability is present example: ["keys:read", "keys:reroll", "analytics:read"] preview: type: boolean default: false description: | When true, creates a preview session for testing the portal experience. additionalProperties: false V2PortalCreateSessionResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2PortalCreateSessionResponseData" additionalProperties: false V2PortalExchangeSessionRequestBody: type: object required: - sessionId properties: sessionId: type: string minLength: 1 x-unkey-redact: true description: | The session token ID received from `portal.createSession`. Must be valid, unexpired, and not previously exchanged. example: pst_abc123def456 additionalProperties: false V2PortalExchangeSessionResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2PortalExchangeSessionResponseData" additionalProperties: false V2PortalGetVerificationsRequestBody: type: object required: - startTime - endTime properties: startTime: type: integer format: int64 description: | Start of the query window as a unix timestamp in milliseconds (inclusive). example: 1704067200000 endTime: type: integer format: int64 description: | End of the query window as a unix timestamp in milliseconds (exclusive). Bucket granularity (minute, hour, or day) is chosen automatically from the window size. example: 1704672000000 keyId: type: string description: | Optional. Restrict results to a single key. The key must belong to the authenticated end user; results are always scoped to the session identity regardless of this value. example: key_1234abcd additionalProperties: false V2PortalGetVerificationsResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: type: array description: | Zero-filled verification timeseries for the authenticated end user, ordered by time ascending. Buckets with no verifications are present with zero counts so the series is contiguous across the requested window. items: $ref: "#/components/schemas/V2PortalGetVerificationsDataPoint" additionalProperties: false V2PortalListKeysRequestBody: type: object properties: limit: type: integer description: | Maximum number of keys to return per request. Balance between response size and number of pagination calls needed. default: 100 minimum: 1 maximum: 100 cursor: type: string description: | Pagination cursor from a previous response to fetch the next page. Use when `hasMore: true` in the previous response. example: key_1234abcd additionalProperties: false V2PortalListKeysResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2PortalListKeysResponseData" pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2ProjectsCreateProjectRequestBody: type: object required: - name - slug properties: name: type: string minLength: 1 maxLength: 256 description: | Human-readable name for this project. Use a descriptive name like 'Payments Service' to identify its purpose. example: Payments Service slug: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2ProjectsCreateProjectResponseBody: type: object required: - meta - data properties: meta: $ref: "#/components/schemas/Meta" data: $ref: "#/components/schemas/V2ProjectsCreateProjectResponseData" additionalProperties: false V2ProjectsDeleteProjectRequestBody: type: object required: - project properties: project: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2ProjectsDeleteProjectResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/EmptyResponse" additionalProperties: false V2ProjectsGetProjectRequestBody: type: object required: - project properties: project: "$ref": "#/components/schemas/ResourceIdentifier" additionalProperties: false V2ProjectsGetProjectResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/Project" additionalProperties: false V2ProjectsListProjectsRequestBody: type: object properties: limit: type: integer description: | Maximum number of projects to return per request. Balance between response size and number of pagination calls needed. default: 100 minimum: 1 maximum: 100 cursor: type: string description: | Pagination cursor from a previous response to fetch the next page. Use when `hasMore: true` in the previous response. example: proj_1234abcd search: type: string maxLength: 256 description: Free-form text to filter projects. Returns projects whose ID, name, or slug contains the search string. Matching is case-insensitive. example: billing-service additionalProperties: false V2ProjectsListProjectsResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: type: array maxItems: 100 items: "$ref": "#/components/schemas/Project" description: Array of projects in the workspace, ordered by project id. pagination: "$ref": "#/components/schemas/Pagination" additionalProperties: false V2ProjectsUpdateProjectRequestBody: type: object required: - project properties: project: "$ref": "#/components/schemas/ResourceIdentifier" slug: "$ref": "#/components/schemas/ResourceIdentifier" name: type: string minLength: 1 maxLength: 256 description: | New human-readable name for the project. Omit this field to leave the current name unchanged. example: Payments Service deleteProtection: type: boolean description: | Enable or disable delete protection for the project. Omit this field to leave the current setting unchanged. example: true additionalProperties: false V2ProjectsUpdateProjectResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/Project" additionalProperties: false V2RatelimitDeleteOverrideRequestBody: description: |- Deletes an existing rate limit override. This permanently removes a custom rate limit rule, reverting affected identifiers back to the default rate limits for the namespace. Use this endpoint when you need to: - Remove special rate limit rules that are no longer needed - Reset entities back to standard rate limits - Clean up temporary overrides - Remove outdated tiering or custom limit rules - Fix misconfigured overrides Once deleted, the override cannot be recovered, and the operation takes effect immediately. additionalProperties: false properties: namespace: description: The id or name of the namespace containing the override. type: string minLength: 1 maxLength: 255 identifier: description: |- The exact identifier pattern of the override to delete. This must match exactly as it was specified when creating the override. Important notes: - This is case-sensitive and must match exactly - Include any wildcards (*) that were part of the original pattern - For example, if the override was created for 'premium_*', you must use 'premium_*' here, not a specific ID After deletion, any identifiers previously affected by this override will immediately revert to using the default rate limit for the namespace. type: string minLength: 1 maxLength: 255 required: - namespace - identifier type: object V2RatelimitDeleteOverrideResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2RatelimitDeleteOverrideResponseData" V2RatelimitGetOverrideRequestBody: description: |- Gets the configuration of an existing rate limit override. Use this to retrieve details about custom rate limit rules that have been created for specific identifiers within a namespace. This endpoint is useful for: - Verifying override configurations - Checking current limits for specific entities - Auditing rate limit policies - Debugging rate limiting behavior - Retrieving override settings for modification additionalProperties: false properties: namespace: description: The id or name of the namespace containing the override. type: string minLength: 1 maxLength: 255 identifier: description: |- The exact identifier pattern for the override you want to retrieve. This must match exactly as it was specified when creating the override. Important notes: - This is case-sensitive and must match exactly - Include any wildcards (*) that were part of the original pattern - For example, if the override was created for 'premium_*', you must use 'premium_*' here, not a specific ID like 'premium_user1' This field is used to look up the specific override configuration for this pattern. type: string minLength: 1 maxLength: 255 required: - namespace - identifier type: object V2RatelimitGetOverrideResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/RatelimitOverride" V2RatelimitLimitRequestBody: additionalProperties: false properties: namespace: type: string minLength: 1 maxLength: 255 description: The id or name of the namespace. example: sms.sign_up cost: type: integer format: int64 minimum: 0 default: 1 description: | Sets how much of the rate limit quota this request consumes, enabling weighted rate limiting. Use higher values for resource-intensive operations and 0 for tracking without limiting. When accumulated cost exceeds the limit within the duration window, subsequent requests are rejected. Essential for implementing fair usage policies and preventing resource abuse through expensive operations. example: 5 duration: type: integer format: int64 minimum: 1000 maximum: 2592000000 description: | Sets the rate limit window duration in milliseconds after which the counter resets. Shorter durations enable faster recovery but may be less effective against sustained abuse. Common values include 60000 (1 minute), 3600000 (1 hour), and 86400000 (24 hours). Balance user experience with protection needs when choosing window sizes. example: 60000 identifier: type: string minLength: 1 maxLength: 255 description: | Defines the scope of rate limiting by identifying the entity being limited. Use user IDs for per-user limits, IP addresses for anonymous limiting, or API key IDs for per-key limits. Accepts letters, numbers, underscores, dots, colons, slashes, and hyphens for flexible identifier formats. The same identifier can be used across different namespaces to apply multiple rate limit types. Choose identifiers that provide appropriate granularity for your rate limiting strategy. example: "user_12345" limit: type: integer format: int64 minimum: 1 description: | Sets the maximum operations allowed within the duration window before requests are rejected. When this limit is reached, subsequent requests fail with `RATE_LIMITED` until the window resets. Balance user experience with resource protection when setting limits for different user tiers. Consider system capacity, business requirements, and fair usage policies in limit determination. example: 1000 required: - namespace - identifier - limit - duration type: object V2RatelimitLimitResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2RatelimitLimitResponseData" GoneErrorResponse: type: object required: - meta - error properties: meta: $ref: "#/components/schemas/Meta" error: $ref: "#/components/schemas/BaseError" description: |- Error response when the requested resource has been soft-deleted and is no longer available. This occurs when: - The resource has been marked as deleted but still exists in the database - The resource is intentionally unavailable but could potentially be restored - The resource cannot be restored through the API or dashboard To resolve this error, contact support if you need the resource restored. V2RatelimitListOverridesRequestBody: additionalProperties: false properties: namespace: description: The id or name of the rate limit namespace to list overrides for. type: string minLength: 1 maxLength: 255 cursor: description: Pagination cursor from a previous response. Include this when fetching subsequent pages of results. Each response containing more results than the requested limit will include a cursor value in the pagination object that can be used here. type: string limit: description: |- Maximum number of override entries to return in a single response. Use this to control response size and loading performance. - Lower values (10-20): Better for UI displays and faster response times - Higher values (50-100): Better for data exports or bulk operations - Default (10): Suitable for most dashboard views Results exceeding this limit will be paginated, with a cursor provided for fetching subsequent pages. type: integer default: 10 minimum: 1 maximum: 100 required: - namespace type: object V2RatelimitListOverridesResponseBody: type: object required: - meta - data - pagination properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2RatelimitListOverridesResponseData" pagination: "$ref": "#/components/schemas/Pagination" V2RatelimitMultiLimitRequestBody: type: array description: Array of rate limit checks to perform minItems: 1 maxItems: 100 items: "$ref": "#/components/schemas/V2RatelimitLimitRequestBody" V2RatelimitMultiLimitResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2RatelimitMultiLimitResponseData" V2RatelimitSetOverrideRequestBody: description: |- Sets a new or overwrites an existing rate limit override. Overrides allow you to apply special rate limit rules to specific identifiers, providing custom limits that differ from the default. Overrides are useful for: - Granting higher limits to premium users or trusted partners - Implementing stricter limits for suspicious or abusive users - Creating tiered access levels with different quotas - Implementing temporary rate limit adjustments - Prioritizing important clients with higher limits additionalProperties: false properties: namespace: description: The ID or name of the rate limit namespace. type: string minLength: 1 maxLength: 255 duration: description: |- The duration in milliseconds for the rate limit window. This defines how long the rate limit counter accumulates before resetting to zero. Considerations: - This can differ from the default duration for the namespace - Longer durations create stricter limits that take longer to reset - Shorter durations allow more frequent bursts of activity - Common values: 60000 (1 minute), 3600000 (1 hour), 86400000 (1 day) format: int64 type: integer minimum: 1000 identifier: description: |- Identifier of the entity receiving this custom rate limit. This can be: - A specific user ID for individual custom limits - An IP address for location-based rules - An email domain for organization-wide policies - Any other string that identifies the target entity Wildcards (*) can be used to create pattern-matching rules that apply to multiple identifiers. For example: - 'premium_*' would match all identifiers starting with 'premium_' - '*_admin' would match all identifiers ending with '_admin' - '*suspicious*' would match any identifier containing 'suspicious' More detailed information on wildcard pattern rules is available at https://www.unkey.com/docs/ratelimiting/overrides#wildcard-rules type: string minLength: 1 maxLength: 255 limit: description: |- The maximum number of requests allowed for this override. This defines the custom quota for the specified identifier(s). Special values: - Higher than default: For premium or trusted entities - Lower than default: For suspicious or abusive entities - 0: To completely block access (useful for ban implementation) This limit entirely replaces the default limit for matching identifiers. format: int64 type: integer minimum: 0 required: - namespace - identifier - limit - duration type: object V2RatelimitSetOverrideResponseBody: type: object required: - meta - data properties: meta: "$ref": "#/components/schemas/Meta" data: "$ref": "#/components/schemas/V2RatelimitSetOverrideResponseData" Meta: type: object required: - requestId properties: requestId: description: A unique id for this request. Always include this ID when contacting support about a specific API request. This identifier allows Unkey's support team to trace the exact request through logs and diagnostic systems to provide faster assistance. example: req_123 type: string additionalProperties: false description: Metadata object included in every API response. This provides context about the request and is essential for debugging, audit trails, and support inquiries. The `requestId` is particularly important when troubleshooting issues with the Unkey support team. V2AnalyticsGetRatelimitsResponseData: type: array description: Array of rate limit rows returned by the query. Fields vary based on the SQL SELECT clause. items: type: object additionalProperties: true description: Dynamic row with fields determined by the query. example: - namespace_id: "rlns_123" total: 1234 BadRequestErrorDetails: allOf: - $ref: "#/components/schemas/BaseError" - type: object properties: errors: description: List of individual validation errors that occurred in the request. Each error provides specific details about what failed validation, where the error occurred in the request, and suggestions for fixing it. This granular information helps developers quickly identify and resolve multiple issues in a single request without having to make repeated API calls. items: $ref: "#/components/schemas/ValidationError" type: array required: - errors description: Extended error details specifically for bad request (400) errors. This builds on the BaseError structure by adding an array of individual validation errors, making it easy to identify and fix multiple issues at once. BaseError: properties: detail: description: A human-readable explanation specific to this occurrence of the problem. This provides detailed information about what went wrong and potential remediation steps. The message is intended to be helpful for developers troubleshooting the issue. example: Property foo is required but is missing. type: string status: description: HTTP status code that corresponds to this error. This will match the status code in the HTTP response. Common codes include `400` (Bad Request), `401` (Unauthorized), `403` (Forbidden), `404` (Not Found), `409` (Conflict), and `500` (Internal Server Error). example: 404 format: int type: integer title: description: A short, human-readable summary of the problem type. This remains constant from occurrence to occurrence of the same problem and should be used for programmatic handling. example: Not Found type: string type: description: A URI reference that identifies the problem type. This provides a stable identifier for the error that can be used for documentation lookups and programmatic error handling. When followed, this URI should provide human-readable documentation for the problem type. example: https://unkey.com/docs/errors/unkey/resource/not_found type: string required: - title - detail - status - type type: object additionalProperties: false description: Base error structure following Problem Details for HTTP APIs (RFC 7807). This provides a standardized way to carry machine-readable details of errors in HTTP response content. ValidationError: additionalProperties: false properties: location: description: |- JSON path indicating exactly where in the request the error occurred. This helps pinpoint the problematic field or parameter. Examples include: - 'body.name' (field in request body) - 'body.items[3].tags' (nested array element) - 'path.apiId' (path parameter) - 'query.limit' (query parameter) Use this location to identify exactly which part of your request needs correction. type: string example: body.permissions[0].name message: description: Detailed error message explaining what validation rule was violated. This provides specific information about why the field or parameter was rejected, such as format errors, invalid values, or constraint violations. type: string example: Must be at least 3 characters long fix: description: A human-readable suggestion describing how to fix the error. This provides practical guidance on what changes would satisfy the validation requirements. Not all validation errors include fix suggestions, but when present, they offer specific remediation advice. type: string example: Ensure the name uses only alphanumeric characters, underscores, and hyphens required: - location - message type: object description: Individual validation error details. Each validation error provides precise information about what failed, where it failed, and how to fix it, enabling efficient error resolution. V2AnalyticsGetVerificationsResponseData: type: array description: Array of verification rows returned by the query. Fields vary based on the SQL SELECT clause. items: type: object additionalProperties: true description: Dynamic row with fields determined by the query. Can include any combination of fields like time, outcome, count, key_id, etc. example: - outcome: "VALID" count: 1234 time: 1696118400000 - outcome: "RATE_LIMITED" count: 56 time: 1696118400000 V2ApisCreateApiResponseData: type: object properties: apiId: type: string minLength: 8 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The unique identifier assigned to the newly created API. Use this ID for all subsequent operations including key creation, verification, and API management. Always begins with 'api_' followed by a unique alphanumeric sequence. Store this ID securely as it's required when: - Creating API keys within this namespace - Verifying keys associated with this API - Managing API settings and metadata - Listing keys belonging to this API This identifier is permanent and cannot be changed after creation. example: api_2cGKbMxRjIzhCxo1IdjH3a required: - apiId additionalProperties: false EmptyResponse: type: object additionalProperties: false description: Empty response object by design. A successful response indicates this operation was successfully executed. V2ApisGetApiResponseData: type: object properties: id: type: string minLength: 8 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The unique identifier of this API within Unkey's system. Used in all operations related to this API including key creation, verification, and management. Always begins with 'api_' followed by alphanumeric characters and underscores. This identifier is permanent and never changes after API creation. example: api_1234567890abcdef name: type: string minLength: 3 maxLength: 255 description: | The internal name of this API as specified during creation. Used for organization and identification within your workspace. Helps distinguish between different environments, services, or access tiers. Not visible to end users - this is purely for administrative purposes. example: payment-service-production required: - id - name additionalProperties: false V2ApisListKeysResponseData: type: array maxItems: 100 items: "$ref": "#/components/schemas/KeyResponseData" description: Array of API keys with complete configuration and metadata. Pagination: type: object properties: cursor: type: string minLength: 1 maxLength: 1024 description: | Opaque pagination token for retrieving the next page of results. Include this exact value in the cursor field of subsequent requests. Cursors are temporary and may expire after extended periods. example: eyJrZXkiOiJrZXlfMTIzNCIsInRzIjoxNjk5Mzc4ODAwfQ== hasMore: type: boolean description: | Indicates whether additional results exist beyond this page. When true, use the cursor to fetch the next page. When false, you have reached the end of the result set. example: true required: - hasMore additionalProperties: false description: Pagination metadata for list endpoints. Provides information necessary to traverse through large result sets efficiently using cursor-based pagination. KeyResponseData: type: object properties: keyId: type: string minLength: 8 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: Unique identifier for this key. example: key_1234567890abcdef start: type: string minLength: 1 maxLength: 50 description: First few characters of the key for identification. example: sk_test_abc123 enabled: type: boolean description: Whether the key is enabled or disabled. example: true name: type: string maxLength: 255 description: Human-readable name for this key. example: Production API Key x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true meta: type: object additionalProperties: true maxProperties: 100 description: Custom metadata associated with this key. example: x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true createdAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: Unix timestamp in milliseconds when key was created. example: 1701425400000 updatedAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: Unix timestamp in milliseconds when key was last updated. example: 1701425400000 x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true lastUsedAt: type: integer format: int64 minimum: 0 description: Unix timestamp in milliseconds when key was last used for verification. This is an approximated value, accurate to within 5 minutes. example: 1701425400000 x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true expires: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: Unix timestamp in milliseconds when key expires (if set). example: 1735689600000 x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true permissions: type: array items: type: string description: List of permission slugs granted to this key. example: - documents.read - documents.write x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true roles: type: array items: type: string description: List of roles assigned to this key. example: - editor - viewer x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true credits: "$ref": "#/components/schemas/KeyCreditsData" identity: "$ref": "#/components/schemas/Identity" x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true plaintext: type: string x-unkey-redact: true description: Decrypted key value (only when decrypt=true). x-go-type-skip-optional-pointer: true example: sk_test_abc123def456 x-go-type-skip-optional-pointer-with-omitzero: true ratelimits: type: array maxItems: 50 items: "$ref": "#/components/schemas/RatelimitResponse" x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - keyId - start - createdAt - enabled additionalProperties: false KeyCreditsData: type: object description: Credit configuration and remaining balance for this key. properties: remaining: type: - integer - "null" format: int64 minimum: 0 maximum: 9223372036854776000 description: Number of credits remaining (null for unlimited). example: 1000 refill: "$ref": "#/components/schemas/KeyCreditsRefill" x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - remaining additionalProperties: false Identity: type: object properties: id: type: string description: Identity ID externalId: type: string description: External identity ID meta: type: object additionalProperties: true description: Identity metadata x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true ratelimits: type: array description: Identity ratelimits items: "$ref": "#/components/schemas/RatelimitResponse" x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - externalId - id RatelimitResponse: type: object properties: id: type: string minLength: 8 maxLength: 255 pattern: "^rl_[a-zA-Z0-9_]+$" description: Unique identifier for this rate limit configuration. example: rl_1234567890abcdef name: type: string minLength: 1 maxLength: 128 description: Human-readable name for this rate limit. example: api_requests limit: type: integer format: int64 minimum: 1 maximum: 1000000 description: Maximum requests allowed within the time window. example: 1000 duration: type: integer format: int64 minimum: 1000 maximum: 2592000000 description: Rate limit window duration in milliseconds. example: 3600000 autoApply: type: boolean description: Whether this rate limit was automatically applied when verifying the key. example: true required: - id - name - limit - duration - autoApply additionalProperties: false KeyCreditsRefill: type: object description: Configuration for automatic credit refill behavior. properties: interval: type: string enum: - daily - monthly x-speakeasy-unknown-values: allow description: How often credits are automatically refilled. example: daily amount: type: integer format: int64 minimum: 1 maximum: 9223372036854776000 description: Number of credits to add during each refill cycle. example: 1000 refillDay: type: integer minimum: 1 maximum: 31 description: | Day of the month for monthly refills (1-31). Only required when interval is 'monthly'. For days beyond the month's length, refill occurs on the last day of the month. example: 15 x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - interval - amount additionalProperties: false ResourceIdentifier: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_-]+$" description: | Identifies a resource by either its unique ID or its slug. Accepts a prefixed ID (such as 'proj_' or 'app_') or a slug. example: proj_1234abcd V2AppsCreateAppResponseData: type: object required: - appId properties: appId: type: string minLength: 8 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The unique identifier of the newly created app, generated by Unkey. Always begins with 'app_' followed by a unique alphanumeric sequence. example: app_1234abcd additionalProperties: false App: type: object required: - id - name - slug - defaultBranch - isRolledBack - deleteProtection - createdAt properties: id: type: string description: | The unique identifier of the app, generated by Unkey. example: app_1234abcd name: type: string description: | Human-readable name for this app. example: Payments API slug: type: string description: | URL-safe handle for this app, unique within its project. Chosen at creation time. example: payments-api defaultBranch: type: string description: | The default git branch deployments track for this app. example: main currentDeploymentId: type: string description: | The identifier of the deployment currently serving this app. Omitted if the app has no active deployment yet. example: d_1234abcd x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true isRolledBack: type: boolean description: | Whether the app is currently serving a rolled-back deployment rather than its latest one. example: false deleteProtection: type: boolean description: | Whether delete protection is enabled for this app. When true, the app cannot be deleted until protection is disabled. example: false createdAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: | Unix timestamp in milliseconds when the app was created. example: 1704067200000 updatedAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: | Unix timestamp in milliseconds when the app was last updated. Omitted if the app has never been updated. example: 1704153600000 x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true additionalProperties: false V2DeployGitCommit: type: object description: Optional git commit information properties: commitSha: type: string description: Git commit SHA example: "a1b2c3d4e5f6" commitMessage: type: string description: Git commit message example: "feat: add new feature" authorHandle: type: string description: Git author handle/username example: "johndoe" authorAvatarUrl: type: string description: Git author avatar URL example: "https://avatars.githubusercontent.com/u/123456" timestamp: type: integer format: int64 description: Commit timestamp in milliseconds example: 1704067200000 V2DeployCreateDeploymentResponseData: type: object required: - deploymentId properties: deploymentId: type: string description: Unique deployment identifier example: "d_abc123xyz" V2DeployGetDeploymentResponseData: type: object required: - id - status properties: id: type: string description: Unique deployment identifier example: "d_abc123xyz" status: type: string description: Current deployment status enum: - UNSPECIFIED - PENDING - STARTING - BUILDING - DEPLOYING - NETWORK - FINALIZING - READY - FAILED - SKIPPED - AWAITING_APPROVAL - STOPPED - SUPERSEDED - CANCELLED example: "READY" x-speakeasy-unknown-values: allow errorMessage: type: string description: Error message if deployment failed example: "Failed to pull image: authentication required" hostnames: type: array items: type: string description: Hostnames associated with this deployment example: ["app.example.com", "api.example.com"] steps: type: array items: $ref: "#/components/schemas/V2DeployDeploymentStep" description: Deployment steps with status and messages V2DeployDeploymentStep: type: object properties: status: type: string description: Step status example: "completed" message: type: string description: Step message example: "Image pulled successfully" errorMessage: type: string description: Error message if step failed example: "Connection timeout" createdAt: type: integer format: int64 description: Unix timestamp in milliseconds example: 1704067200000 DeploymentSourceGit: type: object properties: branch: type: string maxLength: 256 description: Branch to build (its HEAD). Omit branch and commitSha to use the app's default branch. example: "main" commitSha: type: string maxLength: 40 description: Commit to build (full or abbreviated SHA). Takes precedence over branch. example: "9f2c1a7" repository: type: string pattern: "^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$" maxLength: 256 description: Build from a fork instead of the app's connected repository, as "owner/repo". Requires commitSha. example: "contributor/acme-api" description: Build from the app's connected GitHub repository. DeploymentSourceImage: type: object required: - dockerImage properties: dockerImage: type: string minLength: 1 pattern: "\\S" description: Docker image to deploy as-is. example: "ghcr.io/acme/api:v1.2.3" description: Deploy a prebuilt Docker image as-is. DeploymentSourceDeployment: type: object required: - deploymentId properties: deploymentId: "$ref": "#/components/schemas/ResourceIdentifier" description: Re-run an existing deployment. V2DeploymentsCreateDeploymentResponseData: type: object required: - deploymentId properties: deploymentId: type: string description: Unique deployment identifier. Poll deployments.getDeployment with this id to watch status. example: "d_abc123xyz" Deployment: type: object required: - id - status - isCurrent - environment - app - project - availableActions - regions - runtime - createdAt properties: id: type: string description: | The unique identifier of the deployment, generated by Unkey. example: d_1234abcd status: "$ref": "#/components/schemas/DeploymentStatus" isCurrent: type: boolean description: | True when this is the production deployment currently serving traffic, i.e. on api.acme.com. Only production deployments can be current, and at most one deployment is current. Rollbacks and promotions change which deployment is current and serves requests to api.acme.com. example: true environment: type: string description: Slug of the environment this deployment belongs to. example: production app: type: string description: Slug of the app this deployment belongs to. example: payments-api project: type: string description: Slug of the project this deployment belongs to. example: acme git: "$ref": "#/components/schemas/DeploymentGit" description: | Present for git-sourced deployments. Mutually exclusive with `docker`. docker: "$ref": "#/components/schemas/DeploymentDocker" description: | Present for image-sourced deployments. Mutually exclusive with `git`. availableActions: type: array items: "$ref": "#/components/schemas/DeploymentAction" description: | Lifecycle operations you are allowed to call on this deployment right now. Empty when none apply (e.g. while building or in a terminal state). example: ["stop"] regions: type: array items: type: string description: | Regions this deployment is configured to run in. Empty while the deployment has no scheduled regions yet. example: ["us-east-1", "eu-west-1"] error: "$ref": "#/components/schemas/DeploymentError" description: | Why the deployment failed. Present only when `status` is `failed`. domains: type: array items: type: string description: | Public hostnames this deployment is reachable at. example: ["kebap-app.unkey.app"] runtime: "$ref": "#/components/schemas/DeploymentRuntime" createdAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: | Unix timestamp in milliseconds when the deployment was created. example: 1704067200000 updatedAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: | Unix timestamp in milliseconds when the deployment was last updated. Omitted if the deployment has never been updated. example: 1704153600000 x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true additionalProperties: false DeploymentStatus: type: string enum: - pending - starting - building - deploying - network - finalizing - ready - failed - skipped - awaiting_approval - stopped - superseded - cancelled x-enum-varnames: - DeploymentStatusPending - DeploymentStatusStarting - DeploymentStatusBuilding - DeploymentStatusDeploying - DeploymentStatusNetwork - DeploymentStatusFinalizing - DeploymentStatusReady - DeploymentStatusFailed - DeploymentStatusSkipped - DeploymentStatusAwaitingApproval - DeploymentStatusStopped - DeploymentStatusSuperseded - DeploymentStatusCancelled description: | Current lifecycle status of the deployment. Poll until it reaches a terminal state: ready (serving), failed, skipped, superseded, stopped, or cancelled. example: ready DeploymentGit: type: object required: - commitSha properties: commitSha: type: string description: The git commit SHA this deployment was built from. example: 9f2c1a7d3b branch: type: string description: The git branch this deployment was built from. Omitted when unknown. example: main additionalProperties: false DeploymentDocker: type: object required: - image properties: image: type: string description: The Docker image this deployment runs. example: ghcr.io/acme/api:v1.2.3 additionalProperties: false DeploymentAction: type: string enum: - promote - rollback - stop - start x-enum-varnames: - DeploymentActionPromote - DeploymentActionRollback - DeploymentActionStop - DeploymentActionStart description: | A lifecycle operation that can be performed on the deployment in its current state, given its status, environment, and whether it is the current deployment. example: promote DeploymentError: type: object required: - code - step - message properties: code: "$ref": "#/components/schemas/DeploymentErrorCode" step: type: string description: | The pipeline step that failed (e.g. `building`, `deploying`, `starting`). example: deploying message: type: string description: | Human-readable description of why the deployment failed. For programmatic handling, use `code`. example: No schedulable regions configured. Please configure at least one schedulable region before deploying. additionalProperties: false DeploymentRuntime: type: object required: - vCpus - memoryMib - storageMib - port - command - shutdownSignal - upstreamProtocol properties: vCpus: type: number format: double description: | CPU allocation in vCPUs (1 = one vCPU, 0.5 = half a vCPU). example: 0.25 memoryMib: type: integer description: | Memory allocation in mebibytes. example: 256 storageMib: type: integer description: | Ephemeral storage allocation in mebibytes. example: 0 port: type: integer description: | Port the container listens on. example: 8080 command: type: array items: type: string description: | Container entrypoint command override. Empty when none is set. example: ["node", "server.js"] shutdownSignal: "$ref": "#/components/schemas/EnvironmentShutdownSignal" upstreamProtocol: "$ref": "#/components/schemas/EnvironmentUpstreamProtocol" healthcheck: "$ref": "#/components/schemas/EnvironmentHealthcheck" description: | HTTP health probe configuration. Omitted when no healthcheck is configured. additionalProperties: false DeploymentErrorCode: type: string enum: - no_schedulable_regions - invalid_runtime_settings - cpu_quota_exceeded - memory_quota_exceeded - storage_quota_exceeded - build_failed - unknown x-enum-varnames: - DeploymentErrorCodeNoSchedulableRegions - DeploymentErrorCodeInvalidRuntimeSettings - DeploymentErrorCodeCpuQuotaExceeded - DeploymentErrorCodeMemoryQuotaExceeded - DeploymentErrorCodeStorageQuotaExceeded - DeploymentErrorCodeBuildFailed - DeploymentErrorCodeUnknown description: | The reason a deployment failed. `unknown` means Unkey could not classify the failure; see `message` for details. example: no_schedulable_regions EnvironmentShutdownSignal: type: string enum: - SIGTERM - SIGINT - SIGQUIT - SIGKILL description: | Signal sent to the container on shutdown. example: SIGTERM EnvironmentUpstreamProtocol: type: string enum: - http1 - h2c description: | Protocol used to reach the container. example: http1 EnvironmentHealthcheck: type: object required: - method - path properties: method: type: string enum: - GET - POST description: | HTTP method used to probe the container. example: GET path: type: string minLength: 1 maxLength: 512 pattern: '^(/[\w\-]+)+(\.[\w]+)?$' description: | HTTP path probed on the container. Must start with a slash. example: /healthz intervalSeconds: type: integer minimum: 1 maximum: 3600 description: | How often the probe runs, in seconds. Defaults to 10 when omitted. example: 10 timeoutSeconds: type: integer minimum: 1 maximum: 3600 description: | Per-probe timeout, in seconds. Defaults to 5 when omitted. example: 2 failureThreshold: type: integer minimum: 1 maximum: 100 description: | Consecutive failures before the container is restarted. Defaults to 3 when omitted. example: 3 initialDelaySeconds: type: integer minimum: 0 maximum: 3600 description: | Delay before the first probe runs, in seconds. Defaults to 0 when omitted. example: 5 additionalProperties: false Environment: type: object required: - id - slug - description - deleteProtection - createdAt properties: id: type: string description: | The unique identifier of the environment, generated by Unkey. example: env_1234abcd slug: type: string description: | Human-readable slug of the environment, unique within its app. example: production description: type: string description: | Human-readable description of this environment. Empty string if none was provided. example: Production environment deleteProtection: type: boolean description: | Whether delete protection is enabled for this environment. When true, the environment cannot be deleted until protection is disabled. example: false createdAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: | Unix timestamp in milliseconds when the environment was created. example: 1704067200000 updatedAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: | Unix timestamp in milliseconds when the environment was last updated. Omitted if the environment has never been updated. example: 1704153600000 x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true runtime: "$ref": "#/components/schemas/EnvironmentRuntime" build: "$ref": "#/components/schemas/EnvironmentBuild" regions: type: array items: "$ref": "#/components/schemas/EnvironmentRegion" description: | Per-region deployment settings for this environment. Empty until regional settings are configured. additionalProperties: false EnvironmentRuntime: type: object description: | Runtime settings that control how the container runs. Omitted until the environment has runtime settings. required: - port - vCpus - memoryMib - storageMib - command - shutdownSignal - upstreamProtocol properties: port: type: integer description: | Port the container listens on. example: 8080 vCpus: type: number format: double description: | CPU allocation in vCPUs (1 = one vCPU, 0.5 = half a vCPU). example: 0.25 memoryMib: type: integer description: | Memory allocation in mebibytes. example: 256 storageMib: type: integer description: | Ephemeral storage allocation in mebibytes. example: 0 command: type: array items: type: string description: | Container entrypoint command override. example: ["node", "server.js"] healthcheck: "$ref": "#/components/schemas/EnvironmentHealthcheck" shutdownSignal: "$ref": "#/components/schemas/EnvironmentShutdownSignal" upstreamProtocol: "$ref": "#/components/schemas/EnvironmentUpstreamProtocol" openapiSpecPath: type: string description: | Path to the OpenAPI spec served by the container, if any. example: /openapi.yaml additionalProperties: false EnvironmentBuild: type: object description: | Build settings that control how the app is built. Omitted until the environment has build settings. required: - rootDirectory - watchPaths - autoDeploy properties: dockerfile: type: string description: | Path to the Dockerfile used to build the app, if any. example: Dockerfile rootDirectory: type: string description: | The directory the app is built from. "." for the repository root. example: . buildCommand: type: string description: | Overrides the build command auto-detected by Railpack, so monorepos can scope the build to a single app. Omitted when left to auto-detection or for Dockerfile builds. example: pnpm --filter api build watchPaths: type: array items: type: string description: | Paths that trigger a rebuild when changed. example: ["src/**"] autoDeploy: type: boolean description: | Whether pushes automatically trigger a deployment. example: true additionalProperties: false EnvironmentRegion: type: object description: Replica bounds for a single region the environment deploys to. required: - name - replicas properties: name: type: string minLength: 1 maxLength: 64 description: Region name, such as us-east-1. example: us-east-1 replicas: "$ref": "#/components/schemas/Replicas" additionalProperties: false Replicas: type: object description: Min and max replica bounds for autoscaling in a region. required: - min - max properties: min: type: integer description: Minimum number of replicas. example: 1 max: type: integer description: Maximum number of replicas. example: 3 additionalProperties: false EnvironmentVariable: type: object required: - key - kind - createdAt properties: key: type: string description: The variable name. example: DATABASE_URL kind: "$ref": "#/components/schemas/EnvironmentVariableKind" value: type: string x-unkey-redact: true description: | The decrypted plaintext value. Present only for `recoverable` variables. Omitted for `writeonly` variables, which can never be read back. x-go-type-skip-optional-pointer: true example: postgresql://user:pass@host:5432/db description: type: string description: Human-readable description. Omitted if none was provided. example: Primary database connection string x-go-type-skip-optional-pointer: true createdAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: Unix timestamp in milliseconds when the variable was created. example: 1704067200000 additionalProperties: false EnvironmentVariableKind: type: string enum: - recoverable - writeonly description: | How the value may be read back. `writeonly` values can never be read back through the API; `recoverable` values can be decrypted. Values are encrypted at rest either way. example: writeonly EnvironmentVariableInput: type: object description: A single environment variable to set. required: - key - value properties: key: type: string minLength: 1 maxLength: 256 pattern: "^[A-Za-z_][A-Za-z0-9_]*$" description: | The variable name. Must be a POSIX shell name: letters, digits, and underscores only, and must not start with a digit. Other names are unreachable from shells and most runtimes. example: DATABASE_URL value: type: string minLength: 1 maxLength: 16384 x-unkey-redact: true description: | The variable value. Always encrypted at rest. The limit is enforced server-side in UTF-8 bytes, so a multibyte value may be rejected before it reaches this code-point maximum. example: postgresql://user:pass@host:5432/db kind: allOf: - "$ref": "#/components/schemas/EnvironmentVariableKind" default: writeonly description: | How the value may be read back. Defaults to `writeonly`. description: type: string maxLength: 255 description: | Human-readable description of the variable. example: Primary database connection string additionalProperties: false V2GatewayListPoliciesResponseData: type: array maxItems: 50 description: The environment's gateway policies in evaluation order. items: "$ref": "#/components/schemas/PolicyResponse" PolicyResponse: type: object required: - id - name - enabled properties: id: type: string description: Server-generated policy id. Regenerated on every `gateway.setPolicies` call, so treat it as stable only until the environment's policies are next replaced. example: pol_2gJbXhAr4 name: type: string minLength: 1 maxLength: 256 description: Human-readable name shown in the dashboard. enabled: type: boolean description: Disabled policies are stored but skipped during evaluation. match: type: array maxItems: 10 items: "$ref": "#/components/schemas/MatchExpr" description: |- Optional request matchers. The policy applies only to requests matching all expressions; omitted when the policy applies to every request. keyauth: "$ref": "#/components/schemas/KeyauthPolicy" ratelimit: "$ref": "#/components/schemas/RatelimitPolicy" firewall: "$ref": "#/components/schemas/FirewallPolicy" openapi: "$ref": "#/components/schemas/OpenapiPolicy" additionalProperties: false description: |- A stored gateway policy as returned by list endpoints. Exactly one of `keyauth`, `ratelimit`, `firewall` or `openapi` is set. example: id: pol_2gJbXhAr4 name: Block internal paths enabled: true match: - path: path: prefix: /internal/ firewall: action: ACTION_DENY MatchExpr: type: object properties: path: "$ref": "#/components/schemas/PathMatch" method: "$ref": "#/components/schemas/MethodMatch" header: "$ref": "#/components/schemas/FieldMatch" queryParam: "$ref": "#/components/schemas/FieldMatch" additionalProperties: false description: |- A single request match expression. Exactly one of `path`, `method`, `header` or `queryParam` must be set. example: path: path: prefix: /api/ KeyauthPolicy: type: object required: - keyspaces properties: keyspaces: type: array minItems: 1 maxItems: 5 items: type: string minLength: 1 maxLength: 256 description: |- Keyspaces to verify keys against, referenced by id. All keyspaces must belong to your workspace. locations: type: array items: "$ref": "#/components/schemas/KeyLocation" description: |- Where to look for the key on incoming requests, tried in order. Defaults to the `Authorization Bearer` header when omitted. permissionQuery: type: string maxLength: 1000 description: |- Optional permission query the verified key must satisfy, e.g. `documents.read AND documents.write`. ratelimits: type: array maxItems: 10 items: "$ref": "#/components/schemas/KeyRatelimit" description: Rate limits applied during key verification. additionalProperties: false description: Verifies Unkey API keys on matching requests. example: keyspaces: - ks_1234abcd RatelimitPolicy: type: object required: - limit - windowMs - identifier properties: limit: type: integer format: int64 minimum: 1 description: Maximum number of requests per window. windowMs: type: integer format: int64 minimum: 1 description: Window duration in milliseconds. identifier: "$ref": "#/components/schemas/RatelimitIdentifier" additionalProperties: false description: Rate limits matching requests. example: limit: 100 windowMs: 60000 identifier: remoteIp: {} FirewallPolicy: type: object required: - action properties: action: type: string enum: - ACTION_DENY description: What to do with matching requests. additionalProperties: false description: Blocks matching requests. example: action: ACTION_DENY OpenapiPolicy: type: object additionalProperties: false description: |- Validates matching requests against the app's uploaded OpenAPI spec. Has no configuration of its own. If no spec has been uploaded for the deployment, the policy is a no-op and requests pass through unvalidated. example: {} PathMatch: type: object required: - path properties: path: "$ref": "#/components/schemas/StringMatch" additionalProperties: false description: Matches on the request path. MethodMatch: type: object required: - methods properties: methods: type: array minItems: 1 items: type: string enum: - GET - POST - PUT - PATCH - DELETE - HEAD - OPTIONS additionalProperties: false description: Matches when the request method is one of the listed methods. FieldMatch: type: object required: - name properties: name: type: string minLength: 1 maxLength: 256 present: type: boolean enum: - true description: Matches when the field is present, regardless of value. value: "$ref": "#/components/schemas/StringMatch" additionalProperties: false description: |- Matches a named request field (header or query parameter). Exactly one of `present` or `value` must be set. StringMatch: type: object properties: exact: type: string minLength: 1 maxLength: 1024 description: Matches when the input equals this value. prefix: type: string minLength: 1 maxLength: 1024 description: Matches when the input starts with this value. regex: type: string minLength: 1 maxLength: 1024 description: |- Matches when the input satisfies this RE2 regular expression. Invalid patterns are rejected when the policy is created. ignoreCase: type: boolean description: Compare case-insensitively. May accompany any match mode. additionalProperties: false description: |- String matcher. Exactly one of `exact`, `prefix` or `regex` must be set. example: prefix: /api/ ignoreCase: true KeyLocation: type: object properties: bearer: "$ref": "#/components/schemas/BearerTokenLocation" header: "$ref": "#/components/schemas/HeaderKeyLocation" queryParam: "$ref": "#/components/schemas/QueryParamKeyLocation" additionalProperties: false description: |- Where to look for the API key on incoming requests. Exactly one of `bearer`, `header` or `queryParam` must be set. example: bearer: {} KeyRatelimit: type: object required: - name properties: name: type: string minLength: 1 maxLength: 256 description: |- Name of a rate limit configured on the key or its identity, or the name of the inline override defined by `limit` and `duration`. limit: type: integer format: int64 minimum: 1 description: |- Inline override: maximum number of operations per window. Must be set together with `duration`. duration: type: integer format: int64 minimum: 1 description: |- Inline override: window duration in milliseconds. Must be set together with `limit`. cost: type: integer format: int64 minimum: 1 description: Cost charged against the limit per request. Defaults to 1. additionalProperties: false description: |- A rate limit applied during key verification. `limit` and `duration` must be set together or both omitted; a partial pair is rejected. example: name: requests limit: 100 duration: 60000 BearerTokenLocation: type: object additionalProperties: false description: Extract the key from the `Authorization Bearer` header. HeaderKeyLocation: type: object required: - name properties: name: type: string minLength: 1 maxLength: 256 stripPrefix: type: string maxLength: 256 description: Optional prefix removed from the header value before verification. additionalProperties: false description: Extract the key from a custom header. QueryParamKeyLocation: type: object required: - name properties: name: type: string minLength: 1 maxLength: 256 additionalProperties: false description: Extract the key from a query parameter. RatelimitIdentifier: type: object properties: remoteIp: "$ref": "#/components/schemas/RemoteIpKey" header: "$ref": "#/components/schemas/HeaderKey" authenticatedSubject: "$ref": "#/components/schemas/AuthenticatedSubjectKey" path: "$ref": "#/components/schemas/PathKey" principalField: "$ref": "#/components/schemas/PrincipalFieldKey" additionalProperties: false description: |- How requests are grouped for rate limiting. Exactly one of `remoteIp`, `header`, `authenticatedSubject`, `path` or `principalField` must be set. example: remoteIp: {} RemoteIpKey: type: object additionalProperties: false description: Rate limit by the client's IP address. HeaderKey: type: object required: - name properties: name: type: string minLength: 1 maxLength: 256 additionalProperties: false description: Rate limit by the value of a request header. AuthenticatedSubjectKey: type: object additionalProperties: false description: Rate limit by the authenticated subject (e.g. the verified key). PathKey: type: object additionalProperties: false description: Rate limit by the request path. PrincipalFieldKey: type: object required: - path properties: path: type: string minLength: 1 maxLength: 512 additionalProperties: false description: Rate limit by a field extracted from the authenticated principal. Policy: type: object required: - name - enabled properties: name: type: string minLength: 1 maxLength: 256 description: Human-readable name shown in the dashboard. enabled: type: boolean description: Disabled policies are stored but skipped during evaluation. match: type: array maxItems: 10 items: "$ref": "#/components/schemas/MatchExpr" description: |- Optional request matchers. The policy applies only to requests matching all expressions; omit to apply to every request. keyauth: "$ref": "#/components/schemas/KeyauthPolicy" ratelimit: "$ref": "#/components/schemas/RatelimitPolicy" firewall: "$ref": "#/components/schemas/FirewallPolicy" openapi: "$ref": "#/components/schemas/OpenapiPolicy" additionalProperties: false description: |- A gateway policy. Exactly one of `keyauth`, `ratelimit`, `firewall` or `openapi` must be set. The server generates an id for every policy it stores. example: name: Block internal paths enabled: true match: - path: path: prefix: /internal/ firewall: action: ACTION_DENY RatelimitRequest: type: object required: - name - limit - duration - autoApply properties: name: description: |- The name of this rate limit. This name is used to identify which limit to check during key verification. Best practices for limit names: - Use descriptive, semantic names like 'api_requests', 'heavy_operations', or 'downloads' - Be consistent with naming conventions across your application - Create separate limits for different resource types or operation costs - Consider using namespaced names for better organization (e.g., 'files.downloads', 'compute.training') You will reference this exact name when verifying keys to check against this specific limit. type: string example: api minLength: 3 maxLength: 128 limit: description: |- The maximum number of operations allowed within the specified time window. When this limit is reached, verification requests will fail with `code=RATE_LIMITED` until the window resets. The limit should reflect: - Your infrastructure capacity and scaling limitations - Fair usage expectations for your service - Different tier levels for various user types - The relative cost of the operations being limited Higher values allow more frequent access but may impact service performance. type: integer format: int64 minimum: 1 duration: description: |- The duration for each ratelimit window in milliseconds. This controls how long the rate limit counter accumulates before resetting. Common values include: - 1000 (1 second): For strict per-second limits on high-frequency operations - 60000 (1 minute): For moderate API usage control - 3600000 (1 hour): For less frequent but costly operations - 86400000 (24 hours): For daily quotas Shorter windows provide more frequent resets but may allow large burst usage. Longer windows provide more consistent usage patterns but take longer to reset after limit exhaustion. type: integer format: int64 minimum: 1000 autoApply: description: Whether this ratelimit should be automatically applied when verifying a key. type: boolean default: false V2IdentitiesCreateIdentityResponseData: type: object properties: identityId: type: string description: The unique identifier of the created identity. required: - identityId V2IdentitiesListIdentitiesResponseData: type: array items: "$ref": "#/components/schemas/Identity" description: List of identities matching the specified criteria. V2KeysAddPermissionsResponseData: type: array description: |- Complete list of all permissions directly assigned to the key (including both newly added permissions and those that were already assigned). This response includes: - All direct permissions assigned to the key (both pre-existing and newly added) - Both the permission ID and name for each permission Important notes: - This list does NOT include permissions granted through roles - For a complete permission picture, use `/v2/keys.getKey` instead - An empty array indicates the key has no direct permissions assigned items: "$ref": "#/components/schemas/Permission" Permission: type: object properties: id: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The unique identifier for this permission within Unkey's system. Generated automatically when the permission is created and used to reference this permission in API operations. Always begins with 'perm_' followed by alphanumeric characters and underscores. example: perm_1234567890abcdef name: type: string minLength: 1 maxLength: 512 description: | The human-readable name for this permission that describes its purpose. Should be descriptive enough for developers to understand what access it grants. Use clear, semantic names that reflect the resources or actions being permitted. Names must be unique within your workspace to avoid confusion and conflicts. example: "users.read" slug: pattern: ^[a-zA-Z0-9_:\-\.\*]+$ type: string minLength: 1 maxLength: 512 description: The unique URL-safe identifier for this permission. example: users-read description: type: string maxLength: 512 description: | Optional detailed explanation of what this permission grants access to. Helps team members understand the scope and implications of granting this permission. Include information about what resources can be accessed and what actions can be performed. Not visible to end users - this is for internal documentation and team clarity. example: "Allows reading user profile information and account details" x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - id - name - slug V2KeysAddRolesResponseData: type: array description: |- Complete list of all roles directly assigned to the key after the operation completes. The response includes: - All roles now assigned to the key (both pre-existing and newly added) - Both ID and name of each role for easy reference Important notes: - The response shows the complete current state after the addition - An empty array means the key has no roles assigned (unlikely after an add operation) - This only shows direct role assignments, not inherited or nested roles - Role permissions are not expanded in this response - use keys.getKey for full details items: "$ref": "#/components/schemas/Role" Role: type: object properties: id: type: string description: | The unique identifier for this role within Unkey's system. Generated automatically when the role is created and used to reference this role in API operations. Always begins with 'role_' followed by alphanumeric characters and underscores. example: role_1234567890abcdef name: type: string description: | The human-readable name for this role that describes its function. Should be descriptive enough for administrators to understand what access this role provides. Use clear, semantic names that reflect the job function or responsibility level. Names must be unique within your workspace to avoid confusion during role assignment. example: "support.readonly" description: type: string description: | Optional detailed explanation of what this role encompasses and what access it provides. Helps team members understand the role's scope, intended use cases, and security implications. Include information about what types of users should receive this role and what they can accomplish. Not visible to end users - this is for internal documentation and access control audits. example: "Provides read-only access for customer support representatives to view user accounts and support tickets" x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true permissions: type: array items: "$ref": "#/components/schemas/Permission" maxItems: 100 description: | Complete list of permissions currently assigned to this role. Each permission grants specific access rights that will be inherited by any keys or users assigned this role. Use this list to understand the full scope of access provided by this role. Permissions can be added or removed from roles without affecting the role's identity or other properties. Empty array indicates a role with no permissions currently assigned. x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - id - name additionalProperties: false V2KeysCreateKeyResponseData: type: object properties: keyId: type: string description: The unique identifier for this key in Unkey's system. This is NOT the actual API key, but a reference ID used for management operations like updating or deleting the key. Store this ID in your database to reference the key later. This ID is not sensitive and can be logged or displayed in dashboards. example: key_2cGKbMxRyIzhCxo1Idjz8q key: type: string x-unkey-redact: true description: "The full generated API key that should be securely provided to your user.\nSECURITY WARNING: This is the only time you'll receive the complete key - Unkey only stores a securely hashed version. Never log or store this value in your own systems; provide it directly to your end user via secure channels. After this API call completes, this value cannot be retrieved again (unless created with `recoverable=true`)." example: prod_2cGKbMxRjIzhCxo1IdjH3arELti7Sdyc8w6XYbvtcyuBowPT required: - keyId - key V2KeysMigrateKeyData: type: object properties: hash: type: string minLength: 3 description: The current hash of the key on your side example: your_already_hashed_key name: type: string minLength: 1 maxLength: 255 description: | Sets a human-readable identifier for internal organization and dashboard display. Never exposed to end users, only visible in management interfaces and API responses. Avoid generic names like "API Key" when managing multiple keys for the same user or service. example: Payment Service Production Key externalId: type: string minLength: 1 maxLength: 255 description: | Links this key to a user or entity in your system using your own identifier. Returned during verification to identify the key owner without additional database lookups. Essential for user-specific analytics, billing, and multi-tenant key management. Use your primary user ID, organization ID, or tenant ID for best results. Accepts letters, numbers, underscores, dots, and hyphens for flexible identifier formats. example: user_1234abcd meta: type: object additionalProperties: true maxProperties: 100 description: | Stores arbitrary JSON metadata returned during key verification for contextual information. Eliminates additional database lookups during verification, improving performance for stateless services. Avoid storing sensitive data here as it's returned in verification responses. Large metadata objects increase verification latency and should stay under 10KB total size. example: plan: enterprise featureFlags: betaAccess: true concurrentConnections: 10 customerName: Acme Corp billing: tier: premium renewal: "2024-12-31" roles: type: array maxItems: 100 items: type: string minLength: 1 maxLength: 100 description: | Assigns existing roles to this key for permission management through role-based access control. Roles must already exist in your workspace before assignment. During verification, all permissions from assigned roles are checked against requested permissions. Roles provide a convenient way to group permissions and apply consistent access patterns across multiple keys. example: - api_admin - billing_reader permissions: type: array maxItems: 1000 items: type: string minLength: 1 maxLength: 100 description: | Grants specific permissions directly to this key without requiring role membership. Wildcard permissions like `documents.*` grant access to all sub-permissions including `documents.read` and `documents.write`. Direct permissions supplement any permissions inherited from assigned roles. example: - documents.read - documents.write - settings.view expires: type: integer format: int64 minimum: 0 maximum: 4102444800000 description: | Sets when this key automatically expires as a Unix timestamp in milliseconds. Verification fails with code=EXPIRED immediately after this time passes. Omitting this field creates a permanent key that never expires. Avoid setting timestamps in the past as they immediately invalidate the key. Keys expire based on server time, not client time, which prevents timezone-related issues. Essential for trial periods, temporary access, and security compliance requiring key rotation. enabled: type: boolean default: true description: | Controls whether the key is active immediately upon creation. When set to `false`, the key exists but all verification attempts fail with `code=DISABLED`. Useful for pre-creating keys that will be activated later or for keys requiring manual approval. Most keys should be created with `enabled=true` for immediate use. example: true credits: "$ref": "#/components/schemas/KeyCreditsData" description: | Controls usage-based limits through credit consumption with optional automatic refills. Unlike rate limits which control frequency, credits control total usage with global consistency. Essential for implementing usage-based pricing, subscription tiers, and hard usage quotas. Omitting this field creates unlimited usage, while setting null is not allowed during creation. ratelimits: type: array maxItems: 50 items: "$ref": "#/components/schemas/RatelimitRequest" description: | Defines time-based rate limits that protect against abuse by controlling request frequency. Unlike credits which track total usage, rate limits reset automatically after each window expires. Multiple rate limits can control different operation types with separate thresholds and windows. Essential for preventing API abuse while maintaining good performance for legitimate usage. example: - name: requests limit: 100 duration: 60000 autoApply: true - name: heavy_operations limit: 10 duration: 3600000 autoApply: false additionalProperties: false required: - hash V2KeysMigrateKeysResponseData: type: object required: - migrated - failed properties: migrated: type: array description: Successfully migrated keys with their hash and generated keyId items: "$ref": "#/components/schemas/V2KeysMigrateKeysMigration" failed: type: array description: Hashes that could not be migrated (e.g., already exist in the system) items: type: string description: The hash that failed to migrate example: sha256_ghi789jkl012 V2KeysMigrateKeysMigration: type: object required: - hash - keyId properties: hash: type: string description: The hash provided in the migration request example: sha256_abc123def456 keyId: type: string description: The unique identifier for this key in Unkey's system. This is NOT the actual API key, but a reference ID used for management operations like updating or deleting the key. Store this ID in your database to reference the key later. This ID is not sensitive and can be logged or displayed in dashboards. example: key_2cGKbMxRyIzhCxo1Idjz8q V2KeysRemovePermissionsResponseData: type: array description: |- Complete list of all permissions directly assigned to the key after the removal operation (remaining permissions only). Notes: - This list does NOT include permissions granted through roles - For a complete permission picture, use `/v2/keys.getKey` instead - An empty array indicates the key has no direct permissions assigned - Any cached versions of the key are immediately invalidated to ensure consistency - Changes to permissions take effect within seconds for new verifications items: "$ref": "#/components/schemas/Permission" V2KeysRemoveRolesResponseData: type: array description: |- Complete list of all roles directly assigned to the key after the removal operation completes. The response includes: - The remaining roles still assigned to the key (after removing the specified roles) - Both ID and name for each role for easy reference Important notes: - The response reflects the current state after the removal operation - An empty array indicates the key now has no roles assigned - This only shows direct role assignments - Role permissions are not expanded in this response - use keys.getKey for full details - Changes take effect immediately for new verifications but cached sessions may retain old permissions briefly items: "$ref": "#/components/schemas/Role" V2KeysRerollKeyResponseData: type: object properties: keyId: type: string description: | The unique identifier for the newly created key. This is NOT the actual API key token, but a reference ID for management operations. Store this ID to: - Update or revoke the key later - Track the key in your database - Display in admin dashboards (safe to log) Note: This is a new ID - the original key retains its own ID. example: key_2cGKbMxRyIzhCxo1Idjz8q key: type: string x-unkey-redact: true description: | The newly generated API key token (the actual secret that authenticates requests). **SECURITY CRITICAL:** - This is the only time you'll receive the complete key - Unkey stores only a hashed version (unless the original key was created with `recoverable=true`) - Never log, store, or expose this value in your systems - Transmit directly to the end user via secure channels only - If lost and not recoverable, you must reroll or create a new key The key format follows: `[prefix]_[random_bytes]` - Prefix is extracted from the original key or uses API default - Random bytes follow API configuration (default: 16 bytes) This is NOT the keyId - it's the actual secret token used for authentication. example: prod_2cGKbMxRjIzhCxo1IdjH3arELti7Sdyc8w6XYbvtcyuBowPT required: - keyId - key V2KeysSetPermissionsResponseData: type: array description: |- Complete list of all permissions now directly assigned to the key after the set operation has completed. The response includes: - The comprehensive, updated set of direct permissions (reflecting the complete replacement) - Both ID and name for each permission for easy reference Important notes: - This only shows direct permissions, not those granted through roles - An empty array means the key has no direct permissions assigned - For a complete permission picture including roles, use keys.getKey instead items: "$ref": "#/components/schemas/Permission" V2KeysSetRolesResponseData: type: array description: |- Complete list of all roles now directly assigned to the key after the set operation has completed. The response includes: - The comprehensive, updated set of roles (reflecting the complete replacement) - Both ID and name for each role for easy reference Important notes: - This response shows the final state after the complete replacement - If you provided an empty array in the request, this will also be empty - This only shows direct role assignments on the key - Role permissions are not expanded in this response - use keys.getKey for complete details - An empty array indicates the key now has no roles assigned at all items: "$ref": "#/components/schemas/Role" UpdateKeyCreditsData: type: - object - "null" description: Credit configuration and remaining balance for this key. properties: remaining: type: - integer - "null" format: int64 minimum: 0 maximum: 9223372036854776000 description: Number of credits remaining (null for unlimited). This also clears the refilling schedule. example: 1000 refill: "$ref": "#/components/schemas/UpdateKeyCreditsRefill" additionalProperties: false UpdateKeyCreditsRefill: type: - object - "null" description: Configuration for automatic credit refill behavior. properties: interval: type: string enum: - daily - monthly x-speakeasy-unknown-values: allow description: How often credits are automatically refilled. example: daily amount: type: integer format: int64 minimum: 1 maximum: 9223372036854776000 description: Number of credits to add during each refill cycle. example: 1000 refillDay: type: integer minimum: 1 maximum: 31 description: | Day of the month for monthly refills (1-31). Only required when interval is 'monthly'. For days beyond the month's length, refill occurs on the last day of the month. example: 15 required: - interval - amount additionalProperties: false KeysVerifyKeyCredits: type: object required: - cost properties: cost: type: integer format: int64 minimum: 0 maximum: 1000000000000 description: | Sets how many credits to deduct for this verification request. Use 0 for read-only operations or free tier access, higher values for premium features. Credits are deducted after all security checks pass. Essential for implementing usage-based pricing with different operation costs. example: 5 additionalProperties: false description: | Controls credit consumption for usage-based billing and quota enforcement. Omitting this field uses the default cost of 1 credit per verification. Credits provide globally consistent usage tracking, essential for paid APIs with strict quotas. KeysVerifyKeyRatelimit: type: object required: - name properties: name: type: string minLength: 3 maxLength: 255 description: References an existing ratelimit by its name. Key Ratelimits will take precedence over identifier-based limits. example: tokens cost: type: integer minimum: 0 default: 1 description: Optionally override how expensive this operation is and how many tokens are deducted from the current limit. example: 2 limit: type: integer minimum: 0 description: Optionally override the maximum number of requests allowed within the specified interval. example: 50 duration: type: integer minimum: 0 description: Optionally override the duration of the rate limit window duration. example: 600000 V2KeysVerifyKeyResponseData: type: object additionalProperties: false properties: valid: type: boolean description: | The primary verification result. If true, the key is valid and can be used. If false, check the 'code' field to understand why verification failed. Your application should always check this field first before proceeding. code: type: string enum: - VALID - NOT_FOUND - FORBIDDEN - INSUFFICIENT_PERMISSIONS - USAGE_EXCEEDED - RATE_LIMITED - DISABLED - EXPIRED x-speakeasy-unknown-values: allow description: | A machine-readable code indicating the verification status or failure reason. Values: `VALID` (key is valid and passed all checks), `NOT_FOUND` (key doesn't exist or belongs to wrong API), `FORBIDDEN` (key lacks required permissions), `INSUFFICIENT_PERMISSIONS` (key lacks specific required permissions for this request), `USAGE_EXCEEDED` (key has no remaining credits), `RATE_LIMITED` (key exceeded rate limits), `DISABLED` (key was explicitly disabled), `EXPIRED` (key has passed its expiration date). keyId: type: string description: | The unique identifier of the verified key in Unkey's system. Use this ID for operations like updating or revoking the key. This field is returned for both valid and invalid keys (except when `code=NOT_FOUND`). x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true name: type: string description: | The human-readable name assigned to this key during creation. This is useful for displaying in logs or admin interfaces to identify the key's purpose. x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true meta: type: object additionalProperties: true description: | Custom metadata associated with the key. This can include any JSON-serializable data you stored with the key during creation or updates, such as plan information, feature flags, or user details. Use this to avoid additional database lookups for contextual information needed during API calls. x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true expires: type: integer format: int64 description: | Unix timestamp (in milliseconds) when the key will expire. If omitted, the key has no expiration. You can use this to warn users about upcoming expirations or to understand the validity period. x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true credits: type: integer format: int64 description: | The number of requests/credits remaining for this key. If omitted, the key has unlimited usage. This value decreases with each verification (based on the 'cost' parameter) unless explicit credit refills are configured. enabled: type: boolean description: | Indicates if the key is currently enabled. Disabled keys will always fail verification with `code=DISABLED`. This is useful for implementing temporary suspensions without deleting the key. permissions: type: array items: type: string description: | A list of all permission names assigned to this key, either directly or through roles. These permissions determine what actions the key can perform. Only returned when permissions were checked during verification or when the key fails with `code=FORBIDDEN`. x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true roles: type: array items: type: string description: | A list of all role names assigned to this key. Roles are collections of permissions that grant access to specific functionality. Only returned when permissions were checked during verification. x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true identity: "$ref": "#/components/schemas/Identity" description: | Information about the identity associated with this key. Identities allow multiple keys to share resources (like rate limits) and represent the same user or entity across different applications or devices. x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true ratelimits: type: array items: "$ref": "#/components/schemas/VerifyKeyRatelimitData" description: The ratelimits that got checked x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - valid - code VerifyKeyRatelimitData: type: object properties: exceeded: type: boolean description: Whether the rate limit was exceeded. id: type: string minLength: 8 maxLength: 255 pattern: "^rl_[a-zA-Z0-9_]+$" description: Unique identifier for this rate limit configuration. example: rl_1234567890abcdef name: type: string minLength: 1 maxLength: 128 description: Human-readable name for this rate limit. example: api_requests limit: type: integer format: int64 minimum: 1 maximum: 1000000 description: Maximum requests allowed within the time window. example: 1000 duration: type: integer format: int64 minimum: 1000 maximum: 2592000000 description: Rate limit window duration in milliseconds. example: 3600000 reset: type: integer format: int64 minimum: 1000 maximum: 2592000000 description: Rate limit reset duration in milliseconds. example: 3600000 remaining: type: integer format: int64 minimum: 0 maximum: 1000000 description: Rate limit remaining requests within the time window. example: 999 autoApply: type: boolean description: | Whether this rate limit should be automatically applied when verifying keys. When true, we will automatically apply this limit during verification without it being explicitly listed. example: true required: - id - exceeded - name - limit - duration - reset - remaining - autoApply additionalProperties: false V2LivenessResponseData: type: object properties: message: description: Status message indicating the health of the service. A value of 'OK' indicates that the service is functioning properly and ready to accept requests. Any other value indicates a potential issue with the service health. example: OK type: string required: - message description: Response data for the liveness check endpoint. This provides a simple indication of whether the Unkey API service is running and able to process requests. Monitoring systems can use this endpoint to track service availability and trigger alerts if the service becomes unhealthy. V2PermissionsCreatePermissionResponseData: type: object properties: permissionId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The unique identifier assigned to the newly created permission. Use this ID to reference the permission in role assignments, key operations, and other API calls. Always begins with 'perm_' followed by a unique alphanumeric sequence. Store this ID if you need to manage or reference this permission in future operations. example: perm_1234567890abcdef required: - permissionId additionalProperties: false V2PermissionsCreateRoleResponseData: type: object properties: roleId: type: string minLength: 3 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The unique identifier assigned to the newly created role. Use this ID to reference the role in permission assignments, key operations, and role management calls. Always begins with 'role_' followed by a unique alphanumeric sequence. Store this ID if you need to manage, modify, or assign this role in future operations. example: role_1234567890abcdef required: - roleId additionalProperties: false V2PermissionsListPermissionsResponseData: type: array maxItems: 1000 description: Array of permission objects with complete configuration details. items: "$ref": "#/components/schemas/Permission" V2PermissionsListRolesResponseData: type: array maxItems: 1000 description: Array of roles with their assigned permissions. items: "$ref": "#/components/schemas/Role" V2PortalCreateSessionResponseData: type: object required: - sessionId - url properties: sessionId: type: string x-unkey-redact: true description: | The short-lived session token ID. Valid for 15 minutes and can be exchanged once for a browser session. example: pst_abc123def456 url: type: string format: uri x-unkey-redact: true description: | The full portal URL with the session parameter. Redirect the end user to this URL. example: "https://portal.unkey.com/?session=pst_abc123def456" additionalProperties: false V2PortalExchangeSessionResponseData: type: object required: - token - expiresAt properties: token: type: string x-unkey-redact: true description: | The browser session token. Store this as an httpOnly cookie for subsequent portal requests. example: ps_xyz789abc123 expiresAt: type: integer format: int64 description: | Unix timestamp in milliseconds when the browser session expires (24 hours from creation). example: 1711386400000 additionalProperties: false V2PortalGetVerificationsDataPoint: type: object required: - time - total - valid - rateLimited - insufficientPermissions - forbidden - disabled - expired - usageExceeded properties: time: type: integer format: int64 description: Bucket start as a unix timestamp in milliseconds. example: 1704067200000 total: type: integer format: int64 description: Total verifications in this bucket, across all outcomes. valid: type: integer format: int64 description: Verifications with a VALID outcome. rateLimited: type: integer format: int64 description: Verifications rejected because a rate limit was exceeded. insufficientPermissions: type: integer format: int64 description: Verifications rejected for insufficient permissions. forbidden: type: integer format: int64 description: Verifications rejected as forbidden. disabled: type: integer format: int64 description: Verifications rejected because the key was disabled. expired: type: integer format: int64 description: Verifications rejected because the key was expired. usageExceeded: type: integer format: int64 description: Verifications rejected because remaining usage was exhausted. additionalProperties: false V2PortalListKeysResponseData: type: array maxItems: 100 items: "$ref": "#/components/schemas/KeyResponseData" description: Array of the portal end user's API keys. V2ProjectsCreateProjectResponseData: type: object required: - id properties: id: type: string minLength: 8 maxLength: 255 pattern: "^[a-zA-Z0-9_]+$" description: | The unique identifier of the newly created project, generated by Unkey. Always begins with 'proj_' followed by a unique alphanumeric sequence. example: proj_1234abcd additionalProperties: false Project: type: object required: - id - name - slug - createdAt - deleteProtection properties: id: type: string description: | The unique identifier of the project, generated by Unkey. example: proj_1234abcd name: type: string description: | Human-readable name for this project. example: Payments Service slug: type: string description: | URL-safe handle for this project, unique within your workspace. This is the caller-defined identifier used to reference the project in get, update, and delete operations. example: payments-service createdAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: | Unix timestamp in milliseconds when the project was created. example: 1704067200000 updatedAt: type: integer format: int64 minimum: 0 maximum: 9223372036854776000 description: | Unix timestamp in milliseconds when the project was last updated. Omitted if the project has never been updated. example: 1704153600000 x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true deleteProtection: type: boolean description: | Whether delete protection is enabled for this project. When true, the project cannot be deleted until protection is disabled. example: false additionalProperties: false V2RatelimitDeleteOverrideResponseData: type: object additionalProperties: false description: Empty response object. A successful response indicates the override was successfully deleted. The operation is immediate - as soon as this response is received, the override no longer exists and affected identifiers have reverted to using the default rate limit for the namespace. No other data is returned as part of the deletion operation. RatelimitOverride: type: object additionalProperties: false properties: overrideId: description: The unique identifier of this specific rate limit override. This ID is generated when the override is created and can be used for management operations like updating or deleting the override. type: string minLength: 1 maxLength: 255 duration: description: The duration in milliseconds for this override's rate limit window. This may differ from the default duration for the namespace, allowing custom time windows for specific entities. After this duration elapses, the rate limit counter for affected identifiers resets to zero. format: int64 type: integer minimum: 1000 identifier: description: |- The identifier pattern this override applies to. This determines which entities receive the custom rate limit. This can be: - An exact identifier for a specific entity - A pattern with wildcards for matching multiple entities Wildcard examples: - 'admin_*' matches any identifier starting with 'admin_' - '*_test' matches any identifier ending with '_test' - '*premium*' matches any identifier containing 'premium' More complex patterns can combine multiple wildcards. Detailed documentation on pattern matching rules is available at https://www.unkey.com/docs/ratelimiting/overrides#wildcard-rules type: string minLength: 1 maxLength: 255 limit: description: |- The maximum number of requests allowed for entities matching this override. This replaces the default limit for the namespace when applied. Common use cases: - Higher limits for premium customers - Reduced limits for abusive or suspicious entities - Zero limit to completely block specific patterns - Custom tier-based limits for different customer segments format: int64 type: integer minimum: 0 required: - overrideId - duration - identifier - limit V2RatelimitLimitResponseData: type: object properties: limit: description: |- The maximum number of operations allowed within the time window. This reflects either the default limit specified in the request or an override limit if one exists for this identifier. This value helps clients understand their total quota for the current window. format: int64 type: integer remaining: description: |- The number of operations remaining in the current window before the rate limit is exceeded. Applications should use this value to: - Implement client-side throttling before hitting limits - Display usage information to end users - Trigger alerts when approaching limits - Adjust request patterns based on available capacity When this reaches zero, requests will be rejected until the window resets. format: int64 type: integer reset: description: |- The Unix timestamp in milliseconds when the rate limit window will reset and 'remaining' will return to 'limit'. This timestamp enables clients to: - Calculate and display wait times to users - Implement intelligent retry mechanisms - Schedule requests to resume after the reset - Implement exponential backoff when needed The reset time is based on a sliding window from the first request in the current window. format: int64 type: integer success: description: |- Whether the request passed the rate limit check. If true, the request is allowed to proceed. If false, the request has exceeded the rate limit and should be blocked or rejected. You MUST check this field to determine if the request should proceed, as the endpoint always returns `HTTP 200` even when rate limited. type: boolean overrideId: description: |- If a rate limit override was applied for this identifier, this field contains the ID of the override that was used. Empty when no override is in effect. This can be useful for: - Debugging which override rule was matched - Tracking the effects of specific overrides - Understanding why limits differ from default values type: string x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - limit - remaining - reset - success V2RatelimitListOverridesResponseData: type: array items: "$ref": "#/components/schemas/RatelimitOverride" V2RatelimitMultiLimitResponseData: type: object description: Container for multi-limit rate limit check results required: - passed - limits properties: passed: type: boolean description: |- Overall success indicator for all rate limit checks. This is true if ALL individual rate limit checks passed (all have success: true), and false if ANY check failed. Use this as a quick indicator to determine if the request should proceed. limits: type: array description: Array of individual rate limit check results, one for each rate limit check in the request items: "$ref": "#/components/schemas/V2RatelimitMultiLimitCheck" V2RatelimitMultiLimitCheck: type: object properties: namespace: description: |- The namespace this rate limit result corresponds to. Use this field to correlate the response with the request when checking multiple rate limits. type: string identifier: description: |- The identifier this rate limit result corresponds to. Use this field to correlate the response with the request when checking multiple rate limits. type: string limit: description: |- The maximum number of operations allowed within the time window. This reflects either the default limit specified in the request or an override limit if one exists for this identifier. This value helps clients understand their total quota for the current window. format: int64 type: integer remaining: description: |- The number of operations remaining in the current window before the rate limit is exceeded. Applications should use this value to: - Implement client-side throttling before hitting limits - Display usage information to end users - Trigger alerts when approaching limits - Adjust request patterns based on available capacity When this reaches zero, requests will be rejected until the window resets. format: int64 type: integer reset: description: |- The Unix timestamp in milliseconds when the rate limit window will reset and 'remaining' will return to 'limit'. This timestamp enables clients to: - Calculate and display wait times to users - Implement intelligent retry mechanisms - Schedule requests to resume after the reset - Implement exponential backoff when needed The reset time is based on a sliding window from the first request in the current window. format: int64 type: integer passed: description: |- Whether the request passed the rate limit check. If true, the request is allowed to proceed. If false, the request has exceeded the rate limit and should be blocked or rejected. You MUST check this field to determine if the request should proceed, as the endpoint always returns `HTTP 200` even when rate limited. type: boolean overrideId: description: |- If a rate limit override was applied for this identifier, this field contains the ID of the override that was used. Empty when no override is in effect. This can be useful for: - Debugging which override rule was matched - Tracking the effects of specific overrides - Understanding why limits differ from default values type: string x-go-type-skip-optional-pointer: true x-go-type-skip-optional-pointer-with-omitzero: true required: - namespace - identifier - limit - remaining - reset - passed V2RatelimitSetOverrideResponseData: type: object properties: overrideId: description: |- The unique identifier for the newly created or updated rate limit override. This ID can be used to: - Reference this specific override in subsequent API calls - Delete or modify this override later - Track which override is being applied in rate limit responses - Associate override effects with specific rules in analytics Store this ID if you need to manage the override in the future. type: string required: - overrideId info: description: |- Unkey's API provides programmatic access for all resources within our platform. ### Authentication # This API accepts HTTP Bearer credentials. Public integrations use root keys. Dashboard-originated requests use a short-lived dashboard proxy JWT minted by the dashboard server. Most endpoints require permissions associated with the authenticated principal. When making public API requests, include your root key in the `Authorization` header: ``` Authorization: Bearer unkey_xxxxxxxxxxx ``` All responses follow a consistent envelope structure that separates operational metadata from actual data. This design provides several benefits: - Debugging: Every response includes a unique requestId for tracing issues - Consistency: Predictable response format across all endpoints - Extensibility: Easy to add new metadata without breaking existing integrations - Error Handling: Unified error format with actionable information ### Success Response Format: ```json { "meta": { "requestId": "req_123456" }, "data": { // Actual response data here } } ``` The meta object contains operational information: - `requestId`: Unique identifier for this request (essential for support) The data object contains the actual response data specific to each endpoint. ### Paginated Response Format: ```json { "meta": { "requestId": "req_123456" }, "data": [ // Array of results ], "pagination": { "cursor": "next_page_token", "hasMore": true } } ``` The pagination object appears on list endpoints and contains: - `cursor`: Token for requesting the next page - `hasMore`: Whether more results are available ### Error Response Format: ```json { "meta": { "requestId": "req_2c9a0jf23l4k567" }, "error": { "detail": "The resource you are attempting to modify is protected and cannot be changed", "status": 403, "title": "Forbidden", "type": "https://unkey.com/docs/errors/unkey/application/protected_resource" } } ``` Error responses include comprehensive diagnostic information: - `title`: Human-readable error summary - `detail`: Specific description of what went wrong - `status`: HTTP status code - `type`: Link to error documentation - `errors`: Array of validation errors (for 400 responses) This structure ensures you always have the context needed to debug issues and take corrective action. title: Unkey API version: 2.0.0 openapi: 3.1.0 paths: /v2/analytics.getRatelimits: post: description: | Queries may reference only the five public rate limit analytics aliases: `ratelimits_v1`, `ratelimits_per_minute_v1`, `ratelimits_per_hour_v1`, `ratelimits_per_day_v1`, or `ratelimits_per_month_v1`. CTEs, subqueries, UNION, and EXCEPT are supported. Queries are always restricted to the authenticated workspace. Wildcard analytics permission can read every namespace in that workspace; namespace-scoped permissions automatically restrict results to the permitted namespace IDs. Workspace retention and query limits apply. operationId: analytics.getRatelimits requestBody: content: application/json: schema: $ref: '#/components/schemas/V2AnalyticsGetRatelimitsRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2AnalyticsGetRatelimitsResponseBody' description: Query executed successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Invalid SQL query, blocked operation, or missing required authentication "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Invalid authentication credentials "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Insufficient permissions "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: Analytics is not configured for the workspace "422": content: application/json: schema: $ref: '#/components/schemas/UnprocessableEntityErrorResponse' description: Query exceeds workspace query limits "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Query quota exceeded "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Query execution failed "503": content: application/json: schema: $ref: '#/components/schemas/ServiceUnavailableErrorResponse' description: Connection to the database failed security: - bearer: [] summary: Query rate limit data tags: - analytics x-speakeasy-name-override: getRatelimits /v2/analytics.getVerifications: post: description: | Execute custom SQL queries against your key verification analytics. CTEs, subqueries, UNION, and EXCEPT are supported. Queries must use one of the five public aliases: `key_verifications_v1`, `key_verifications_per_minute_v1`, `key_verifications_per_hour_v1`, `key_verifications_per_day_v1`, or `key_verifications_per_month_v1`. Physical `default.*` table names are unsupported. Queries are always restricted to the authenticated workspace. Wildcard analytics permission can read every API in that workspace; API-scoped permissions automatically restrict results to the permitted APIs. For complete documentation including available tables, columns, data types, query examples, see the schema reference in the API documentation. operationId: analytics.getVerifications requestBody: content: application/json: schema: $ref: '#/components/schemas/V2AnalyticsGetVerificationsRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2AnalyticsGetVerificationsResponseBody' description: Query executed successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Invalid SQL query, blocked operation, or missing required authentication "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Invalid authentication credentials "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Insufficient permissions "422": content: application/json: schema: $ref: '#/components/schemas/UnprocessableEntityErrorResponse' description: Query exceeds resource limits (timeout, memory, rows scanned, or result size) "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Query quota exceeded "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Query execution failed "503": content: application/json: schema: $ref: '#/components/schemas/ServiceUnavailableErrorResponse' description: Connection to the database failed security: - bearer: [] summary: Query key verification data tags: - analytics x-speakeasy-name-override: getVerifications /v2/apis.createApi: post: description: | Create an API namespace for organizing keys by environment, service, or product. Use this to separate production from development keys, isolate different services, or manage multiple products. Each API gets a unique identifier and dedicated infrastructure for secure key operations. **Important**: API names must be unique within your workspace and cannot be changed after creation. **Required Permissions** Your root key must have one of the following permissions: - `api.*.create_api` (to create APIs in any workspace) operationId: apis.createApi requestBody: content: application/json: schema: $ref: '#/components/schemas/V2ApisCreateApiRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2ApisCreateApiResponseBody' description: | API namespace created successfully. The response contains the unique API ID for referencing this namespace in key operations. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Create API namespace tags: - apis x-speakeasy-name-override: createApi /v2/apis.deleteApi: post: description: | Permanently delete an API namespace and immediately invalidate all associated keys. Use this for cleaning up development environments, retiring deprecated services, or removing unused resources. All keys in the namespace are immediately marked as deleted and will fail verification with `code=NOT_FOUND`. **Important**: This operation is immediate and permanent. Verify you have the correct API ID before deletion. If delete protection is enabled, disable it first through the dashboard or API configuration. **Required Permissions** Your root key must have one of the following permissions: - `api.*.delete_api` (to delete any API) - `api..delete_api` (to delete a specific API) operationId: apis.deleteApi requestBody: content: application/json: schema: $ref: '#/components/schemas/V2ApisDeleteApiRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2ApisDeleteApiResponseBody' description: API namespace deleted successfully. All associated keys are immediately invalidated and will fail verification with `code=NOT_FOUND`. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: Delete protection is enabled. Disable protection through the dashboard or API configuration, then retry the deletion. "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Delete API namespace tags: - apis x-speakeasy-name-override: deleteApi /v2/apis.getApi: post: description: | Retrieve basic information about an API namespace including its ID and name. Use this to verify an API exists before performing operations, get the human-readable name when you only have the API ID, or confirm access to a specific namespace. For detailed key information, use the `listKeys` endpoint instead. **Required Permissions** Your root key must have one of the following permissions: - `api.*.read_api` (to read any API) - `api..read_api` (to read a specific API) operationId: apis.getApi requestBody: content: application/json: schema: $ref: '#/components/schemas/V2ApisGetApiRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2ApisGetApiResponseBody' description: API information retrieved successfully. Contains the unique API ID and human-readable name. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Get API namespace tags: - apis x-speakeasy-name-override: getApi /v2/apis.listKeys: post: description: | Retrieve a paginated list of API keys for dashboard and administrative interfaces. Use this to build key management dashboards, filter keys by user with `externalId`, or retrieve key details for administrative purposes. Each key includes status, metadata, permissions, and usage limits. **Important**: Set `decrypt: true` only in secure contexts to retrieve plaintext key values from recoverable keys. **Required Permissions** Your root key must have one of the following permissions for basic key listing: - `api.*.read_key` (to read keys from any API) - `api..read_key` (to read keys from a specific API) Additionally, you need read access to the API itself: - `api.*.read_api` or `api..read_api` Additional permission required for decrypt functionality: - `api.*.decrypt_key` or `api..decrypt_key` operationId: apis.listKeys requestBody: content: application/json: schema: $ref: '#/components/schemas/V2ApisListKeysRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2ApisListKeysResponseBody' description: | Successfully retrieved paginated keys. Use the pagination cursor for additional results when `hasMore: true`. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: List API keys tags: - apis x-speakeasy-name-override: listKeys x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/apps.createApp: post: description: | Create an app within a project. The app is created with default `production` and `preview` environments. The slug you provide is the stable, caller-defined handle used to reference this app. It must be unique within the project. **Important**: The slug cannot collide with an existing app in the same project. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have one of the following permissions: - `project.*.create_app` (to create apps in any project) - `project..create_app` (to create apps in a specific project) operationId: apps.createApp requestBody: content: application/json: examples: basic: description: Create an app within a project summary: Basic app creation value: name: Payments API project: payments slug: payments-api schema: $ref: '#/components/schemas/V2AppsCreateAppRequestBody' required: true responses: "200": content: application/json: examples: success: description: Successfully created an app, returning its id summary: App created successfully value: data: appId: app_1234abcd meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2AppsCreateAppResponseBody' description: | App created successfully. The response contains the app id used to reference it in subsequent operations. "400": content: application/json: examples: invalidSlug: summary: Invalid slug format value: error: detail: The slug must match the pattern ^[a-z0-9]+(-[a-z0-9]+)*$. errors: - fix: Use lowercase letters, numbers, and hyphens, starting and ending with a letter or number (no leading, trailing, or consecutive hyphens) location: body.slug message: must match ^[a-z0-9]+(-[a-z0-9]+)*$ status: 400 title: Bad Request type: validation-error meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'project.*.create_app' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `project.*.create_app`) "404": content: application/json: examples: projectNotFound: summary: Project not found value: error: detail: The requested project does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested project does not exist in your workspace "409": content: application/json: examples: appExists: summary: App already exists value: error: detail: An app with slug 'payments-api' already exists in this project. status: 409 title: Conflict type: conflict meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ConflictErrorResponse' description: Conflict - App with this slug already exists in the project "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Create app tags: - apps x-speakeasy-name-override: createApp x-unkey-idempotency: conditionally-idempotent /v2/apps.deleteApp: post: description: | Delete an existing app, identified by its id. Deletion is asynchronous and eventually consistent. The app and all of its associated resources (environments, deployments, custom domains) are torn down by a background workflow. A successful response indicates the deletion was enqueued, not that every resource has already been removed. Apps with delete protection enabled cannot be deleted until protection is disabled. **Required Permissions** Your root key must have one of the following permissions: - `app.*.delete_app` (to delete any app) - `app..delete_app` (to delete a specific app) operationId: apps.deleteApp requestBody: content: application/json: examples: deleteById: description: Delete an app using its unique identifier summary: Delete by app ID value: app: app_1234abcd project: payments deleteBySlug: description: Delete an app using its slug summary: Delete by app slug value: app: payments-service project: payments schema: $ref: '#/components/schemas/V2AppsDeleteAppRequestBody' required: true responses: "202": content: application/json: examples: success: description: App deletion was successfully enqueued summary: Deletion enqueued value: data: {} meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2AppsDeleteAppResponseBody' description: | Successfully enqueued deletion of the app. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'delete_app' permission on the target app to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `app.*.delete_app`) "404": content: application/json: examples: appNotFound: summary: App not found value: error: detail: The requested app does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested app does not exist in your workspace "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: Delete protection is enabled. Disable protection through the dashboard or API, then retry the deletion. "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Delete app tags: - apps x-speakeasy-name-override: deleteApp /v2/apps.getApp: post: description: | Retrieve a single app by its id or slug within a project. Use this to fetch app details after creation or to verify an app exists before performing operations. **Required Permissions** Your root key must have one of the following permissions: - `app.*.read_app` (to read any app) - `app..read_app` (to read a specific app) operationId: apps.getApp requestBody: content: application/json: examples: getById: description: Fetch an app using its unique identifier summary: Retrieve by app ID value: app: app_1234abcd project: payments getBySlug: description: Fetch an app using its slug summary: Retrieve by app slug value: app: payments-api project: payments schema: $ref: '#/components/schemas/V2AppsGetAppRequestBody' required: true responses: "200": content: application/json: examples: app: description: Successfully retrieved an app summary: App details value: data: createdAt: 1704067200000 currentDeploymentId: d_1234abcd defaultBranch: main deleteProtection: false id: app_1234abcd isRolledBack: false name: Payments API slug: payments-api updatedAt: 1704153600000 meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2AppsGetAppResponseBody' description: | Successfully retrieved the app. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'app.*.read_app' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `app.*.read_app`) "404": content: application/json: examples: appNotFound: summary: App not found value: error: detail: The requested app does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested app does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Get app tags: - apps x-speakeasy-name-override: getApp /v2/apps.listApps: post: description: | Retrieve a paginated list of apps within a project. Use this to enumerate every app in a project. Results are ordered by app id and paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have the following permission: - `app.*.read_app` (to read apps in any project) operationId: apps.listApps requestBody: content: application/json: examples: basic: description: List the first page of apps in the given project summary: List a project's apps value: project: payments-service schema: $ref: '#/components/schemas/V2AppsListAppsRequestBody' required: true responses: "200": content: application/json: examples: appList: description: Successfully retrieved a page of apps summary: App list value: data: - createdAt: 1704067200000 currentDeploymentId: d_1234abcd defaultBranch: main deleteProtection: false id: app_1234abcd isRolledBack: false name: Payments API slug: payments-api updatedAt: 1704153600000 - createdAt: 1704240000000 defaultBranch: main deleteProtection: false id: app_5678efgh isRolledBack: false name: Billing API slug: billing-api meta: requestId: req_1234abcd pagination: hasMore: false schema: $ref: '#/components/schemas/V2AppsListAppsResponseBody' description: | Successfully retrieved a paginated list of apps. Use the pagination cursor for additional results when `hasMore: true`. "400": content: application/json: examples: invalidLimit: summary: Invalid limit value: error: detail: The limit must be between 1 and 100. errors: - fix: Use a limit between 1 and 100 location: body.limit message: must be less than or equal to 100 status: 400 title: Bad Request type: validation-error meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'app.*.read_app' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `app.*.read_app`) "404": content: application/json: examples: projectNotFound: summary: Project not found value: error: detail: The requested project does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested project does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: List apps tags: - apps x-speakeasy-name-override: listApps x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/apps.updateApp: post: description: | Update an existing app, identified by its id. The app name, slug, default branch, and delete protection setting can be changed. Omitted fields are left unchanged. Changing the slug affects the deployment domains generated for this app. **Important**: The slug cannot collide with an existing app in the same project. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have one of the following permissions: - `app.*.update_app` (to update any app) - `app..update_app` (to update a specific app) operationId: apps.updateApp requestBody: content: application/json: examples: changeSlug: description: Locate the app by its current slug and assign a new one summary: Change an app slug by slug value: app: payments-service project: payments slug: payments-api rename: description: Update only the display name, locating the app by its ID summary: Rename an app by ID value: app: app_1234abcd name: Payments API project: payments schema: $ref: '#/components/schemas/V2AppsUpdateAppRequestBody' required: true responses: "200": content: application/json: examples: app: description: Successfully updated an app summary: Updated app value: data: createdAt: 1704067200000 defaultBranch: main deleteProtection: true id: app_1234abcd isRolledBack: false name: Payments API slug: payments-api updatedAt: 1704153600000 meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2AppsUpdateAppResponseBody' description: | Successfully updated the app. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'update_app' permission on the target app to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `app.*.update_app`) "404": content: application/json: examples: appNotFound: summary: App not found value: error: detail: The requested app does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested app does not exist in your workspace "409": content: application/json: examples: appExists: summary: App already exists value: error: detail: An app with slug 'payments-api' already exists in this project. status: 409 title: Conflict type: conflict meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ConflictErrorResponse' description: Conflict - App with this slug already exists in the project "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Update app tags: - apps x-speakeasy-name-override: updateApp /v2/deploy.createDeployment: post: deprecated: true description: | **INTERNAL** - This endpoint is internal and may change without notice. Not recommended for production use. Creates a new deployment for a project using either a pre-built Docker image or build context. **Authentication**: Requires a valid root key with appropriate permissions. operationId: deploy.createDeployment requestBody: content: application/json: schema: $ref: '#/components/schemas/V2DeployCreateDeploymentRequestBody' required: true responses: "201": content: application/json: schema: $ref: '#/components/schemas/V2DeployCreateDeploymentResponseBody' description: Deployment created successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Create deployment tags: - deploy x-speakeasy-group: internal x-speakeasy-name-override: createDeployment /v2/deploy.getDeployment: post: deprecated: true description: | **INTERNAL** - This endpoint is internal and may change without notice. Not recommended for production use. Retrieves deployment information including status, error messages, and steps. **Authentication**: Requires a valid root key with appropriate permissions. operationId: deploy.getDeployment requestBody: content: application/json: schema: $ref: '#/components/schemas/V2DeployGetDeploymentRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2DeployGetDeploymentResponseBody' description: Deployment retrieved successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Get deployment tags: - deploy x-speakeasy-group: internal x-speakeasy-name-override: getDeployment /v2/deployments.createDeployment: post: description: | Create a deployment for an app in a project. Provide exactly one source: - `image`: deploy a prebuilt Docker image as-is (no build). - `git`: build and deploy from the app's connected GitHub repository, a branch, a specific commit, or a fork commit. Requires the app to have a repository connected. - `deployment`: re-run an existing deployment by its id. Git-connected apps rebuild from the recorded commit; other apps reuse the recorded image. Returns immediately with a `deploymentId`. The build and rollout run asynchronously — poll `deployments.getDeployment` to watch status until it is ready. **Authentication**: requires a root key with permission to create deployments. operationId: deployments.createDeployment requestBody: content: application/json: schema: $ref: '#/components/schemas/V2DeploymentsCreateDeploymentRequestBody' required: true responses: "201": content: application/json: schema: $ref: '#/components/schemas/V2DeploymentsCreateDeploymentResponseBody' description: Deployment created successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: Precondition failed "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Create deployment tags: - deployments x-speakeasy-name-override: createDeployment /v2/deployments.getDeployment: post: description: | Retrieve a single deployment by its id. Use this to check a deployment's status after creating it, or to inspect the runtime configuration of an existing deployment. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_deployment` (to read deployments in any environment) - `environment..read_deployment` (to read deployments in a specific environment) operationId: deployments.getDeployment requestBody: content: application/json: examples: getById: description: Fetch a deployment using its unique identifier summary: Retrieve by deployment ID value: deploymentId: d_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsGetDeploymentRequestBody' required: true responses: "200": content: application/json: examples: deployment: description: Successfully retrieved a deployment summary: Deployment details value: data: createdAt: 1704067200000 id: d_1234abcd runtime: command: - node - server.js memoryMib: 256 port: 8080 shutdownSignal: SIGTERM storageMib: 0 upstreamProtocol: http1 vCpus: 0.25 status: ready updatedAt: 1704153600000 meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsGetDeploymentResponseBody' description: | Successfully retrieved the deployment. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "404": content: application/json: examples: deploymentNotFound: summary: Deployment not found value: error: detail: The requested deployment does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested deployment does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Get deployment tags: - deployments x-speakeasy-name-override: getDeployment /v2/deployments.listDeployments: post: description: | Retrieve a paginated list of deployments within a workspace, newest first. Filter by project, app, environment, and lifecycle status. All filters are optional; with none set, every deployment in the workspace is returned. Filters nest: `app` requires `project`, and `environment` requires both `project` and `app`. Results are paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have the `environment.*.read_deployment` permission. Listing spans environments, so a grant on a single environment is not sufficient. operationId: deployments.listDeployments requestBody: content: application/json: examples: byEnvironment: description: Restrict to one environment, providing the full hierarchy summary: List an environment's deployments value: app: payments-api environment: production project: payments-service workspaceWide: description: List the first page of deployments in the workspace summary: List all deployments value: {} schema: $ref: '#/components/schemas/V2DeploymentsListDeploymentsRequestBody' required: true responses: "200": content: application/json: examples: deploymentList: description: Successfully retrieved a page of deployments summary: Deployment list value: data: - createdAt: 1704153600000 id: dep_1234abcd runtime: command: - node - server.js cpuMillicores: 250 memoryMib: 256 port: 8080 shutdownSignal: SIGTERM storageMib: 0 upstreamProtocol: http1 status: ready - createdAt: 1704067200000 id: dep_5678efgh runtime: command: [] cpuMillicores: 250 memoryMib: 256 port: 8080 shutdownSignal: SIGTERM storageMib: 0 upstreamProtocol: http1 status: failed meta: requestId: req_1234abcd pagination: hasMore: false schema: $ref: '#/components/schemas/V2DeploymentsListDeploymentsResponseBody' description: | Successfully retrieved a paginated list of deployments. Use the pagination cursor for additional results when `hasMore: true`. "400": content: application/json: examples: missingParent: summary: Missing parent filter value: error: detail: The 'environment' filter requires both 'project' and 'app' to be set. status: 400 title: Bad Request type: validation-error meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'environment.*.read_deployment' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.read_deployment`) "404": content: application/json: examples: projectNotFound: summary: Project not found value: error: detail: The requested project does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - A referenced project, app, or environment does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: List deployments tags: - deployments x-speakeasy-name-override: listDeployments x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/deployments.promoteDeployment: post: description: | Promote a deployment to become the current deployment for its environment. All sticky domains are reassigned from the current deployment to the promoted one, and the previous deployment is scheduled for standby. The deployment must be ready, not already shutting down, belong to the production environment, and its app must already have a current deployment. Promoting the deployment that is already current fails, unless the app is in a rolled-back state, in which case promoting the current deployment confirms the rollback and re-enables automatic promotion of future deployments. Promotion runs as a durable workflow: this endpoint returns once the promotion is accepted. Poll `getDeployment` or `listDeployments` to observe the result. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.promote_deployment` (to promote deployments in any environment) - `environment..promote_deployment` (to promote deployments in a specific environment) operationId: deployments.promoteDeployment requestBody: content: application/json: examples: promote: description: Point all live traffic at this deployment summary: Promote a deployment to live value: deploymentId: d_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsPromoteDeploymentRequestBody' required: true responses: "202": content: application/json: examples: accepted: summary: Promotion accepted value: data: {} meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsPromoteDeploymentResponseBody' description: | Promotion accepted. Poll `getDeployment` to observe the result. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: | Not Found - The deployment does not exist in your workspace, or your root key lacks the `promote_deployment` permission for it. Both cases return the same response, so deployment existence is never revealed. "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: | Precondition failed - The deployment is not ready, is shutting down, is already the current deployment (and the app is not in a rolled-back state), does not belong to the production environment, or its app has no current deployment to promote over. "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Promote deployment tags: - deployments x-speakeasy-name-override: promoteDeployment /v2/deployments.rollbackDeployment: post: description: | Roll live traffic back to a previous deployment. `deploymentId` is the deployment to roll back TO; the app's current deployment is used as the rollback source automatically. The target deployment must be ready, not already shutting down, belong to the production environment, and must not itself be the current deployment. After a rollback the app is marked as rolled back, which prevents new deployments from automatically taking over live traffic. Promote the rolled-back deployment (or a newer one) to clear this state. Rollback runs as a durable workflow: this endpoint returns once the rollback is accepted. Poll `getDeployment` or `listDeployments` to observe the result. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.rollback_deployment` (to roll back deployments in any environment) - `environment..rollback_deployment` (to roll back deployments in a specific environment) operationId: deployments.rollbackDeployment requestBody: content: application/json: examples: rollback: description: Point live traffic back at an earlier deployment summary: Roll back to a previous deployment value: deploymentId: d_prev5678 schema: $ref: '#/components/schemas/V2DeploymentsRollbackDeploymentRequestBody' required: true responses: "202": content: application/json: examples: accepted: summary: Rollback accepted value: data: {} meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsRollbackDeploymentResponseBody' description: | Rollback accepted. Poll `getDeployment` to observe the result. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: | Not Found - The deployment does not exist in your workspace, or your root key lacks the `rollback_deployment` permission for it. Both cases return the same response, so deployment existence is never revealed. "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: | Precondition failed - The deployment is not ready, is shutting down, is already the current deployment, does not belong to the production environment, or the app has no current deployment to roll back from. "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Rollback deployment tags: - deployments x-speakeasy-name-override: rollbackDeployment /v2/deployments.startDeployment: post: description: | Start a deployment that was previously stopped with `stopDeployment`, so it serves traffic again. The deployment keeps the configuration it had when it was stopped; nothing is rebuilt or redeployed. The deployment must currently be stopped, and must belong to a non-production environment. Production deployments are never stopped, so they cannot be started. Starting is asynchronous: this endpoint only enqueues the start and returns immediately. Poll `getDeployment` until the status reaches `ready`. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.start_deployment` (to start deployments in any environment) - `environment..start_deployment` (to start deployments in a specific environment) operationId: deployments.startDeployment requestBody: content: application/json: examples: start: description: Resume a preview deployment that was previously stopped summary: Start a stopped preview deployment value: deploymentId: d_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsStartDeploymentRequestBody' required: true responses: "202": content: application/json: examples: accepted: summary: Start enqueued value: data: {} meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsStartDeploymentResponseBody' description: | Start accepted and enqueued. The deployment transitions to `ready` asynchronously; poll `getDeployment` to observe the transition. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: | Not Found - The deployment does not exist in your workspace, or your root key lacks the `start_deployment` permission for it. Both cases return the same response, so deployment existence is never revealed. "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: | Precondition failed - The deployment is not stopped, it belongs to a production environment, or the workspace is suspended by its Compute spend cap. "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Start deployment tags: - deployments x-speakeasy-name-override: startDeployment /v2/deployments.stopDeployment: post: description: | Stop a running preview deployment. Stopped deployments keep their configuration and can be resumed later with `startDeployment`. The deployment must be ready and running, and must belong to a non-production environment; production deployments cannot be stopped. A deployment that is already draining from a previous stop is rejected with a precondition error. Stopping is asynchronous: this endpoint only enqueues the stop and returns immediately. Poll `getDeployment` until the status reaches `stopped`. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.stop_deployment` (to stop deployments in any environment) - `environment..stop_deployment` (to stop deployments in a specific environment) operationId: deployments.stopDeployment requestBody: content: application/json: examples: stop: description: Spin down a preview deployment that is currently serving summary: Stop a running preview deployment value: deploymentId: d_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsStopDeploymentRequestBody' required: true responses: "202": content: application/json: examples: accepted: summary: Stop enqueued value: data: {} meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2DeploymentsStopDeploymentResponseBody' description: | Stop accepted and enqueued. The deployment transitions to `stopped` asynchronously; poll `getDeployment` to observe the transition. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: | Not Found - The deployment does not exist in your workspace, or your root key lacks the `stop_deployment` permission for it. Both cases return the same response, so deployment existence is never revealed. "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: | Precondition failed - The deployment is not running, a stop is already in progress, or it belongs to a production environment. "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Stop deployment tags: - deployments x-speakeasy-name-override: stopDeployment /v2/environments.getEnvironment: post: description: | Retrieve a single environment by its id. Use this to fetch environment details after creation or to verify an environment exists before performing operations. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_environment` (to read any environment) - `environment..read_environment` (to read a specific environment) operationId: environments.getEnvironment requestBody: content: application/json: examples: getById: description: Fetch an environment using its unique identifier summary: Retrieve by environment ID value: app: payments-api environment: env_1234abcd project: payments getBySlug: description: Fetch an environment using its slug summary: Retrieve by environment slug value: app: payments-api environment: production project: payments schema: $ref: '#/components/schemas/V2EnvironmentsGetEnvironmentRequestBody' required: true responses: "200": content: application/json: examples: environment: description: Successfully retrieved an environment summary: Environment details value: data: build: autoDeploy: true buildCommand: pnpm --filter api build dockerfile: Dockerfile rootDirectory: . watchPaths: - src/** createdAt: 1704067200000 deleteProtection: false description: Production environment id: env_1234abcd regions: - name: us-east-1 replicas: max: 3 min: 1 runtime: command: - node - server.js memoryMib: 256 port: 8080 shutdownSignal: SIGTERM storageMib: 0 upstreamProtocol: http1 vCpus: 0.25 slug: production updatedAt: 1704153600000 meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2EnvironmentsGetEnvironmentResponseBody' description: | Successfully retrieved the environment. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'environment.*.read_environment' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.read_environment`) "404": content: application/json: examples: environmentNotFound: summary: Environment not found value: error: detail: The requested environment does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested environment does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Get environment tags: - environments x-speakeasy-name-override: getEnvironment /v2/environments.listEnvironmentVariables: post: description: | Retrieve the environment variables for an environment. Identify the environment by its project, app, and environment identifiers. Results are ordered by variable id and paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. `recoverable` variables are returned with their decrypted plaintext value. `writeonly` variables never expose a value: only the key, kind, and description are returned. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_environment_variables` (for any environment) - `environment..read_environment_variables` (for a specific environment) operationId: environments.listEnvironmentVariables requestBody: content: application/json: examples: list: description: List the first page of variables in the given environment summary: List variables for an environment value: app: payments-api environment: production project: payments schema: $ref: '#/components/schemas/V2EnvironmentsListEnvironmentVariablesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2EnvironmentsListEnvironmentVariablesResponseBody' description: | Successfully retrieved a page of environment variables. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.read_environment_variables`) "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested environment does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: List environment variables tags: - environments x-speakeasy-name-override: listEnvironmentVariables /v2/environments.listEnvironments: post: description: | Retrieve the environments within an app. Use this to enumerate every environment in an app. Identify the app by its project slug and app slug. Results are ordered by environment id. An app has only a handful of environments, so all of them are returned in a single response. **Required Permissions** Your root key must have the following permission: - `environment.*.read_environment` (to read environments in any app) operationId: environments.listEnvironments requestBody: content: application/json: examples: basic: description: List the environments in the given app summary: List an app's environments value: app: payments-api project: payments-service schema: $ref: '#/components/schemas/V2EnvironmentsListEnvironmentsRequestBody' required: true responses: "200": content: application/json: examples: environmentList: description: Successfully retrieved a page of environments summary: Environment list value: data: - build: autoDeploy: true dockerfile: Dockerfile rootDirectory: . watchPaths: - src/** createdAt: 1704067200000 deleteProtection: false description: Production environment id: env_1234abcd regions: - name: us-east-1 replicas: max: 3 min: 1 runtime: command: - node - server.js memoryMib: 256 port: 8080 shutdownSignal: SIGTERM storageMib: 0 upstreamProtocol: http1 vCpus: 0.25 slug: production updatedAt: 1704153600000 - build: autoDeploy: true buildCommand: pnpm --filter api build rootDirectory: . watchPaths: - src/** createdAt: 1704240000000 deleteProtection: false description: Staging environment id: env_5678efgh runtime: command: - node - server.js memoryMib: 256 port: 8080 shutdownSignal: SIGTERM storageMib: 0 upstreamProtocol: http1 vCpus: 0.25 slug: staging meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2EnvironmentsListEnvironmentsResponseBody' description: | Successfully retrieved the app's environments. "400": content: application/json: examples: missingApp: summary: Missing required field value: error: detail: The app field is required. errors: - fix: Provide the app id or slug location: body.app message: missing required field status: 400 title: Bad Request type: validation-error meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'environment.*.read_environment' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.read_environment`) "404": content: application/json: examples: appNotFound: summary: App not found value: error: detail: The requested app does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested app does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: List environments tags: - environments x-speakeasy-name-override: listEnvironments /v2/environments.removeEnvironmentVariables: post: description: | Remove environment variables from an environment in a single atomic request. This operation only deletes keys by name. Keys in the payload that exist are removed; keys that are not present are ignored, since their absence already matches the requested state. To replace or update values, use `setEnvironmentVariables` instead. The whole operation is atomic: if any part fails the environment is left unchanged. Duplicate keys in the payload collapse to a single removal. Values are never read or returned. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.remove_environment_variables` (for any environment) - `environment..remove_environment_variables` (for a specific environment) operationId: environments.removeEnvironmentVariables requestBody: content: application/json: examples: removeVariables: description: Locate the environment by slug and remove the named variables summary: Remove variables value: app: payments-api environment: production project: payments variables: - LOG_LEVEL - DEBUG_MODE schema: $ref: '#/components/schemas/V2EnvironmentsRemoveEnvironmentVariablesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2EnvironmentsRemoveEnvironmentVariablesResponseBody' description: | Successfully removed the environment variables. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.remove_environment_variables`) "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested environment does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Remove environment variables tags: - environments x-speakeasy-name-override: removeEnvironmentVariables /v2/environments.setEnvironmentVariables: post: description: | Create or update environment variables for an environment in a single atomic request. By default this is an upsert: each variable in the payload is created if new or fully overwritten if the key already exists, and any variable not in the payload is left untouched. This lets you change one variable without re-sending the others, which matters for write-only secrets you can no longer read back. Set `prune: true` to make it a full replace instead: after upserting, every variable not in the payload is deleted. Sending `prune: true` with an empty `variables` list resets the environment by deleting every variable. Each variable is written exactly as sent, never merged, so omitted optional fields fall back to their defaults rather than the previous value. Values are always encrypted at rest. Set `kind: recoverable` to allow a value to be read back; it defaults to `writeonly`, which can never be read back through the API. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.set_environment_variables` (for any environment) - `environment..set_environment_variables` (for a specific environment) operationId: environments.setEnvironmentVariables requestBody: content: application/json: examples: replace: description: |- With `prune: true`, the listed variables become the entire environment. Any variable not in the list is deleted. summary: Full replace with prune value: app: payments-api environment: production project: payments prune: true variables: - key: DATABASE_URL kind: writeonly value: postgresql://user:pass@host:5432/db - description: Application log verbosity key: LOG_LEVEL kind: recoverable value: debug reset: description: |- An empty `variables` list with `prune: true` deletes every variable in the environment. summary: Reset - delete every variable value: app: payments-api environment: production project: payments prune: true variables: [] upsert: description: |- Without `prune`, only the listed variables are created or overwritten. Every other variable, including write-only secrets you can no longer read back, is left untouched. Here LOG_LEVEL is flipped to info and nothing else is affected. summary: Upsert (default) - change one variable, keep the rest value: app: payments-api environment: production project: payments variables: - key: LOG_LEVEL kind: recoverable value: info schema: $ref: '#/components/schemas/V2EnvironmentsSetEnvironmentVariablesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2EnvironmentsSetEnvironmentVariablesResponseBody' description: | Successfully set the environment variables. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.set_environment_variables`) "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested environment does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Set environment variables tags: - environments x-speakeasy-name-override: setEnvironmentVariables /v2/environments.updateSettings: post: description: | Update the build, runtime, and regional settings for an environment. All settings fields are optional. Omit a field to leave it unchanged. For nullable fields (`dockerfile`, `healthcheck`, `openapiSpecPath`), send null to clear the value. When `regions` is present it replaces the full set of regions for the environment. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.update_environment` (to update any environment) - `environment..update_environment` (to update a specific environment) operationId: environments.updateSettings requestBody: content: application/json: examples: setRegions: description: Deploy to a single region with replica bounds summary: Replace the region set value: app: payments-api environment: production project: payments regions: - name: us-east-1 replicas: max: 3 min: 1 setRuntime: description: Adjust CPU and memory, locating the environment by slug summary: Update runtime resources value: app: payments-api environment: production memoryMib: 1024 project: payments vCpus: 2 schema: $ref: '#/components/schemas/V2EnvironmentsUpdateSettingsRequestBody' required: true responses: "200": content: application/json: examples: success: description: Environment settings were successfully updated summary: Settings updated value: data: {} meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2EnvironmentsUpdateSettingsResponseBody' description: | Successfully updated the environment settings. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'environment.*.update_environment' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.update_environment`) "404": content: application/json: examples: environmentNotFound: summary: Environment not found value: error: detail: The requested environment does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested environment does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Update environment settings tags: - environments x-speakeasy-name-override: updateSettings /v2/gateway.listPolicies: post: description: | Retrieve an environment's gateway policies in evaluation order: the gateway evaluates them top to bottom and the first rejection short-circuits the request. The full policy list is returned in a single response. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_policies` (for any environment) - `environment..read_policies` (for a specific environment) operationId: gateway.listPolicies requestBody: content: application/json: examples: list: summary: List the environment's policies value: app: payments-api environment: production project: payments schema: $ref: '#/components/schemas/V2GatewayListPoliciesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2GatewayListPoliciesResponseBody' description: Policies retrieved successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.read_policies`) "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The environment does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: List policies tags: - gateway x-speakeasy-name-override: listPolicies /v2/gateway.setPolicies: post: description: | Replace an environment's gateway policies in a single atomic request. Policies run at the edge before requests reach your app: verify API keys, rate limit, block requests outright, or validate them against your OpenAPI spec. Policies are an ordered list: the gateway evaluates them top to bottom and the first rejection short-circuits the request. Each policy sets exactly one of `keyauth`, `ratelimit`, `firewall` or `openapi`, plus optional `match` expressions restricting which requests it applies to. Every call is a full replace: the environment's policies become exactly the request list in the given order, and the server generates a fresh id for each one. An empty list removes all policies. The operation is atomic: if any policy is invalid, nothing is written. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.set_policies` (for any environment) - `environment..set_policies` (for a specific environment) operationId: gateway.setPolicies requestBody: content: application/json: examples: matchers: summary: Block a path prefix with a firewall policy value: app: payments-api environment: production policies: - enabled: true firewall: action: ACTION_DENY match: - path: path: prefix: /internal/ name: Block internal paths project: payments reset: summary: Remove all policies value: app: payments-api environment: production policies: [] project: payments set: summary: Replace the environment's policies value: app: payments-api environment: production policies: - enabled: true keyauth: keyspaces: - ks_1234abcd name: Require API key - enabled: true name: Global IP limit ratelimit: identifier: remoteIp: {} limit: 100 windowMs: 60000 project: payments schema: $ref: '#/components/schemas/V2GatewaySetPoliciesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2GatewaySetPoliciesResponseBody' description: | Successfully set the policies. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.set_policies`) "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The environment or a referenced keyspace does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Set policies tags: - gateway x-speakeasy-name-override: setPolicies /v2/gateway.updatePolicy: post: description: | Update a single policy in place without resending the environment's full policy list. The policy keeps its id and its position in the evaluation order, and all other policies are untouched. Omitted fields keep their stored values; at least one updatable field must be provided. Setting `match` to null removes all match expressions so the policy applies to every request. Providing one of `keyauth`, `ratelimit`, `firewall` or `openapi` replaces the policy's rule entirely, including switching its type; at most one may be set. Policy ids are regenerated whenever `gateway.setPolicies` replaces the list, so fetch current ids via `gateway.listPolicies` first. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.update_policy` (for any environment) - `environment..update_policy` (for a specific environment) operationId: gateway.updatePolicy requestBody: content: application/json: examples: clearMatch: summary: Remove all match expressions value: app: payments-api environment: production match: null policyId: pol_9d2Fk1LmQ project: payments disable: summary: Disable a policy without touching its rule value: app: payments-api enabled: false environment: production policyId: pol_9d2Fk1LmQ project: payments rename: summary: Rename a policy value: app: payments-api environment: production name: Require API key (v2) policyId: pol_9d2Fk1LmQ project: payments switchRule: summary: Replace the policy's rule with a firewall deny value: app: payments-api environment: production firewall: action: ACTION_DENY policyId: pol_9d2Fk1LmQ project: payments schema: $ref: '#/components/schemas/V2GatewayUpdatePolicyRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2GatewayUpdatePolicyResponseBody' description: | Successfully updated the policy. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `environment.*.update_policy`) "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The environment, policy, or a referenced keyspace does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Update policy tags: - gateway x-speakeasy-name-override: updatePolicy /v2/identities.createIdentity: post: description: | Create an identity to group multiple API keys under a single entity. Identities enable shared rate limits and metadata across all associated keys. Perfect for users with multiple devices, organizations with multiple API keys, or when you need unified rate limiting across different services. **Important** Requires `identity.*.create_identity` permission operationId: identities.createIdentity requestBody: content: application/json: examples: basic: summary: Simple identity value: externalId: user_123 withMetadata: summary: With user data value: externalId: user_123 meta: email: alice@example.com name: Alice Smith plan: premium withRatelimits: summary: With rate limits value: externalId: user_123 ratelimits: - duration: 60000 limit: 1000 name: requests schema: $ref: '#/components/schemas/V2IdentitiesCreateIdentityRequestBody' required: true responses: "200": content: application/json: examples: success: summary: Successfully created identity value: meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX schema: $ref: '#/components/schemas/V2IdentitiesCreateIdentityResponseBody' description: "" "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'identity.*.create_identity' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `identity.*.create_identity`) "409": content: application/json: examples: identityExists: summary: Identity already exists value: error: detail: Identity with externalId "user_abc123" already exists in this workspace. status: 409 title: Conflict type: conflict meta: requestId: req_2wXyZaAbCdEfGhIjKlMnOp schema: $ref: '#/components/schemas/ConflictErrorResponse' description: Conflict - Identity with this externalId already exists "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Create Identity tags: - identities x-speakeasy-name-override: createIdentity /v2/identities.deleteIdentity: post: description: | Permanently delete an identity. This operation cannot be undone. Use this for data cleanup, compliance requirements, or when removing entities from your system. > **Important** > Requires `identity.*.delete_identity` permission > Associated API keys remain functional but lose shared resources > External ID becomes available for reuse immediately operationId: identities.deleteIdentity requestBody: content: application/json: examples: basic: summary: Delete identity value: identity: user_123 schema: $ref: '#/components/schemas/V2IdentitiesDeleteIdentityRequestBody' required: true responses: "200": content: application/json: examples: success: summary: Successful deletion value: meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX schema: $ref: '#/components/schemas/V2IdentitiesDeleteIdentityResponseBody' description: Identity successfully deleted "400": content: application/problem+json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/problem+json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/problem+json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'identity.*.delete_identity' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `identity.*.delete_identity`) "404": content: application/problem+json: examples: identityNotFound: summary: Identity not found value: error: detail: Identity with externalId "user_abc123" not found. status: 404 title: Not Found type: not_found meta: requestId: req_2wXyZaAbCdEfGhIjKlMnOp schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - Identity with the specified externalId doesn't exist "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/problem+json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Error security: - bearer: [] summary: Delete Identity tags: - identities x-speakeasy-name-override: deleteIdentity /v2/identities.getIdentity: post: description: | Retrieve an identity by external ID. Returns metadata, rate limits, and other associated data. Use this to check if an identity exists, view configurations, or build management dashboards. > **Important** > Requires `identity.*.read_identity` permission operationId: identities.getIdentity requestBody: content: application/json: examples: basic: summary: Get identity value: identity: user_123 schema: $ref: '#/components/schemas/V2IdentitiesGetIdentityRequestBody' required: true responses: "200": content: application/json: examples: success: summary: Identity found value: data: externalId: user_123 id: id_1234567890abcdef meta: email: alice@example.com name: Alice Smith plan: premium ratelimits: - duration: 60000 limit: 1000 name: requests meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX schema: $ref: '#/components/schemas/V2IdentitiesGetIdentityResponseBody' description: Successfully retrieved the identity information "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'identity.*.read_identity' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `identity.*.read_identity`) "404": content: application/json: examples: identityNotFound: summary: Identity not found value: error: detail: Identity with externalId "user_abc123" not found. status: 404 title: Not Found type: not_found meta: requestId: req_2wXyZaAbCdEfGhIjKlMnOp schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - Identity with the specified externalId doesn't exist "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Get Identity tags: - identities x-speakeasy-name-override: getIdentity /v2/identities.listIdentities: post: description: | Get a paginated list of all identities in your workspace. Returns metadata and rate limit configurations. Perfect for building management dashboards, auditing configurations, or browsing your identities. > **Important** > Requires `identity.*.read_identity` permission operationId: identities.listIdentities requestBody: content: application/json: examples: basic: summary: List identities value: limit: 50 withCursor: summary: With pagination cursor value: cursor: cursor_eyJrZXkiOiJrZXlfMTIzNCJ9 limit: 50 withSearch: summary: Search by ID or external ID value: limit: 50 search: user_123 schema: $ref: '#/components/schemas/V2IdentitiesListIdentitiesRequestBody' required: true responses: "200": content: application/json: examples: success: summary: Identities retrieved value: data: cursor: cursor_eyJsYXN0SWQiOiJpZF8wMlpZUjNROU5QOEpNNFg4SFdTS1BXNDNKRiJ9 identities: - externalId: user_123 id: id_01H9TQP8NP8JN3X8HWSKPW43JE meta: name: Alice Smith plan: premium ratelimits: - duration: 60000 limit: 1000 name: requests - externalId: user_456 id: id_02ZYR3Q9NP8JM4X8HWSKPW43JF meta: name: Bob Johnson plan: basic ratelimits: - duration: 60000 limit: 500 name: requests total: 247 meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX schema: $ref: '#/components/schemas/V2IdentitiesListIdentitiesResponseBody' description: Successfully retrieved the list of identities "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request - Invalid parameters "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized - Missing or invalid authentication "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'identity.*.read_identity' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `identity.*.read_identity`) "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: List Identities tags: - identities x-speakeasy-name-override: listIdentities x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/identities.updateIdentity: post: description: | Update an identity's metadata and rate limits. Only specified fields are modified - others remain unchanged. Perfect for subscription changes, plan upgrades, or updating user information. Changes take effect immediately. > **Important** > Requires `identity.*.update_identity` permission > Rate limit changes propagate within 30 seconds operationId: identities.updateIdentity requestBody: content: application/json: examples: updateMetadata: summary: Update metadata value: identity: user_123 meta: email: alice@example.com name: Alice Smith plan: premium schema: $ref: '#/components/schemas/V2IdentitiesUpdateIdentityRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2IdentitiesUpdateIdentityResponseBody' description: Identity successfully updated "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'identity.*.update_identity' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `identity.*.update_identity`) "404": content: application/json: examples: identityNotFound: summary: Identity not found value: error: detail: Identity with externalId "user_123" not found. status: 404 title: Not Found type: not_found meta: requestId: req_2wXyZaAbCdEfGhIjKlMnOp schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - Identity with the specified ID or externalId doesn't exist "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Update Identity tags: - identities x-speakeasy-name-override: updateIdentity /v2/keys.addPermissions: post: description: | Add permissions to a key without affecting existing permissions. Use this for privilege upgrades, enabling new features, or plan changes that grant additional capabilities. Permissions granted through roles remain unchanged. **Important**: Changes take effect immediately with up to 30-second edge propagation. **Required Permissions** Your root key must have one of the following permissions: - `api.*.update_key` (to update keys in any API) - `api..update_key` (to update keys in a specific API) **Side Effects** Invalidates the key cache for immediate effect, and makes permissions available for verification within 30 seconds across all regions. operationId: keys.addPermissions requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysAddPermissionsRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysAddPermissionsResponseBody' description: Permissions added successfully. Returns all permissions currently assigned to the key. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Add key permissions tags: - keys x-speakeasy-name-override: addPermissions /v2/keys.addRoles: post: description: | Add roles to a key without affecting existing roles or permissions. Use this for privilege upgrades, enabling new feature sets, or subscription changes that grant additional role-based capabilities. Direct permissions remain unchanged. **Important**: Changes take effect immediately with up to 30-second edge propagation. **Required Permissions** Your root key must have one of the following permissions: - `api.*.update_key` (to update keys in any API) - `api..update_key` (to update keys in a specific API) **Side Effects** Invalidates the key cache for immediate effect, and makes role assignments available for verification within 30 seconds across all regions. operationId: keys.addRoles requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysAddRolesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysAddRolesResponseBody' description: Roles added successfully. Returns all roles currently assigned to the key. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Add key roles tags: - keys x-speakeasy-name-override: addRoles /v2/keys.createKey: post: description: | Create a new API key for user authentication and authorization. Use this endpoint when users sign up, upgrade subscription tiers, or need additional keys. Keys are cryptographically secure and unique to the specified API namespace. **Important**: The key is returned only once. Store it immediately and provide it to your user, as it cannot be retrieved later. **Common use cases:** - Generate keys for new user registrations - Create additional keys for different applications - Issue keys with specific permissions or limits **Required Permissions** Your credential needs one of: - `api.*.create_key` (create keys in any API) - `api..create_key` (create keys in specific API) - `unkey:v1::keyspaces/*#create_key` (create keys in any keyspace) - `unkey:v1::keyspaces/#create_key` (create keys in a specific keyspace) operationId: keys.createKey requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysCreateKeyRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysCreateKeyResponseBody' description: 'Successfully created a new API key. The response includes both the keyId (for reference in your system) and the full key string. IMPORTANT: This is the only time the complete key is available - it cannot be retrieved later. You must securely provide this key to your end user immediately.' "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Create API key tags: - keys x-speakeasy-name-override: createKey /v2/keys.deleteKey: post: description: | Delete API keys from user accounts or for cleanup purposes. Use this for user-requested key revocation, account deletion workflows, or cleaning up unused keys. Keys are immediately invalidated. Two modes: soft delete (default, preserves audit records) and permanent delete. **Important**: For temporary access control, use `updateKey` with `enabled: false` instead of deletion. **Required Permissions** Your credential must have one of the following permissions: - `api.*.delete_key` (to delete keys in any API) - `api..delete_key` (to delete keys in a specific API) - `unkey:v1::keyspaces/*/keys/*#delete_key` (to delete keys in any keyspace) - `unkey:v1::keyspaces//keys/*#delete_key` (to delete keys in a specific keyspace) - `unkey:v1::keyspaces//keys/#delete_key` (to delete a specific key) operationId: keys.deleteKey requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysDeleteKeyRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysDeleteKeyResponseBody' description: | Key deleted successfully. Verification fails immediately with up to 30-second edge propagation. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Delete API keys tags: - keys x-speakeasy-name-override: deleteKey /v2/keys.getKey: post: description: | Retrieve detailed key information for dashboard interfaces and administrative purposes. Use this to build key management dashboards showing users their key details, status, permissions, and usage data. You can identify keys by `keyId` or the actual key string. **Important**: Set `decrypt: true` only in secure contexts to retrieve plaintext key values from recoverable keys. **Required Permissions** Your credential must have one of the following permissions for basic key information: - `api.*.read_key` (to read keys from any API) - `api..read_key` (to read keys from a specific API) - `unkey:v1::keyspaces/*/keys/*#read_key` (to read keys in any keyspace) - `unkey:v1::keyspaces//keys/*#read_key` (to read keys in a specific keyspace) - `unkey:v1::keyspaces//keys/#read_key` (to read a specific key) Additional permission required for decrypt functionality: - `api.*.decrypt_key` or `api..decrypt_key` - `unkey:v1::keyspaces/*/keys/*#decrypt_key` - `unkey:v1::keyspaces//keys/*#decrypt_key` - `unkey:v1::keyspaces//keys/#decrypt_key` operationId: keys.getKey requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysGetKeyRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysGetKeyResponseBody' description: | Successfully retrieved key information. When `decrypt: true`, includes plaintext key value for recoverable keys. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Get API key tags: - keys x-speakeasy-name-override: getKey /v2/keys.migrateKeys: post: description: | Returns HTTP 200 even on partial success; hashes that could not be migrated are listed under `data.failed`. **Required Permissions** Your root key must have one of the following permissions for basic key information: - `api.*.create_key` (to migrate keys to any API) - `api..create_key` (to migrate keys to a specific API) operationId: keys.migrateKeys requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysMigrateKeysRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysMigrateKeysResponseBody' description: Successfully migrated keys. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Migrate API key(s) tags: - keys x-speakeasy-name-override: migrateKeys /v2/keys.removePermissions: post: description: | Remove permissions from a key without affecting existing roles or other permissions. Use this for privilege downgrades, removing temporary access, or plan changes that revoke specific capabilities. Permissions granted through roles remain unchanged. **Important**: Changes take effect immediately with up to 30-second edge propagation. **Required Permissions** Your root key must have one of the following permissions: - `api.*.update_key` (to update keys in any API) - `api..update_key` (to update keys in a specific API) **Side Effects** Invalidates the key cache for immediate effect, and makes permission changes available for verification within 30 seconds across all regions. operationId: keys.removePermissions requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysRemovePermissionsRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysRemovePermissionsResponseBody' description: Permissions removed successfully. Returns all permissions currently assigned to the key. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Remove key permissions tags: - keys x-speakeasy-name-override: removePermissions /v2/keys.removeRoles: post: description: | Remove roles from a key without affecting direct permissions or other roles. Use this for privilege downgrades, removing temporary access, or subscription changes that revoke specific role-based capabilities. Direct permissions remain unchanged. **Important**: Changes take effect immediately with up to 30-second edge propagation. **Required Permissions** Your root key must have one of the following permissions: - `api.*.update_key` (to update keys in any API) - `api..update_key` (to update keys in a specific API) **Side Effects** Invalidates the key cache for immediate effect, and makes role changes available for verification within 30 seconds across all regions. operationId: keys.removeRoles requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysRemoveRolesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysRemoveRolesResponseBody' description: Roles removed successfully. Returns all roles currently assigned to the key. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Remove key roles tags: - keys x-speakeasy-name-override: removeRoles /v2/keys.rerollKey: post: description: | Generate a new API key while preserving the configuration from an existing key. This operation creates a fresh key with a new token while maintaining all settings from the original key: - Permissions and roles - Custom metadata - Rate limit configurations - Identity associations - Remaining credits - Recovery settings **Key Generation:** - The system attempts to extract the prefix from the original key - If prefix extraction fails, the default API prefix is used - Key length follows the API's default byte configuration (or 16 bytes if not specified) **Original Key Handling:** - The original key will be revoked after the duration specified in `expiration` - Set `expiration` to 0 to revoke immediately - This allows for graceful key rotation with an overlap period Common use cases include: - Rotating keys for security compliance - Issuing replacement keys for compromised credentials - Creating backup keys with identical permissions **Important:** Analytics and usage metrics are tracked at both the key level AND identity level. If the original key has an identity, the new key will inherit it, allowing you to track usage across both individual keys and the overall identity. **Required Permissions** Your credential must have: - `api.*.create_key` or `api..create_key` - `unkey:v1::keyspaces/*#create_key` or `unkey:v1::keyspaces/#create_key` - `api.*.encrypt_key` or `api..encrypt_key` (only when the original key is recoverable) - `unkey:v1::keyspaces/*/keys/*#encrypt_key` or `unkey:v1::keyspaces//keys/*#encrypt_key` (only when the original key is recoverable) operationId: keys.rerollKey requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysRerollKeyRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysRerollKeyResponseBody' description: Key rerolled successfully. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Reroll Key tags: - keys x-speakeasy-name-override: rerollKey /v2/keys.setPermissions: post: description: | Replace all permissions on a key with the specified set in a single atomic operation. Use this to synchronize with external systems, reset permissions to a known state, or apply standardized permission templates. Permissions granted through roles remain unchanged. **Important**: Changes take effect immediately with up to 30-second edge propagation. **Required Permissions** Your root key must have one of the following permissions: - `api.*.update_key` (to update keys in any API) - `api..update_key` (to update keys in a specific API) **Side Effects** Invalidates the key cache for immediate effect, and makes permission changes available for verification within 30 seconds across all regions. operationId: keys.setPermissions requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysSetPermissionsRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysSetPermissionsResponseBody' description: Permissions set successfully. Returns all permissions currently assigned to the key. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Set key permissions tags: - keys x-speakeasy-name-override: setPermissions /v2/keys.setRoles: post: description: | Replace all roles on a key with the specified set in a single atomic operation. Use this to synchronize with external systems, reset roles to a known state, or apply standardized role templates. Direct permissions are never affected. **Important**: Changes take effect immediately with up to 30-second edge propagation. **Required Permissions** Your root key must have one of the following permissions: - `api.*.update_key` (to update keys in any API) - `api..update_key` (to update keys in a specific API) **Side Effects** Invalidates the key cache for immediate effect, and makes role changes available for verification within 30 seconds across all regions. operationId: keys.setRoles requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysSetRolesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysSetRolesResponseBody' description: Roles set successfully. Returns all roles currently assigned to the key. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Set key roles tags: - keys x-speakeasy-name-override: setRoles /v2/keys.updateCredits: post: description: | Update credit quotas in response to plan changes, billing cycles, or usage purchases. Use this for user upgrades/downgrades, monthly quota resets, credit purchases, or promotional bonuses. Supports three operations: set, increment, or decrement credits. Set to null for unlimited usage. **Important**: Setting unlimited credits automatically clears existing refill configurations. **Required Permissions** Your credential must have one of the following permissions: - `api.*.update_key` (to update keys in any API) - `api..update_key` (to update keys in a specific API) - `unkey:v1::keyspaces/*/keys/*#update_key` (to update keys in any keyspace) - `unkey:v1::keyspaces//keys/*#update_key` (to update keys in a specific keyspace) - `unkey:v1::keyspaces//keys/#update_key` (to update a specific key) **Side Effects** Credit updates remove the key from cache immediately. Setting credits to unlimited automatically clears any existing refill settings. Changes take effect instantly but may take up to 30 seconds to propagate to all edge regions. operationId: keys.updateCredits requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysUpdateCreditsRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysUpdateCreditsResponseBody' description: | Credits updated successfully. Response includes updated remaining credits and refill settings. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Update key credits tags: - keys x-speakeasy-name-override: updateCredits /v2/keys.updateKey: post: description: | Update key properties in response to plan changes, subscription updates, or account status changes. Use this for user upgrades/downgrades, role modifications, or administrative changes. Supports partial updates - only specify fields you want to change. Set fields to null to clear them. **Important**: Permissions and roles are replaced entirely. Use dedicated add/remove endpoints for incremental changes. **Required Permissions** Your credential must have one of the following permissions: - `api.*.update_key` (to update keys in any API) - `api..update_key` (to update keys in a specific API) - `unkey:v1::keyspaces/*/keys/*#update_key` (to update keys in any keyspace) - `unkey:v1::keyspaces//keys/*#update_key` (to update keys in a specific keyspace) - `unkey:v1::keyspaces//keys/#update_key` (to update a specific key) **Side Effects** If you specify an `externalId` that doesn't exist, a new identity will be automatically created and linked to the key. Permission updates will auto-create any permissions that don't exist in your workspace. Changes take effect immediately but may take up to 30 seconds to propagate to all edge regions due to cache invalidation. operationId: keys.updateKey requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysUpdateKeyRequestBody' required: true responses: "200": content: application/json: examples: success: summary: Successful update value: data: {} meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQY schema: $ref: '#/components/schemas/V2KeysUpdateKeyResponseBody' description: | Key updated successfully. Changes take effect immediately with up to 30-second edge propagation. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Update key settings tags: - keys x-speakeasy-name-override: updateKey /v2/keys.verifyKey: post: description: | Verify an API key's validity and permissions for request authentication. Use this endpoint on every incoming request to your protected resources. It checks key validity, permissions, rate limits, and usage quotas in a single call. **Important**: Returns HTTP 200 for all verification outcomes — check the `valid` field in response data to determine if the key is authorized. A 429 may be returned if the workspace exceeds its API rate limit. **Common use cases:** - Authenticate API requests before processing - Enforce permission-based access control - Track usage and apply rate limits **Required Permissions** Your credential needs one of: - `api.*.verify_key` (verify keys in any API) - `api..verify_key` (verify keys in specific API) - `unkey:v1::keyspaces/*/keys/*#verify_key` (verify keys in any keyspace) - `unkey:v1::keyspaces//keys/*#verify_key` (verify keys in a specific keyspace) - `unkey:v1::keyspaces//keys/#verify_key` (verify a specific key) **Note**: If your credential has no verify permissions at all, you will receive a `403 Forbidden` error. If your credential has verify permissions for a different API or keyspace than the key you're verifying, you will receive a `200` response with `code: NOT_FOUND` to avoid leaking key existence. operationId: keys.verifyKey requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysVerifyKeyRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysVerifyKeyResponseBody' description: | Key verification process completed. This endpoint always returns HTTP 200 regardless of whether the key passed or failed verification. You must check the `valid` field in the response data to determine the actual verification result. When verification succeeds, the response includes comprehensive information about the key including its current status, remaining credits, expiration time, associated permissions and roles, metadata, and any rate limiting information. This data enables your application to make informed authorization decisions and provide appropriate user experiences. When verification fails, the response indicates the specific reason through the `code` field while setting `valid` to false. The failure codes help you handle different scenarios appropriately, such as directing users to renew expired keys, upgrade for more credits, or contact support for disabled keys. The response also includes identity information when the key is associated with an identity, providing additional context about the key holder and any identity-specific rate limits or metadata that may apply to the verification. "400": content: application/json: examples: permissionsQuerySyntaxError: summary: Invalid permissions query syntax value: error: detail: 'Syntax error in permission query: unexpected token ''AND'' at position 15. Expected permission name or opening parenthesis.' errors: - fix: Check your query syntax. AND/OR operators must be between permissions, not at the start or end location: body.permissions message: unexpected token 'AND' at position 15 status: 400 title: Bad Request type: https://unkey.com/docs/errors/user/bad_request/permissions_query_syntax_error meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: | Forbidden. Returned when the credential has no verify permissions at all. "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Verify API key tags: - keys x-speakeasy-name-override: verifyKey /v2/keys.whoami: post: description: | Find out what key this is. **Required Permissions** Your credential must have one of the following permissions for basic key information: - `api.*.read_key` (to read keys from any API) - `api..read_key` (to read keys from a specific API) - `unkey:v1::keyspaces/*/keys/*#read_key` (to read keys in any keyspace) - `unkey:v1::keyspaces//keys/*#read_key` (to read keys in a specific keyspace) - `unkey:v1::keyspaces//keys/#read_key` (to read a specific key) If your credential lacks permissions but the key exists, we may return a 404 status here to prevent leaking the existence of a key to unauthorized clients. If you believe that a key should exist, but receive a 404, please double check your credential has the correct permissions. operationId: keys.whoami requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysWhoamiRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysWhoamiResponseBody' description: | Successfully retrieved key information. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error summary: Get API key by hash tags: - keys x-speakeasy-name-override: whoami /v2/liveness: get: description: | Check if the Unkey API service is healthy and ready to handle requests. Use this for load balancer health checks, monitoring systems, and orchestration platforms. No authentication required with minimal processing overhead. **Required Permissions** None - this endpoint requires no authentication. **Side Effects** None - this is a read-only health check that does not modify any data or state. operationId: liveness responses: "200": content: application/json: examples: healthy: summary: Healthy service value: data: message: OK meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX schema: $ref: '#/components/schemas/V2LivenessResponseBody' description: | Service is healthy and ready to process requests. Returns 'OK' message for normal operation. "412": content: application/json: examples: degraded: summary: Service in degraded state value: error: detail: Service is in a degraded state. Some functionality may be limited. status: 412 title: Precondition Failed type: https://unkey.dev/errors/precondition-failed meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: "" "500": content: application/json: examples: unhealthy: summary: Service unhealthy value: error: detail: The service is currently experiencing issues and may not be fully operational. status: 500 title: Internal Server Error type: https://unkey.dev/errors/internal-server-error meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQY schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: | Service is unhealthy and unable to process requests properly. Significant service issue requiring immediate attention. security: [] summary: Health check tags: - liveness x-excluded: true x-speakeasy-ignore: true /v2/permissions.createPermission: post: description: | Create a new permission to define specific actions or capabilities in your RBAC system. Permissions can be assigned directly to API keys or included in roles. Use hierarchical naming patterns like `documents.read`, `admin.users.delete`, or `billing.invoices.create` for clear organization. **Important:** Permission names must be unique within the workspace. Once created, permissions are immediately available for assignment. **Required Permissions** Your root key must have the following permission: - `rbac.*.create_permission` operationId: permissions.createPermission requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PermissionsCreatePermissionRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PermissionsCreatePermissionResponseBody' description: Permission created successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "409": content: application/json: schema: $ref: '#/components/schemas/ConflictErrorResponse' description: Conflict - permission with that name already exists "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Create permission tags: - permissions x-speakeasy-name-override: CreatePermission /v2/permissions.createRole: post: description: | Create a new role to group related permissions for easier management. Roles enable consistent permission assignment across multiple API keys. **Important:** Role names must be unique within the workspace. Once created, roles are immediately available for assignment. **Required Permissions** Your root key must have the following permission: - `rbac.*.create_role` operationId: permissions.createRole requestBody: content: application/json: examples: basic: summary: Basic role creation value: description: Can read and write content name: content.editor withoutDescription: summary: Role without description value: name: api.reader schema: $ref: '#/components/schemas/V2PermissionsCreateRoleRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PermissionsCreateRoleResponseBody' description: Role created successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "409": content: application/json: schema: $ref: '#/components/schemas/ConflictErrorResponse' description: Conflict - A role with this name already exists "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Create role tags: - permissions x-speakeasy-name-override: CreateRole /v2/permissions.deletePermission: post: description: | Remove a permission from your workspace. This also removes the permission from all API keys and roles. **Important:** This operation cannot be undone and immediately affects all API keys and roles that had this permission assigned. **Required Permissions** Your root key must have the following permission: - `rbac.*.delete_permission` operationId: permissions.deletePermission requestBody: content: application/json: examples: basic: summary: Delete a permission value: permissionId: perm_1234567890abcdef schema: $ref: '#/components/schemas/V2PermissionsDeletePermissionRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PermissionsDeletePermissionResponseBody' description: Permission deleted successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The specified permission does not exist "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Delete permission tags: - permissions x-speakeasy-name-override: DeletePermission /v2/permissions.deleteRole: post: description: | Remove a role from your workspace. This also removes the role from all assigned API keys. **Important:** This operation cannot be undone and immediately affects all API keys that had this role assigned. **Required Permissions** Your root key must have the following permission: - `rbac.*.delete_role` operationId: permissions.deleteRole requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PermissionsDeleteRoleRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PermissionsDeleteRoleResponseBody' description: Role deleted successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Delete role tags: - permissions x-speakeasy-name-override: DeleteRole /v2/permissions.getPermission: post: description: | Retrieve details about a specific permission including its name, description, and metadata. **Required Permissions** Your root key must have the following permission: - `rbac.*.read_permission` operationId: permissions.getPermission requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PermissionsGetPermissionRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PermissionsGetPermissionResponseBody' description: Permission retrieved successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Get permission tags: - permissions x-speakeasy-name-override: GetPermission /v2/permissions.getRole: post: description: | Retrieve details about a specific role including its assigned permissions. **Required Permissions** Your root key must have the following permission: - `rbac.*.read_role` operationId: permissions.getRole requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PermissionsGetRoleRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PermissionsGetRoleResponseBody' description: Role retrieved successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Get role tags: - permissions x-speakeasy-name-override: GetRole /v2/permissions.listPermissions: post: description: | Retrieve all permissions in your workspace. Results are paginated and sorted by their id. **Required Permissions** Your root key must have the following permission: - `rbac.*.read_permission` operationId: permissions.listPermissions requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PermissionsListPermissionsRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PermissionsListPermissionsResponseBody' description: Permissions retrieved successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: List permissions tags: - permissions x-speakeasy-name-override: ListPermissions x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/permissions.listRoles: post: description: | Retrieve all roles in your workspace including their assigned permissions. Results are paginated and sorted by their id. **Required Permissions** Your root key must have the following permission: - `rbac.*.read_role` operationId: permissions.listRoles requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PermissionsListRolesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PermissionsListRolesResponseBody' description: Roles retrieved successfully "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad Request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: List roles tags: - permissions x-speakeasy-name-override: ListRoles x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/portal.createSession: post: description: | Create a short-lived session token for an end user to access the Customer Portal. The returned session ID is valid for 15 minutes and can be exchanged exactly once for a 24-hour browser session via `portal.exchangeSession`. Redirect the end user to the returned URL to start the portal experience. **Required Permissions** Your root key must be associated with a workspace that has an enabled portal configuration. operationId: portal.createSession requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PortalCreateSessionRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PortalCreateSessionResponseBody' description: | Session token created successfully. Redirect the end user to the returned URL. headers: Cache-Control: description: Prevents caching of the session token response. schema: example: no-store type: string example: no-store Pragma: description: HTTP/1.0 backward-compatible cache prevention. schema: example: no-cache type: string example: no-cache "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Create portal session tags: - portal x-excluded: true x-speakeasy-name-override: createSession /v2/portal.exchangeSession: post: description: | Exchange a short-lived session token for a long-lived browser session. This endpoint is unauthenticated. The session token itself serves as proof of authorization. Each token can only be exchanged once; subsequent attempts return 401. The returned browser session token is valid for 24 hours and should be stored as an httpOnly cookie or used in the Authorization header for subsequent API calls. operationId: portal.exchangeSession requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PortalExchangeSessionRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PortalExchangeSessionResponseBody' description: | Session exchanged successfully. Use the returned token for subsequent API calls. headers: Cache-Control: description: Prevents caching of the session token response. schema: example: no-store type: string example: no-store Pragma: description: HTTP/1.0 backward-compatible cache prevention. schema: example: no-cache type: string example: no-cache "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized — session is invalid, expired, or already exchanged "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: [] summary: Exchange session token tags: - portal x-excluded: true x-speakeasy-name-override: exchangeSession /v2/portal.getVerifications: post: description: | Return a verification analytics timeseries for the authenticated portal session's end user. Authenticates only with a portal session cookie and always restricts results to verification events attributed to the session's external identity. Unlike `analytics.getVerifications`, this endpoint takes a fixed time window (no query language) and returns a zero-filled, outcome-broken-out timeseries. Bucket granularity is chosen automatically from the window size. operationId: portal.getVerifications requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PortalGetVerificationsRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PortalGetVerificationsResponseBody' description: | Successfully retrieved verification analytics. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - portalSession: [] summary: Get portal verifications tags: - portal x-excluded: true x-speakeasy-name-override: getVerifications /v2/portal.listKeys: post: description: | Retrieve a paginated list of API keys owned by the authenticated portal session's end user. This is the portal-scoped variant of `apis.listKeys`. It authenticates only with a portal session cookie and always restricts results to the keys owned by the session's external identity, within the keyspaces configured on the portal configuration. Both the identity and the keyspaces come from the session, so the request body has no `externalId` or `apiId` field. operationId: portal.listKeys requestBody: content: application/json: schema: $ref: '#/components/schemas/V2PortalListKeysRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2PortalListKeysResponseBody' description: | Successfully retrieved paginated keys. Use the pagination cursor for additional results when `hasMore: true`. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - portalSession: [] summary: List portal keys tags: - portal x-excluded: true x-speakeasy-name-override: listKeys x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/portal.rerollKey: post: description: | Reroll an API key owned by the authenticated portal session's end user, issuing a new key while preserving its configuration. This is the portal-scoped variant of `keys.rerollKey`. It authenticates only with a portal session cookie and may only reroll keys owned by the session's external identity; any other key returns 404. operationId: portal.rerollKey requestBody: content: application/json: schema: $ref: '#/components/schemas/V2KeysRerollKeyRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2KeysRerollKeyResponseBody' description: | Key rerolled successfully. The new plaintext key is returned exactly once. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - portalSession: [] summary: Reroll portal key tags: - portal x-excluded: true x-speakeasy-name-override: rerollKey /v2/projects.createProject: post: description: | Create a project to group deployments and applications under a workspace-scoped slug. The slug you provide is the stable, caller-defined handle used to reference this project in subsequent operations (get, update, delete). It must be unique within your workspace. **Important**: The slug cannot collide with an existing project in your workspace. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have the following permission: - `project.*.create_project` (to create projects in your workspace) operationId: projects.createProject requestBody: content: application/json: examples: basic: description: Create a project for a payment service summary: Basic project creation value: name: Payments Service slug: payments-service schema: $ref: '#/components/schemas/V2ProjectsCreateProjectRequestBody' required: true responses: "200": content: application/json: examples: success: description: Successfully created a project, returning its id summary: Project created successfully value: data: id: proj_1234abcd meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2ProjectsCreateProjectResponseBody' description: | Project created successfully. The response contains the project id used to reference it in subsequent operations. "400": content: application/json: examples: invalidSlug: summary: Invalid slug format value: error: detail: The slug must match the pattern ^[a-zA-Z0-9_-]+$. errors: - fix: Use only letters, numbers, hyphens, and underscores location: body.slug message: must match ^[a-zA-Z0-9_-]+$ status: 400 title: Bad Request type: validation-error meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'project.*.create_project' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `project.*.create_project`) "409": content: application/json: examples: projectExists: summary: Project already exists value: error: detail: A project with slug 'payments-service' already exists in this workspace. status: 409 title: Conflict type: conflict meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ConflictErrorResponse' description: Conflict - Project with this slug already exists "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Create project tags: - projects x-speakeasy-name-override: createProject x-unkey-idempotency: conditionally-idempotent /v2/projects.deleteProject: post: description: | Delete an existing project in your workspace, identified by its id. Deletion is asynchronous and eventually consistent. The project and all of its associated resources (apps, environments, deployments, custom domains) are torn down by a background workflow. A successful response indicates the deletion was enqueued, not that every resource has already been removed. Projects with delete protection enabled cannot be deleted until protection is disabled. **Required Permissions** Your root key must have one of the following permissions: - `project.*.delete_project` (to delete any project) - `project..delete_project` (to delete a specific project) operationId: projects.deleteProject requestBody: content: application/json: examples: deleteById: description: Delete a project using its unique identifier summary: Delete by project ID value: project: proj_1234abcd deleteBySlug: description: Delete a project using its slug summary: Delete by project slug value: project: payment-service schema: $ref: '#/components/schemas/V2ProjectsDeleteProjectRequestBody' required: true responses: "202": content: application/json: examples: success: description: Project deletion was successfully enqueued summary: Deletion enqueued value: data: {} meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2ProjectsDeleteProjectResponseBody' description: | Successfully enqueued deletion of the project. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'project.*.delete_project' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `project.*.delete_project`) "404": content: application/json: examples: projectNotFound: summary: Project not found value: error: detail: The requested project does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested project does not exist in your workspace "412": content: application/json: schema: $ref: '#/components/schemas/PreconditionFailedErrorResponse' description: Delete protection is enabled. Disable protection through the dashboard or API, then retry the deletion. "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Delete project tags: - projects x-speakeasy-name-override: deleteProject /v2/projects.getProject: post: description: | Retrieve a single project in your workspace by its id. Use this to fetch project details after creation, verify a project exists before performing operations, or resolve a project's metadata from its id. **Required Permissions** Your root key must have one of the following permissions: - `project.*.read_project` (to read any project) - `project..read_project` (to read a specific project) operationId: projects.getProject requestBody: content: application/json: examples: getById: description: Fetch a project using its unique identifier summary: Retrieve by project ID value: project: proj_1234abcd getBySlug: description: Fetch a project using its slug summary: Retrieve by project slug value: project: payment-service schema: $ref: '#/components/schemas/V2ProjectsGetProjectRequestBody' required: true responses: "200": content: application/json: examples: project: description: Successfully retrieved a project summary: Project details value: data: createdAt: 1704067200000 deleteProtection: true id: proj_1234abcd name: Payments Service slug: payments-service updatedAt: 1704153600000 meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2ProjectsGetProjectResponseBody' description: | Successfully retrieved the project. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'project.*.read_project' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `project.*.read_project`) "404": content: application/json: examples: projectNotFound: summary: Project not found value: error: detail: The requested project does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested project does not exist in your workspace "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Get project tags: - projects x-speakeasy-name-override: getProject /v2/projects.listProjects: post: description: | Retrieve a paginated list of projects in your workspace. Use this to build project management dashboards or to enumerate projects for administrative purposes. Results are ordered by project id and returned in pages. When `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have the following permission: - `project.*.read_project` (to read projects in your workspace) operationId: projects.listProjects requestBody: content: application/json: examples: basic: description: List the first page of projects in your workspace summary: List all projects value: {} schema: $ref: '#/components/schemas/V2ProjectsListProjectsRequestBody' required: true responses: "200": content: application/json: examples: projectList: description: Successfully retrieved a page of projects summary: Project list value: data: - createdAt: 1704067200000 deleteProtection: true id: proj_1234abcd name: Payments Service slug: payments-service updatedAt: 1704153600000 - createdAt: 1704240000000 deleteProtection: false id: proj_5678efgh name: Billing Service slug: billing-service meta: requestId: req_1234abcd pagination: cursor: proj_5678efgh hasMore: false schema: $ref: '#/components/schemas/V2ProjectsListProjectsResponseBody' description: | Successfully retrieved a paginated list of projects. Use the pagination cursor for additional results when `hasMore: true`. "400": content: application/json: examples: invalidLimit: summary: Invalid limit value: error: detail: The limit must be between 1 and 100. errors: - fix: Use a limit between 1 and 100 location: body.limit message: must be less than or equal to 100 status: 400 title: Bad Request type: validation-error meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'project.*.read_project' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `project.*.read_project`) "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: List projects tags: - projects x-speakeasy-name-override: listProjects x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/projects.updateProject: post: description: | Update an existing project in your workspace, identified by its id. The project name, slug, and delete protection setting can be changed. Omitted fields are left unchanged. Changing the slug affects the deployment domains generated for this project. **Required Permissions** Your root key must have one of the following permissions: - `project.*.update_project` (to update any project) - `project..update_project` (to update a specific project) operationId: projects.updateProject requestBody: content: application/json: examples: changeSlug: description: Locate the project by its current slug and assign a new one summary: Change a project slug by slug value: project: payments-service slug: payments-api rename: description: Update only the display name, locating the project by its ID summary: Rename a project by ID value: name: Payments API project: proj_1234abcd schema: $ref: '#/components/schemas/V2ProjectsUpdateProjectRequestBody' required: true responses: "200": content: application/json: examples: project: description: Successfully updated a project summary: Updated project value: data: createdAt: 1704067200000 deleteProtection: true id: proj_1234abcd name: Payments API slug: payments-service updatedAt: 1704153600000 meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/V2ProjectsUpdateProjectResponseBody' description: | Successfully updated the project. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'project.*.update_project' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `project.*.update_project`) "404": content: application/json: examples: projectNotFound: summary: Project not found value: error: detail: The requested project does not exist. status: 404 title: Not Found type: not-found meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - The requested project does not exist in your workspace "409": content: application/json: examples: projectExists: summary: Project already exists value: error: detail: A project with slug 'payments-api' already exists in this workspace. status: 409 title: Conflict type: conflict meta: requestId: req_1234abcd schema: $ref: '#/components/schemas/ConflictErrorResponse' description: Conflict - Project with this slug already exists "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Update project tags: - projects x-speakeasy-name-override: updateProject /v2/ratelimit.deleteOverride: post: description: | Permanently remove a rate limit override. Affected identifiers immediately revert to the namespace default. Use this to remove temporary overrides, reset identifiers to standard limits, or clean up outdated rules. **Important:** Deletion is immediate and permanent. The override cannot be recovered and must be recreated if needed again. **Permissions:** Requires `ratelimit.*.delete_override` or `ratelimit..delete_override` operationId: ratelimit.deleteOverride requestBody: content: application/json: examples: specific: summary: Delete specific override value: identifier: premium_user_123 namespace: api.requests wildcard: summary: Delete wildcard pattern override value: identifier: premium_* namespace: api.requests schema: $ref: '#/components/schemas/V2RatelimitDeleteOverrideRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2RatelimitDeleteOverrideResponseBody' description: Override successfully deleted. Affected identifiers now use default limits. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'ratelimit.*.delete_override' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `ratelimit.*.delete_override`) "404": content: application/json: examples: overrideNotFound: summary: Override not found value: error: detail: No override found for the specified identifier in this namespace. status: 404 title: Not Found type: not_found meta: requestId: req_2wXyZaAbCdEfGhIjKlMnOp schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - Override or namespace not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Delete ratelimit override tags: - ratelimit x-speakeasy-name-override: deleteOverride /v2/ratelimit.getOverride: post: description: | Retrieve the configuration of a specific rate limit override by its identifier. Use this to inspect override configurations, audit rate limiting policies, or debug rate limiting behavior. **Important:** The identifier must match exactly as specified when creating the override, including wildcard patterns. **Permissions:** Requires `ratelimit.*.read_override` or `ratelimit..read_override` operationId: ratelimit.getOverride requestBody: content: application/json: examples: specific: summary: Get specific override value: identifier: premium_user_123 namespace: api.requests wildcard: summary: Get wildcard pattern override value: identifier: premium_* namespace: api.requests schema: $ref: '#/components/schemas/V2RatelimitGetOverrideRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2RatelimitGetOverrideResponseBody' description: Override found and returned successfully. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'ratelimit.*.read_override' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `ratelimit.*.read_override`) "404": content: application/json: examples: overrideNotFound: summary: Override not found value: error: detail: No override found for the specified identifier in this namespace. status: 404 title: Not Found type: not_found meta: requestId: req_2wXyZaAbCdEfGhIjKlMnOp schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - Override or namespace not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Get ratelimit override tags: - ratelimit x-speakeasy-name-override: getOverride /v2/ratelimit.limit: post: description: | Check and enforce rate limits for any identifier (user ID, IP address, API client, etc.). Use this for rate limiting beyond API keys - limit users by ID, IPs by address, or any custom identifier. Supports namespace organization, variable costs, and custom overrides. **Response Codes**: Rate limit checks return HTTP 200 regardless of whether the limit is exceeded — check the `success` field in the response to determine if the request should be allowed. A 429 may be returned if the workspace exceeds its API rate limit. Other 4xx responses indicate auth, namespace existence/deletion, or validation errors (e.g., 410 Gone for deleted namespaces). 5xx responses indicate server errors. **Required Permissions** Your root key must have one of the following permissions: - `ratelimit.*.limit` (to check limits in any namespace) - `ratelimit..limit` (to check limits in a specific namespace) operationId: ratelimit.limit requestBody: content: application/json: examples: basic: summary: Basic rate limit check value: duration: 60000 identifier: user_abc123 limit: 100 namespace: api.requests ipLimit: summary: IP-based rate limiting value: duration: 60000 identifier: 203.0.113.42 limit: 5 namespace: auth.login weightedCost: summary: Operation with variable cost value: cost: 5 duration: 3600000 identifier: user_def456 limit: 50 namespace: api.heavy_operations schema: $ref: '#/components/schemas/V2RatelimitLimitRequestBody' required: true responses: "200": content: application/json: examples: allowed: summary: Request allowed value: data: limit: 100 remaining: 99 reset: 1714582980000 success: true meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX limitReached: summary: Rate limit exceeded value: data: limit: 100 remaining: 0 reset: 1714582980000 success: false meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQY withOverride: summary: With custom override applied value: data: limit: 1000 overrideId: ovr_2cGKbMxRyIzhCxo1Idjz8q remaining: 995 reset: 1714582980000 success: true meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQZ schema: $ref: '#/components/schemas/V2RatelimitLimitResponseBody' description: | Rate limit check completed successfully. Check the `success` field to determine if the request is allowed. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "410": content: application/json: schema: $ref: '#/components/schemas/GoneErrorResponse' description: Gone - Namespace has been deleted "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Apply rate limiting tags: - ratelimit x-speakeasy-name-override: limit /v2/ratelimit.listOverrides: post: description: | Retrieve a paginated list of all rate limit overrides in a namespace. Use this to audit rate limiting policies, build admin dashboards, or manage override configurations. **Important:** Results are paginated. Use the cursor parameter to retrieve additional pages when more results are available. **Permissions:** Requires `ratelimit.*.read_override` or `ratelimit..read_override` operationId: ratelimit.listOverrides requestBody: content: application/json: examples: basic: summary: List all overrides value: limit: 20 namespace: api.requests pagination: summary: Get next page value: cursor: cursor_eyJsYXN0SWQiOiJvdnJfM2RITGNOeVN6SnppRHlwMkpla2E5ciJ9 namespace: api.requests schema: $ref: '#/components/schemas/V2RatelimitListOverridesRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2RatelimitListOverridesResponseBody' description: Overrides retrieved successfully. Includes pagination metadata if more results are available. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'ratelimit.*.read_override' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `ratelimit.*.read_override`) "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Error security: - bearer: [] summary: List ratelimit overrides tags: - ratelimit x-speakeasy-name-override: listOverrides x-speakeasy-pagination: inputs: - in: requestBody name: cursor type: cursor outputs: nextCursor: $.pagination.cursor type: cursor /v2/ratelimit.multiLimit: post: description: | Check and enforce multiple rate limits in a single request for any identifiers (user IDs, IP addresses, API clients, etc.). Use this to efficiently check multiple rate limits at once. Each rate limit check is independent and returns its own result with a top-level `passed` indicator showing if all checks succeeded. **Response Codes**: Rate limit checks return HTTP 200 regardless of whether limits are exceeded — check the `passed` field to see if all limits passed, or the `success` field in each individual result. A 429 may be returned if the workspace exceeds its API rate limit. Other 4xx responses indicate auth, namespace existence/deletion, or validation errors (e.g., 410 Gone for deleted namespaces). 5xx responses indicate server errors. **Required Permissions** Your root key must have one of the following permissions: - `ratelimit.*.limit` (to check limits in any namespace) - `ratelimit..limit` (to check limits in all specific namespaces being checked) operationId: ratelimit.multiLimit requestBody: content: application/json: examples: ipHashAndUserLimits: summary: Check both hashed IP and user rate limits value: - duration: 60000 identifier: sha256_8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4 limit: 10 namespace: auth.login - duration: 3600000 identifier: user_def456 limit: 1000 namespace: api.requests multipleChecks: summary: Multiple rate limit checks value: - duration: 60000 identifier: user_abc123 limit: 100 namespace: api.requests - duration: 60000 identifier: user_abc123 limit: 5 namespace: auth.login withWeightedCost: summary: Multiple checks with variable costs value: - cost: 1 duration: 60000 identifier: user_xyz789 limit: 100 namespace: api.light_operations - cost: 5 duration: 3600000 identifier: user_xyz789 limit: 50 namespace: api.heavy_operations schema: $ref: '#/components/schemas/V2RatelimitMultiLimitRequestBody' required: true responses: "200": content: application/json: examples: allAllowed: summary: All requests allowed value: data: limits: - identifier: user_abc123 limit: 100 namespace: api.requests remaining: 99 reset: 1714582980000 success: true - identifier: user_abc123 limit: 5 namespace: auth.login remaining: 4 reset: 1714582980000 success: true passed: true meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX mixedResults: summary: Some limits exceeded value: data: limits: - identifier: sha256_8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4 limit: 10 namespace: auth.login remaining: 5 reset: 1714582980000 success: true - identifier: user_def456 limit: 1000 namespace: api.requests remaining: 0 reset: 1714583040000 success: false passed: false meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQY withOverride: summary: With custom override applied value: data: limits: - identifier: user_xyz789 limit: 100 namespace: api.light_operations remaining: 95 reset: 1714582980000 success: true - identifier: user_xyz789 limit: 1000 namespace: api.heavy_operations overrideId: ovr_2cGKbMxRyIzhCxo1Idjz8q remaining: 995 reset: 1714582980000 success: true passed: true meta: requestId: req_01H9TQPP77V5E48E9SH0BG0ZQZ schema: $ref: '#/components/schemas/V2RatelimitMultiLimitResponseBody' description: | All rate limit checks completed successfully. Check the `success` field in each result to determine if the corresponding request is allowed. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden "404": content: application/json: schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found "410": content: application/json: schema: $ref: '#/components/schemas/GoneErrorResponse' description: Gone - Namespace has been deleted "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal server error security: - bearer: [] summary: Apply multiple rate limit checks tags: - ratelimit x-speakeasy-name-override: multiLimit /v2/ratelimit.setOverride: post: description: | Create or update a custom rate limit for specific identifiers, bypassing the namespace default. Use this to create premium tiers with higher limits, apply stricter limits to specific users, or implement emergency throttling. **Important:** Overrides take effect immediately and completely replace the default limit for matching identifiers. Use wildcard patterns (e.g., `premium_*`) to match multiple identifiers. **Permissions:** Requires `ratelimit.*.set_override` or `ratelimit..set_override` operationId: ratelimit.setOverride requestBody: content: application/json: examples: premium: summary: Higher limit for premium user value: duration: 60000 identifier: premium_user_123 limit: 1000 namespace: api.requests wildcard: summary: Pattern for multiple identifiers value: duration: 60000 identifier: premium_* limit: 500 namespace: api.requests schema: $ref: '#/components/schemas/V2RatelimitSetOverrideRequestBody' required: true responses: "200": content: application/json: schema: $ref: '#/components/schemas/V2RatelimitSetOverrideResponseBody' description: Override successfully created or updated and is now active. "400": content: application/json: schema: $ref: '#/components/schemas/BadRequestErrorResponse' description: Bad request "401": content: application/json: schema: $ref: '#/components/schemas/UnauthorizedErrorResponse' description: Unauthorized "403": content: application/json: examples: missingPermission: summary: Missing required permission value: error: detail: Your root key requires the 'ratelimit.*.set_override' permission to perform this operation status: 403 title: Forbidden type: forbidden meta: requestId: req_0uVwX4yZaAbCdEfGhIjKl schema: $ref: '#/components/schemas/ForbiddenErrorResponse' description: Forbidden - Insufficient permissions (requires `ratelimit.*.set_override`) "404": content: application/json: examples: namespaceNotFound: summary: Namespace not found value: error: detail: This namespace does not exist. status: 404 title: Not Found type: not_found meta: requestId: req_2wXyZaAbCdEfGhIjKlMnOp schema: $ref: '#/components/schemas/NotFoundErrorResponse' description: Not Found - Namespace not found "429": content: application/problem+json: schema: $ref: '#/components/schemas/TooManyRequestsErrorResponse' description: Too Many Requests "500": content: application/json: schema: $ref: '#/components/schemas/InternalServerErrorResponse' description: Internal Server Error security: - bearer: [] summary: Set ratelimit override tags: - ratelimit x-speakeasy-name-override: setOverride security: - bearer: [] servers: - url: https://api.unkey.com tags: - description: Analytics query operations name: analytics - description: API management operations name: apis - description: App management operations name: apps - description: Deployment operations name: deploy - description: Deployment operations name: deployments - description: Environment management operations name: environments - description: Identity management operations name: identities - description: API key management operations name: keys - description: Health check operations name: liveness - description: Permission and role management operations name: permissions - description: Gateway policy operations name: gateway - description: Customer Portal session management name: portal - description: Rate limiting operations name: ratelimit x-speakeasy-retries: backoff: exponent: 1.5 initialInterval: 50 maxElapsedTime: 10000 maxInterval: 1000 retryConnectionErrors: true statusCodes: - 5XX strategy: backoff