Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: OpenMail Inboxes API
description: Email infrastructure API for AI agents. Create inboxes, send and receive email, and get real-time notifications via webhooks.
version: 1.0.0
license:
name: Proprietary
servers:
- url: https://api.openmail.sh
security:
- bearerAuth: []
tags:
- name: Inboxes
description: Email inboxes and their webhook configuration
paths:
/v1/inboxes:
post:
operationId: createInbox
summary: Create inbox
tags:
- Inboxes
description: Create a new email inbox. Optionally set a sender display name.
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
mailboxName:
type: string
minLength: 3
maxLength: 30
description: 'Inbox local part (default: random)'
displayName:
type: string
maxLength: 200
description: Sender display name shown in the From header
domain:
type: string
description: Domain for the inbox address. Defaults to your account domain (e.g. `openmail.sh`). Pass a verified custom domain you own to create the inbox on it (e.g. `agent-mail.example.com`). The domain must already be added and verified for your account; the account default never switches automatically.
webhookUrl:
type: string
minLength: 0
description: URL to receive signed webhook events for this inbox (e.g. inbound mail). Overrides the account-level webhook for this inbox only. A signing secret is generated and returned once in the response body.
forwardTo:
type: string
format: email
description: Email address that receives a copy of inbound messages, e.g. your own Gmail. Members of your organisation are confirmed at once; any other address is emailed a confirmation link and nothing is forwarded until they click it (`forwardStatus` is `pending` meanwhile). Spam and bulk mail are never forwarded. Replies go to the original sender.
forwardWhen:
type: string
enum:
- always
- needs_human
- webhook_failed
description: When to forward. `always` (default); `needs_human` only mail the agent should not auto-handle (`autoReplyable` false); `webhook_failed` only once webhook delivery has exhausted its retries or there was no webhook or WebSocket to deliver to.
podId:
type: string
description: Pod to create the inbox in. Accepts the pod ID or your own `clientId`. Omit to place the inbox in your account's default pod.
responses:
'201':
description: Inbox created
content:
application/json:
schema:
description: Inbox created
allOf:
- $ref: '#/components/schemas/Inbox'
'400':
description: Invalid mailbox name, `domain` is not verified or not available in the selected pod, or `podId` does not match a pod in your account
content:
application/json:
schema:
description: Invalid mailbox name, `domain` is not verified or not available in the selected pod, or `podId` does not match a pod in your account
allOf:
- $ref: '#/components/schemas/Error'
'402':
description: 'Pro plan: inbox creation is paused because the account''s monthly spend limit was reached'
content:
application/json:
schema:
description: 'Pro plan: inbox creation is paused because the account''s monthly spend limit was reached'
allOf:
- $ref: '#/components/schemas/Error'
'409':
description: Address already in use, or the mailbox name is reserved
content:
application/json:
schema:
description: Address already in use, or the mailbox name is reserved
allOf:
- $ref: '#/components/schemas/Error'
'422':
description: Plan inbox limit reached, `webhookUrl` failed validation (`invalid_webhook_url`), or forwarding settings were rejected (`invalid_forward_to`, `forward_to_is_openmail_address`, `forward_verification_cooldown`, `invalid_forward_when`, `forward_when_requires_forward_to`)
content:
application/json:
schema:
description: Plan inbox limit reached, `webhookUrl` failed validation (`invalid_webhook_url`), or forwarding settings were rejected (`invalid_forward_to`, `forward_to_is_openmail_address`, `forward_verification_cooldown`, `invalid_forward_when`, `forward_when_requires_forward_to`)
allOf:
- $ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded (100 inbox creations/day, or 10 forwarding confirmation emails/hour — `forward_verification_limit`)
content:
application/json:
schema:
description: Rate limit exceeded (100 inbox creations/day, or 10 forwarding confirmation emails/hour — `forward_verification_limit`)
allOf:
- $ref: '#/components/schemas/Error'
get:
operationId: listInboxes
summary: List inboxes
tags:
- Inboxes
description: List all inboxes for your account. Supports pagination.
parameters:
- schema:
type: integer
default: 50
in: query
name: limit
required: false
description: Max results to return (clamped to 100)
- schema:
type: integer
default: 0
in: query
name: offset
required: false
description: Number of results to skip
- schema:
type: string
in: query
name: podId
required: false
description: Filter to inboxes in a single pod. Accepts the pod ID or your own `clientId`. An unknown value returns an empty list.
responses:
'200':
description: List of inboxes
content:
application/json:
schema:
description: List of inboxes
type: object
additionalProperties: true
properties:
data:
type: array
items:
$ref: '#/components/schemas/Inbox'
total:
type: integer
'401':
description: Missing, invalid, or expired API key
content:
application/json:
schema:
description: Missing, invalid, or expired API key
allOf:
- $ref: '#/components/schemas/Error'
/v1/inboxes/{id}:
get:
operationId: getInbox
summary: Get inbox
tags:
- Inboxes
description: Retrieve a single inbox by its ID, including its address, display name, and creation time.
parameters:
- schema:
type: string
in: path
name: id
required: true
responses:
'200':
description: Inbox details
content:
application/json:
schema:
description: Inbox details
allOf:
- $ref: '#/components/schemas/Inbox'
'404':
description: Not found
content:
application/json:
schema:
description: Not found
allOf:
- $ref: '#/components/schemas/Error'
patch:
operationId: updateInbox
summary: Update inbox
tags:
- Inboxes
description: Update an inbox's settings, such as the sender display name shown in the From header.
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
displayName:
type:
- string
- 'null'
maxLength: 200
description: Sender display name. Set null to clear.
webhookUrl:
type:
- string
- 'null'
minLength: 0
description: URL to receive signed webhook events for this inbox. Set null to clear and revert to the account-level webhook. A signing secret is generated the first time a webhook URL is set on this inbox and returned once in the response body.
forwardTo:
type:
- string
- 'null'
description: Email address that receives a copy of inbound messages, e.g. your own Gmail. Members of your organisation are confirmed at once; any other address is emailed a confirmation link and `forwardStatus` stays `pending` until they click it. Re-sending the same pending address re-issues the link. Setting a new address also re-enables forwarding that was paused for bouncing. Set null to stop forwarding.
forwardWhen:
type:
- string
- 'null'
enum:
- always
- needs_human
- webhook_failed
- null
description: When to forward. `always` (default); `needs_human` only mail the agent should not auto-handle (`autoReplyable` false); `webhook_failed` only once webhook delivery has exhausted its retries or there was no webhook or WebSocket to deliver to.
parameters:
- schema:
type: string
in: path
name: id
required: true
responses:
'200':
description: Inbox updated
content:
application/json:
schema:
description: Inbox updated
allOf:
- $ref: '#/components/schemas/Inbox'
'403':
description: The authenticating key is inbox-scoped (read + send only) and cannot modify the inbox
content:
application/json:
schema:
description: The authenticating key is inbox-scoped (read + send only) and cannot modify the inbox
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
description: Not found
allOf:
- $ref: '#/components/schemas/Error'
'422':
description: '`webhookUrl` failed validation (`invalid_webhook_url`), or forwarding settings were rejected (`invalid_forward_to`, `forward_to_is_openmail_address`, `forward_verification_cooldown`, `invalid_forward_when`, `forward_when_requires_forward_to`)'
content:
application/json:
schema:
description: '`webhookUrl` failed validation (`invalid_webhook_url`), or forwarding settings were rejected (`invalid_forward_to`, `forward_to_is_openmail_address`, `forward_verification_cooldown`, `invalid_forward_when`, `forward_when_requires_forward_to`)'
allOf:
- $ref: '#/components/schemas/Error'
'429':
description: 10 forwarding confirmation emails already sent this hour (`forward_verification_limit`)
content:
application/json:
schema:
description: 10 forwarding confirmation emails already sent this hour (`forward_verification_limit`)
allOf:
- $ref: '#/components/schemas/Error'
delete:
operationId: deleteInbox
summary: Delete inbox
tags:
- Inboxes
description: Permanently delete an inbox and stop delivery to its address. This action cannot be undone. An account-wide key or a pod-scoped key for this inbox's pod may delete it; an inbox-scoped key cannot.
parameters:
- schema:
type: string
in: path
name: id
required: true
responses:
'204':
description: Inbox deleted
'403':
description: The authenticating key is inbox-scoped, or a pod-scoped key for a different pod, and cannot delete this inbox
content:
application/json:
schema:
description: The authenticating key is inbox-scoped, or a pod-scoped key for a different pod, and cannot delete this inbox
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
description: Not found
allOf:
- $ref: '#/components/schemas/Error'
/v1/inboxes/{id}/webhook/rotate-secret:
post:
operationId: rotateInboxWebhookSecret
summary: Rotate webhook secret
tags:
- Inboxes
description: Generate a new signing secret for this inbox's webhook. The inbox must already have a webhook URL set. The previous secret is invalidated immediately.
parameters:
- schema:
type: string
in: path
name: id
required: true
responses:
'200':
description: New signing secret
content:
application/json:
schema:
description: New signing secret
type: object
additionalProperties: true
required:
- webhookSecret
properties:
webhookSecret:
type: string
'400':
description: No webhook URL is set on this inbox (`no_webhook_url`)
content:
application/json:
schema:
description: No webhook URL is set on this inbox (`no_webhook_url`)
allOf:
- $ref: '#/components/schemas/Error'
'403':
description: The authenticating key is inbox-scoped (read + send only) and cannot rotate webhook secrets
content:
application/json:
schema:
description: The authenticating key is inbox-scoped (read + send only) and cannot rotate webhook secrets
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
description: Not found
allOf:
- $ref: '#/components/schemas/Error'
/v1/inboxes/{id}/webhook/test:
post:
operationId: testInboxWebhook
summary: Send test webhook
tags:
- Inboxes
description: Send a signed test event to this inbox's webhook URL. Requires a webhook URL (and signing secret) to already be set on the inbox.
parameters:
- schema:
type: string
in: path
name: id
required: true
responses:
'200':
description: Test webhook sent successfully
content:
application/json:
schema:
description: Test webhook sent successfully
type: object
additionalProperties: true
properties:
ok:
type: boolean
message:
type: string
'400':
description: No webhook URL is set on this inbox (`no_webhook_url`)
content:
application/json:
schema:
description: No webhook URL is set on this inbox (`no_webhook_url`)
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
description: Not found
allOf:
- $ref: '#/components/schemas/Error'
'502':
description: The webhook endpoint returned an error status, or the request to it failed (`webhook_failed`)
content:
application/json:
schema:
description: The webhook endpoint returned an error status, or the request to it failed (`webhook_failed`)
allOf:
- $ref: '#/components/schemas/Error'
/v1/inboxes/{id}/api-keys:
post:
operationId: createInboxApiKey
summary: Create inbox API key
tags:
- Inboxes
description: Mint an API key scoped to this inbox. The key can only read and send from this one inbox — its threads, messages, and drafts — and can never reach another inbox, manage pods, or mint keys. The full `token` is returned once, here — store it securely, it cannot be retrieved again. An account-wide key, or a pod-scoped key for this inbox's pod, may mint; an inbox-scoped key cannot.
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
name:
type:
- string
- 'null'
maxLength: 255
description: Human-readable label to identify the key later.
parameters:
- schema:
type: string
in: path
name: id
required: true
description: Inbox ID
responses:
'201':
description: API key created
content:
application/json:
schema:
description: API key created
allOf:
- $ref: '#/components/schemas/ApiKeyWithToken'
'403':
description: The authenticating key is inbox-scoped, or a pod-scoped key for a different pod, and cannot mint keys
content:
application/json:
schema:
description: The authenticating key is inbox-scoped, or a pod-scoped key for a different pod, and cannot mint keys
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Inbox not found
content:
application/json:
schema:
description: Inbox not found
allOf:
- $ref: '#/components/schemas/Error'
'409':
description: The inbox is not assigned to a pod, so an inbox-scoped key cannot be minted for it (`inbox_has_no_pod`)
content:
application/json:
schema:
description: The inbox is not assigned to a pod, so an inbox-scoped key cannot be minted for it (`inbox_has_no_pod`)
allOf:
- $ref: '#/components/schemas/Error'
'422':
description: The inbox already has the maximum number of active keys (`api_key_limit_reached`)
content:
application/json:
schema:
description: The inbox already has the maximum number of active keys (`api_key_limit_reached`)
allOf:
- $ref: '#/components/schemas/Error'
get:
operationId: listInboxApiKeys
summary: List inbox API keys
tags:
- Inboxes
description: List the (non-revoked) API keys scoped to this inbox. Only non-secret fields are returned — the token itself is never retrievable after creation. An account-wide key, or a pod-scoped key for this inbox's pod, may list; an inbox-scoped key cannot.
parameters:
- schema:
type: string
in: path
name: id
required: true
description: Inbox ID
responses:
'200':
description: List of API keys
content:
application/json:
schema:
description: List of API keys
type: object
additionalProperties: true
properties:
data:
type: array
items:
$ref: '#/components/schemas/ApiKey'
'403':
description: The authenticating key is inbox-scoped, or a pod-scoped key for a different pod, and cannot manage keys
content:
application/json:
schema:
description: The authenticating key is inbox-scoped, or a pod-scoped key for a different pod, and cannot manage keys
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Inbox not found
content:
application/json:
schema:
description: Inbox not found
allOf:
- $ref: '#/components/schemas/Error'
/v1/inboxes/{id}/api-keys/{keyId}:
delete:
operationId: deleteInboxApiKey
summary: Revoke inbox API key
tags:
- Inboxes
description: Permanently revoke an inbox-scoped API key. Any integration using it immediately starts getting 401s. An account-wide key, or a pod-scoped key for this inbox's pod, may revoke; an inbox-scoped key cannot.
parameters:
- schema:
type: string
in: path
name: id
required: true
description: Inbox ID
- schema:
type: string
in: path
name: keyId
required: true
description: The API key ID to revoke
responses:
'204':
description: Key revoked
'403':
description: The authenticating key is inbox-scoped, or a pod-scoped key for a different pod, and cannot manage keys
content:
application/json:
schema:
description: The authenticating key is inbox-scoped, or a pod-scoped key for a different pod, and cannot manage keys
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Key not found
content:
application/json:
schema:
description: Key not found
allOf:
- $ref: '#/components/schemas/Error'
components:
schemas:
Inbox:
type: object
additionalProperties: true
properties:
id:
type: string
description: OpenMail inbox ID
podId:
type: string
description: ID of the pod this inbox belongs to. Inboxes created without an explicit pod land in your account's default pod.
address:
type: string
format: email
description: Full email address
displayName:
type:
- string
- 'null'
description: Sender display name
webhookUrl:
type:
- string
- 'null'
description: URL that receives signed webhook events for this inbox, if set. Overrides the account-level webhook for this inbox only.
webhookSecret:
type:
- string
- 'null'
description: Signing secret for this inbox's webhook. Only present in the response when the secret is generated or rotated (on create, on first setting a webhook URL, or via the rotate-secret endpoint) — it is never returned afterward.
forwardTo:
type:
- string
- 'null'
description: Address that receives copies of this inbox's inbound mail, if set.
forwardWhen:
type:
- string
- 'null'
enum:
- always
- needs_human
- webhook_failed
- null
description: Which inbound mail is forwarded. Null when forwarding is not set.
forwardStatus:
type:
- string
- 'null'
enum:
- pending
- active
- disabled
- null
description: '`pending` until the address confirms via the emailed link (members of your organisation are confirmed at once); `active` once copies are flowing; `disabled` when forwarding paused itself after the address hard-bounced repeatedly or complained — set `forwardTo` again to resume. Null when forwarding is not set.'
createdAt:
type: string
format: date-time
ApiKeyWithToken:
type: object
additionalProperties: true
description: An API key plus its raw `token`. The token is returned only once, at creation, and is never retrievable again.
allOf:
- $ref: '#/components/schemas/ApiKey'
properties:
token:
type: string
description: The secret API key. Store it securely — it is shown only once and cannot be retrieved later.
Error:
type: object
additionalProperties: true
properties:
error:
type: string
message:
type: string
ApiKey:
type: object
additionalProperties: true
properties:
id:
type: string
description: OpenMail API key ID
name:
type:
- string
- 'null'
description: Human-readable label for the key, if set.
podId:
type:
- string
- 'null'
description: ID of the pod this key is scoped to, or null for an account-wide key. A pod-scoped key can only access resources in this pod.
inboxId:
type:
- string
- 'null'
description: ID of the inbox this key is confined to, or null. When set, the key can only access this single inbox and its threads, messages, and drafts (its `podId` is the inbox's pod).
tokenPrefix:
type: string
description: Non-secret leading characters of the token, to help you identify it.
last4:
type: string
description: Last 4 characters of the token, shown alongside the prefix.
createdAt:
type: string
format: date-time
lastUsedAt:
type:
- string
- 'null'
format: date-time
description: When the key last authenticated a request, or null if never used.
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: API key