openapi: 3.1.0
info:
title: Unkey API
description: >-
Unkey is an open-source developer platform for API key management,
authentication, and rate limiting. This is an API Evangelist modeling of
Unkey's RPC-style REST API, grounded in Unkey's own published OpenAPI. All
operations use POST and are grouped into service namespaces
(keys, apis, ratelimit, identities, permissions, analytics, deploy,
liveness). The stable v2 API is served from https://api.unkey.com; the
legacy v1 API is served from https://api.unkey.dev with /v1/* paths.
Authentication uses HTTP Bearer authentication with a root key:
`Authorization: Bearer unkey_xxxxxxxxxxx`. Most endpoints require specific
permissions on the root key. Responses use a consistent envelope with a
`meta.requestId`, a `data` object (or array plus `pagination` on list
endpoints), and a structured `error` object on failures.
version: 2.0.0
contact:
name: Unkey
url: https://www.unkey.com
license:
name: AGPL-3.0
url: https://github.com/unkeyed/unkey/blob/main/LICENSE.md
servers:
- url: https://api.unkey.com
description: Unkey v2 (current)
- url: https://api.unkey.dev
description: Unkey v1 (legacy)
security:
- rootKey: []
tags:
- name: keys
description: API key management operations.
- name: apis
description: API (namespace) management operations.
- name: ratelimit
description: Standalone rate limiting and override operations.
- name: identities
description: Identity (tenant / user) management operations.
- name: permissions
description: Permission and role (RBAC) management operations.
- name: analytics
description: Key-verification analytics query operations.
- name: deploy
description: Deployment operations.
- name: liveness
description: Health check operations.
paths:
/v2/keys.createKey:
post:
operationId: keys.createKey
tags: [keys]
summary: Create a key
description: >-
Creates a new API key in a given API (namespace). Supports name, prefix,
byteLength, externalId (identity link), meta, expiration, remaining
usage credits, refill, ratelimits, permissions, and roles. Returns the
plaintext key once and its keyId.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
/v2/keys.verifyKey:
post:
operationId: keys.verifyKey
tags: [keys]
summary: Verify a key
description: >-
Verifies an API key on the request hot path. Checks validity,
expiration, remaining credits, ratelimits, permissions, and roles, and
returns the key's metadata plus any linked identity. This is the
endpoint API providers call on every incoming request.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/keys.getKey:
post:
operationId: keys.getKey
tags: [keys]
summary: Get a key
description: Retrieves metadata about a single key by its keyId.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/keys.updateKey:
post:
operationId: keys.updateKey
tags: [keys]
summary: Update a key
description: >-
Updates a key's mutable attributes - name, meta, expiration, enabled
state, external identity, ratelimits, remaining credits, permissions,
and roles.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/keys.deleteKey:
post:
operationId: keys.deleteKey
tags: [keys]
summary: Delete a key
description: Permanently deletes (or soft-deletes) a key so it can no longer be verified.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/keys.rerollKey:
post:
operationId: keys.rerollKey
tags: [keys]
summary: Reroll a key
description: >-
Rotates a key by creating a new secret while preserving the key's
configuration and identity, optionally keeping the old key valid until
an expiration for a smooth migration.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/keys.updateCredits:
post:
operationId: keys.updateCredits
tags: [keys]
summary: Update key credits
description: Sets, increments, or decrements the remaining usage credits on a key.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/keys.whoami:
post:
operationId: keys.whoami
tags: [keys]
summary: Who am I
description: Resolves a plaintext key to its keyId and metadata without a full verification.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/keys.migrateKeys:
post:
operationId: keys.migrateKeys
tags: [keys]
summary: Migrate keys
description: >-
Bulk-imports existing keys (by hash) from another system into an Unkey
namespace, preserving prefixes and metadata so customers keep their
current keys.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/keys.addPermissions:
post:
operationId: keys.addPermissions
tags: [keys]
summary: Add permissions to a key
description: Attaches one or more permissions to a key, creating them if requested.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/keys.removePermissions:
post:
operationId: keys.removePermissions
tags: [keys]
summary: Remove permissions from a key
description: Detaches one or more permissions from a key.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/keys.setPermissions:
post:
operationId: keys.setPermissions
tags: [keys]
summary: Set key permissions
description: Replaces the full set of permissions on a key with the provided list.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/keys.addRoles:
post:
operationId: keys.addRoles
tags: [keys]
summary: Add roles to a key
description: Attaches one or more roles to a key.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/keys.removeRoles:
post:
operationId: keys.removeRoles
tags: [keys]
summary: Remove roles from a key
description: Detaches one or more roles from a key.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/keys.setRoles:
post:
operationId: keys.setRoles
tags: [keys]
summary: Set key roles
description: Replaces the full set of roles on a key with the provided list.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/apis.createApi:
post:
operationId: apis.createApi
tags: [apis]
summary: Create an API
description: Creates a new API (namespace / keyspace) that keys are issued into and verified against.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/apis.getApi:
post:
operationId: apis.getApi
tags: [apis]
summary: Get an API
description: Retrieves an API (namespace) by its apiId.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/apis.deleteApi:
post:
operationId: apis.deleteApi
tags: [apis]
summary: Delete an API
description: Deletes an API namespace and, depending on settings, its keys.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/apis.listKeys:
post:
operationId: apis.listKeys
tags: [apis]
summary: List keys for an API
description: Lists the keys belonging to an API namespace, with cursor pagination.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/PaginatedSuccess' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/ratelimit.limit:
post:
operationId: ratelimit.limit
tags: [ratelimit]
summary: Ratelimit
description: >-
Checks and enforces a rate limit for an identifier within a namespace.
Returns whether the request is allowed plus remaining, limit, and reset.
Works standalone, without an API key.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/ratelimit.multiLimit:
post:
operationId: ratelimit.multiLimit
tags: [ratelimit]
summary: Multi ratelimit
description: Evaluates several rate limits in a single request and returns the combined result.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/ratelimit.setOverride:
post:
operationId: ratelimit.setOverride
tags: [ratelimit]
summary: Set ratelimit override
description: Sets a per-identifier override of the limit and duration within a namespace.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/ratelimit.getOverride:
post:
operationId: ratelimit.getOverride
tags: [ratelimit]
summary: Get ratelimit override
description: Retrieves a rate limit override for an identifier in a namespace.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/ratelimit.listOverrides:
post:
operationId: ratelimit.listOverrides
tags: [ratelimit]
summary: List ratelimit overrides
description: Lists the rate limit overrides configured in a namespace, with cursor pagination.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/PaginatedSuccess' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/ratelimit.deleteOverride:
post:
operationId: ratelimit.deleteOverride
tags: [ratelimit]
summary: Delete ratelimit override
description: Deletes a rate limit override for an identifier in a namespace.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/identities.createIdentity:
post:
operationId: identities.createIdentity
tags: [identities]
summary: Create an identity
description: >-
Creates an identity representing a user, tenant, or organization, keyed
by an externalId, with optional meta and shared ratelimits that all of
the identity's keys inherit.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/identities.getIdentity:
post:
operationId: identities.getIdentity
tags: [identities]
summary: Get an identity
description: Retrieves an identity by its identityId or externalId.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/identities.listIdentities:
post:
operationId: identities.listIdentities
tags: [identities]
summary: List identities
description: Lists identities in the workspace, with cursor pagination.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/PaginatedSuccess' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/identities.updateIdentity:
post:
operationId: identities.updateIdentity
tags: [identities]
summary: Update an identity
description: Updates an identity's meta and shared ratelimits.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/identities.deleteIdentity:
post:
operationId: identities.deleteIdentity
tags: [identities]
summary: Delete an identity
description: Deletes an identity and detaches it from its keys.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/permissions.createPermission:
post:
operationId: permissions.createPermission
tags: [permissions]
summary: Create a permission
description: Creates a permission that can be attached to keys and roles.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/permissions.getPermission:
post:
operationId: permissions.getPermission
tags: [permissions]
summary: Get a permission
description: Retrieves a permission by id or name.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/permissions.listPermissions:
post:
operationId: permissions.listPermissions
tags: [permissions]
summary: List permissions
description: Lists permissions in the workspace, with cursor pagination.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/PaginatedSuccess' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/permissions.deletePermission:
post:
operationId: permissions.deletePermission
tags: [permissions]
summary: Delete a permission
description: Deletes a permission and removes it from keys and roles.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/permissions.createRole:
post:
operationId: permissions.createRole
tags: [permissions]
summary: Create a role
description: Creates a role, a named bundle of permissions that can be attached to keys.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/permissions.getRole:
post:
operationId: permissions.getRole
tags: [permissions]
summary: Get a role
description: Retrieves a role and its permissions by id or name.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/permissions.listRoles:
post:
operationId: permissions.listRoles
tags: [permissions]
summary: List roles
description: Lists roles in the workspace, with cursor pagination.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/PaginatedSuccess' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/permissions.deleteRole:
post:
operationId: permissions.deleteRole
tags: [permissions]
summary: Delete a role
description: Deletes a role and detaches it from keys.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/analytics.getVerifications:
post:
operationId: analytics.getVerifications
tags: [analytics]
summary: Get verifications
description: >-
Queries key-verification analytics over a time range, grouped and
filtered by key, identity, outcome, and more, for usage dashboards,
billing, and abuse detection.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/deploy.createDeployment:
post:
operationId: deploy.createDeployment
tags: [deploy]
summary: Create a deployment
description: Creates a deployment on the Unkey deploy platform.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
/v2/deploy.getDeployment:
post:
operationId: deploy.getDeployment
tags: [deploy]
summary: Get a deployment
description: Retrieves a deployment by its id.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenericRequest'
responses:
'200': { $ref: '#/components/responses/Success' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
/v2/liveness:
post:
operationId: liveness
tags: [liveness]
summary: Liveness check
description: Simple health check that returns a 200 when the API is available.
responses:
'200': { $ref: '#/components/responses/Success' }
components:
securitySchemes:
rootKey:
type: http
scheme: bearer
description: >-
HTTP Bearer authentication with an Unkey root key, passed as
`Authorization: Bearer unkey_xxxxxxxxxxx`. Most endpoints require
specific permissions on the root key.
responses:
Success:
description: Successful response using the standard Unkey envelope.
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessEnvelope'
PaginatedSuccess:
description: Successful list response with cursor pagination.
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedEnvelope'
BadRequest:
description: The request payload failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
Unauthorized:
description: Missing or invalid root key.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
Forbidden:
description: The root key lacks the permission required for this operation.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
NotFound:
description: The requested resource was not found.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
schemas:
GenericRequest:
type: object
description: >-
Request body for an RPC-style operation. The concrete fields depend on
the operation (for example keyId, apiId, key, namespace, identifier,
externalId, permissions, roles). See the Unkey API reference for the
per-operation schema.
additionalProperties: true
Meta:
type: object
properties:
requestId:
type: string
description: Unique identifier for this request, useful for support and tracing.
Pagination:
type: object
properties:
cursor:
type: string
description: Token for requesting the next page.
hasMore:
type: boolean
description: Whether more results are available.
SuccessEnvelope:
type: object
properties:
meta:
$ref: '#/components/schemas/Meta'
data:
type: object
additionalProperties: true
PaginatedEnvelope:
type: object
properties:
meta:
$ref: '#/components/schemas/Meta'
data:
type: array
items:
type: object
additionalProperties: true
pagination:
$ref: '#/components/schemas/Pagination'
ErrorEnvelope:
type: object
properties:
meta:
$ref: '#/components/schemas/Meta'
error:
type: object
properties:
title:
type: string
description: Human-readable error summary.
detail:
type: string
description: Specific description of what went wrong.
status:
type: integer
description: HTTP status code.
type:
type: string
format: uri
description: Link to error documentation.
errors:
type: array
description: Array of validation errors (for 400 responses).
items:
type: object
additionalProperties: true