Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/openmail-sh:openmail-sh-policy-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: OpenMail Policy 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: Policy
description: Correspondent policy — provider-enforced allow/block rules and allowlist mode, scoped per account, pod, or inbox. Account-wide key only.
paths:
/v1/policy:
get:
operationId: getPolicy
summary: Get correspondent policy
tags:
- Policy
description: Read the correspondent policy for a scope (account by default, or a pod/inbox). Returns the mode this scope sets for each direction, the effective mode after inheritance, this scope's own rules, and the rules inherited from parent scopes. Inbox-scoped keys are rejected. A pod-scoped key may read its own pod or an inbox in that pod, never account-wide policy. Account-wide keys may read any scope.
parameters:
- schema:
type: string
in: query
name: podId
required: false
description: Confine the operation to one pod's policy. Accepts the pod ID. Mutually exclusive with `inboxId`.
- schema:
type: string
in: query
name: inboxId
required: false
description: Confine the operation to one inbox's policy. Mutually exclusive with `podId`.
responses:
'200':
description: The resolved policy for the scope
content:
application/json:
schema:
description: The resolved policy for the scope
type: object
additionalProperties: true
'403':
description: The authenticating key is scoped and cannot read policy (`forbidden`)
content:
application/json:
schema:
description: The authenticating key is scoped and cannot read policy (`forbidden`)
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Pod or inbox not found
content:
application/json:
schema:
description: Pod or inbox not found
allOf:
- $ref: '#/components/schemas/Error'
put:
operationId: replacePolicy
summary: Replace correspondent policy
tags:
- Policy
description: Declaratively set a scope's entire policy in one call — ideal for automated provisioning. Sets the inbound and/or outbound mode and REPLACES the scope's own rules for any direction you include. Rules created here are fail-closed (an empty allowlist denies all). Omitted directions are left untouched. Inbox-scoped keys are rejected. A pod-scoped key may mutate its own pod or an inbox in that pod, never account-wide policy. Pod keys cannot set `none` or extra allows on a parent allowlist.
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
inbound:
type: object
additionalProperties: false
description: Inbound (who may send to this scope) policy to set. Omit to leave inbound untouched.
properties:
mode:
type: string
enum:
- none
- allowlist
- inherit
description: '`none` = no filtering; `allowlist` = only listed correspondents are permitted (empty allowlist denies all — fail closed); `inherit` = defer to the parent scope (pod, then account). Not valid at the account scope.'
rules:
type: array
maxItems: 500
description: Replaces this scope's own inbound rules. Omit to leave rules untouched; pass [] to clear them.
items:
type: object
additionalProperties: false
required:
- type
- value
properties:
type:
type: string
enum:
- allow
- block
value:
type: string
minLength: 3
maxLength: 255
description: An email address (`user@example.com`), a whole domain (`example.com`), or a domain and all its subdomains (`*.example.com`, which also covers `example.com` itself).
outbound:
type: object
additionalProperties: false
description: Outbound (who this scope may send to) policy to set. Omit to leave outbound untouched.
properties:
mode:
type: string
enum:
- none
- allowlist
- inherit
description: '`none` = no filtering; `allowlist` = only listed correspondents are permitted (empty allowlist denies all — fail closed); `inherit` = defer to the parent scope (pod, then account). Not valid at the account scope.'
rules:
type: array
maxItems: 500
description: Replaces this scope's own outbound rules. Omit to leave rules untouched; pass [] to clear them.
items:
type: object
additionalProperties: false
required:
- type
- value
properties:
type:
type: string
enum:
- allow
- block
value:
type: string
minLength: 3
maxLength: 255
parameters:
- schema:
type: string
in: query
name: podId
required: false
description: Confine the operation to one pod's policy. Accepts the pod ID. Mutually exclusive with `inboxId`.
- schema:
type: string
in: query
name: inboxId
required: false
description: Confine the operation to one inbox's policy. Mutually exclusive with `podId`.
responses:
'200':
description: The resulting policy for the scope
content:
application/json:
schema:
description: The resulting policy for the scope
type: object
additionalProperties: true
'403':
description: The authenticating key is scoped and cannot manage policy
content:
application/json:
schema:
description: The authenticating key is scoped and cannot manage policy
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Pod or inbox not found
content:
application/json:
schema:
description: Pod or inbox not found
allOf:
- $ref: '#/components/schemas/Error'
'422':
description: Invalid mode for the scope, or an invalid rule value
content:
application/json:
schema:
description: Invalid mode for the scope, or an invalid rule value
allOf:
- $ref: '#/components/schemas/Error'
/v1/policy/audit:
get:
operationId: getPolicyAudit
summary: List correspondent policy audit events
tags:
- Policy
description: 'Read the append-only audit trail for correspondent policy, newest first. Two kinds of event share one stream: `rule_added`, `rule_removed`, `mode_changed`, and `scope_deleted` record who moved the boundary and how (`scope_deleted` covers a pod or inbox being deleted, which cascade-deletes its policy — the row carries the modes and rules that were removed, so lifting a restriction by deleting its scope is not a silent operation). `send_rejected` and `inbound_rejected` record what the boundary refused: a send the outbound policy would not make, and inbound mail it would not accept. Both are deduped to one row per inbox + correspondent per hour, so neither a looping agent nor an outside sender can flood the trail. `inbound_rejected_no_inbox` records mail a verified custom domain accepted for an address with no inbox: it is dropped after SMTP, so the sender gets no bounce and this row is the only trace the domain''s owner can reach. It is deduped per address per hour and capped per organisation per hour. Rows are never updated or deleted. Inbox-scoped keys are rejected. A pod-scoped key may read the trail for its own pod or an inbox in that pod (`?podId=` / `?inboxId=`), never the unfiltered account-wide trail.'
parameters:
- schema:
type: string
in: query
name: podId
required: false
description: Confine the operation to one pod's policy. Accepts the pod ID. Mutually exclusive with `inboxId`.
- schema:
type: string
in: query
name: inboxId
required: false
description: Confine the operation to one inbox's policy. Mutually exclusive with `podId`.
- schema:
type: string
in: query
name: action
required: false
description: 'Comma-separated actions to include: `rule_added`, `rule_removed`, `mode_changed`, `scope_deleted`, `send_rejected`, `inbound_rejected`, `inbound_rejected_no_inbox`. Omit for all.'
- schema:
type: string
enum:
- inbound
- outbound
in: query
name: direction
required: false
description: '`inbound` governs who may send to the inbox; `outbound` governs who the inbox may send to (enforced across To, Cc, Bcc, and Reply-To on every send path).'
- schema:
type: string
in: query
name: since
required: false
description: ISO-8601 timestamp. Only events at or after this time (inclusive).
- schema:
type: string
in: query
name: until
required: false
description: ISO-8601 timestamp. Only events strictly before this time.
- schema:
type: string
in: query
name: limit
required: false
description: Page size, 1–100. Defaults to 50.
- schema:
type: string
in: query
name: offset
required: false
description: Rows to skip. Defaults to 0.
responses:
'200':
description: 'A page of audit events plus the unpaginated `total`. Each event carries its scope (with the pod name / inbox address resolved at read time, or null if since deleted), the acting console user where there was one, and an action-specific `detail` object: `type`/`valueType`/`value` for rule events, `from`/`to` for mode changes, and `rejectedRecipient`/`reason`/`matchedScope` for rejected sends.'
content:
application/json:
schema:
description: 'A page of audit events plus the unpaginated `total`. Each event carries its scope (with the pod name / inbox address resolved at read time, or null if since deleted), the acting console user where there was one, and an action-specific `detail` object: `type`/`valueType`/`value` for rule events, `from`/`to` for mode changes, and `rejectedRecipient`/`reason`/`matchedScope` for rejected sends.'
type: object
additionalProperties: true
'400':
description: An unknown `action`, or a `since`/`until` that is not a valid timestamp
content:
application/json:
schema:
description: An unknown `action`, or a `since`/`until` that is not a valid timestamp
allOf:
- $ref: '#/components/schemas/Error'
'403':
description: The authenticating key is scoped and cannot read the audit trail (`forbidden`)
content:
application/json:
schema:
description: The authenticating key is scoped and cannot read the audit trail (`forbidden`)
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Pod or inbox not found
content:
application/json:
schema:
description: Pod or inbox not found
allOf:
- $ref: '#/components/schemas/Error'
/v1/policy/mode:
put:
operationId: setPolicyMode
summary: Set correspondent policy mode
tags:
- Policy
description: Set the filtering mode for one direction of a scope's policy, without touching rules. Inbox-scoped keys are rejected. A pod-scoped key may mutate its own pod or an inbox in that pod, never account-wide policy. Pod keys cannot set `none`.
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- mode
properties:
mode:
type: string
enum:
- none
- allowlist
- inherit
description: '`none` = no filtering; `allowlist` = only listed correspondents are permitted (empty allowlist denies all — fail closed); `inherit` = defer to the parent scope (pod, then account). Not valid at the account scope.'
direction:
type: string
enum:
- inbound
- outbound
description: '`inbound` governs who may send to the inbox; `outbound` governs who the inbox may send to (enforced across To, Cc, Bcc, and Reply-To on every send path).'
parameters:
- schema:
type: string
in: query
name: podId
required: false
description: Confine the operation to one pod's policy. Accepts the pod ID. Mutually exclusive with `inboxId`.
- schema:
type: string
in: query
name: inboxId
required: false
description: Confine the operation to one inbox's policy. Mutually exclusive with `podId`.
responses:
'200':
description: The updated mode
content:
application/json:
schema:
description: The updated mode
type: object
additionalProperties: true
'403':
description: The authenticating key is scoped and cannot manage policy
content:
application/json:
schema:
description: The authenticating key is scoped and cannot manage policy
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Pod or inbox not found
content:
application/json:
schema:
description: Pod or inbox not found
allOf:
- $ref: '#/components/schemas/Error'
'422':
description: Invalid mode for the scope
content:
application/json:
schema:
description: Invalid mode for the scope
allOf:
- $ref: '#/components/schemas/Error'
/v1/policy/rules:
post:
operationId: addPolicyRule
summary: Add correspondent policy rule
tags:
- Policy
description: Add one allow/block rule for a direction of a scope's policy. Inbox-scoped keys are rejected. A pod-scoped key may mutate its own pod or an inbox in that pod, never account-wide policy. Pod keys cannot add allows on a parent allowlist (blocks are fine).
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- type
- value
properties:
type:
type: string
enum:
- allow
- block
value:
type: string
minLength: 3
maxLength: 255
description: An email address (`user@example.com`), a whole domain (`example.com`), or a domain and all its subdomains (`*.example.com`, which also covers `example.com` itself).
direction:
type: string
enum:
- inbound
- outbound
description: '`inbound` governs who may send to the inbox; `outbound` governs who the inbox may send to (enforced across To, Cc, Bcc, and Reply-To on every send path).'
parameters:
- schema:
type: string
in: query
name: podId
required: false
description: Confine the operation to one pod's policy. Accepts the pod ID. Mutually exclusive with `inboxId`.
- schema:
type: string
in: query
name: inboxId
required: false
description: Confine the operation to one inbox's policy. Mutually exclusive with `podId`.
responses:
'201':
description: Rule created
content:
application/json:
schema:
description: Rule created
type: object
additionalProperties: true
'403':
description: The authenticating key is scoped and cannot manage policy
content:
application/json:
schema:
description: The authenticating key is scoped and cannot manage policy
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Pod or inbox not found
content:
application/json:
schema:
description: Pod or inbox not found
allOf:
- $ref: '#/components/schemas/Error'
'409':
description: An identical rule already exists (`rule_exists`)
content:
application/json:
schema:
description: An identical rule already exists (`rule_exists`)
allOf:
- $ref: '#/components/schemas/Error'
'422':
description: The value is not a valid email or domain
content:
application/json:
schema:
description: The value is not a valid email or domain
allOf:
- $ref: '#/components/schemas/Error'
/v1/policy/rules/{id}:
delete:
operationId: deletePolicyRule
summary: Delete correspondent policy rule
tags:
- Policy
description: Remove a single policy rule by its ID. Inbox-scoped keys are rejected. A pod-scoped key may delete a rule on its own pod or an inbox in that pod, never an account-wide rule.
parameters:
- schema:
type: string
in: path
name: id
required: true
description: The rule ID to delete
responses:
'204':
description: Rule deleted
'403':
description: The authenticating key is scoped and cannot manage policy
content:
application/json:
schema:
description: The authenticating key is scoped and cannot manage policy
allOf:
- $ref: '#/components/schemas/Error'
'404':
description: Rule not found
content:
application/json:
schema:
description: Rule not found
allOf:
- $ref: '#/components/schemas/Error'
components:
schemas:
Error:
type: object
additionalProperties: true
properties:
error:
type: string
message:
type: string
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: API key