Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions api-reference/authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,21 @@ API keys are prefixed with `om_` for production.

See [Quickstart](/quickstart) for the full setup flow.

## Multiple API keys

Your account has a primary key (shown in the dashboard), and you can issue additional **named** keys via the API:

- `POST /v1/api-keys` with `{ "name": "..." }` creates a key and returns its value **once** — store it securely.
- `GET /v1/api-keys` lists your keys with masked previews (the full value is never returned again).
- `DELETE /v1/api-keys/{id}` revokes a key immediately.

Issue separate keys per environment or per fleet so you can revoke one without disrupting the others. You don't need to round-robin keys to scale — [rate limits](/concepts/rate-limits) are mostly per inbox, so spread load across inboxes instead.

## Security

- Keep your API key secret. Do not expose it in client-side code.
- Keep your API keys secret. Do not expose them in client-side code.
- Each API key is scoped to a single account. Requests authenticate to the account that owns the key.
- If you believe your key has been compromised, contact support immediately for rotation.
- If you believe a key has been compromised, revoke it with `DELETE /v1/api-keys/{id}` (or rotate the primary key from the dashboard).

## Invalid authentication

Expand Down
162 changes: 162 additions & 0 deletions api-reference/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,125 @@
}
}
},
"/v1/api-keys": {
"get": {
"summary": "List API keys",
"description": "List the account's named API keys. The full key value is never returned — only a masked preview.",
"operationId": "listApiKeys",
"responses": {
"200": {
"description": "API keys",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ApiKey"
}
},
"total": {
"type": "integer"
}
}
}
}
}
}
}
},
"post": {
"summary": "Create API key",
"description": "Create a new named API key. The full key is returned exactly once in this response — store it securely. Use this to issue multiple scoped keys (e.g. one per environment or fleet) instead of round-robining a single key.",
"operationId": "createApiKey",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
}
}
}
}
}
},
"responses": {
"201": {
"description": "API key created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ApiKeyWithSecret"
}
}
}
},
"400": {
"description": "Missing name",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Per-account API key limit reached",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/v1/api-keys/{id}": {
"delete": {
"summary": "Revoke API key",
"description": "Revoke a named API key. Idempotent; already-revoked keys return 204.",
"operationId": "revokeApiKey",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"description": "API key revoked"
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/v1/usage": {
"get": {
"summary": "Get usage",
Expand Down Expand Up @@ -1064,6 +1183,49 @@
}
}
},
"ApiKey": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"keyPreview": {
"type": "string",
"description": "Masked preview, e.g. om_****1a2b"
},
"lastUsedAt": {
"type": "string",
"format": "date-time",
"nullable": true
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},
"ApiKeyWithSecret": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"key": {
"type": "string",
"description": "Full key — returned only on creation"
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},
"InboxUsage": {
"type": "object",
"properties": {
Expand Down
99 changes: 99 additions & 0 deletions scripts/generate-openapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,86 @@ const spec = {
},
},
},
"/v1/api-keys": {
get: {
summary: "List API keys",
description:
"List the account's named API keys. The full key value is never returned — only a masked preview.",
operationId: "listApiKeys",
responses: {
"200": {
description: "API keys",
content: {
"application/json": {
schema: {
type: "object",
properties: {
data: {
type: "array",
items: { $ref: "#/components/schemas/ApiKey" },
},
total: { type: "integer" },
},
},
},
},
},
},
},
post: {
summary: "Create API key",
description:
"Create a new named API key. The full key is returned exactly once in this response — store it securely. Use this to issue multiple scoped keys (e.g. one per environment or fleet) instead of round-robining a single key.",
operationId: "createApiKey",
requestBody: {
required: true,
content: {
"application/json": {
schema: {
type: "object",
required: ["name"],
properties: {
name: { type: "string", minLength: 1, maxLength: 100 },
},
},
},
},
},
responses: {
"201": {
description: "API key created",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/ApiKeyWithSecret" },
},
},
},
"400": {
description: "Missing name",
content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } },
},
"422": {
description: "Per-account API key limit reached",
content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } },
},
},
},
},
"/v1/api-keys/{id}": {
delete: {
summary: "Revoke API key",
description: "Revoke a named API key. Idempotent; already-revoked keys return 204.",
operationId: "revokeApiKey",
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" } }],
responses: {
"204": { description: "API key revoked" },
"404": {
description: "Not found",
content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } },
},
},
},
},
"/v1/usage": {
get: {
summary: "Get usage",
Expand Down Expand Up @@ -614,6 +694,25 @@ const spec = {
createdAt: { type: "string", format: "date-time" },
},
},
ApiKey: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
keyPreview: { type: "string", description: "Masked preview, e.g. om_****1a2b" },
lastUsedAt: { type: "string", format: "date-time", nullable: true },
createdAt: { type: "string", format: "date-time" },
},
},
ApiKeyWithSecret: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
key: { type: "string", description: "Full key — returned only on creation" },
createdAt: { type: "string", format: "date-time" },
},
},
InboxUsage: {
type: "object",
properties: {
Expand Down