mails-ai Public API
Unauthenticated endpoints (health, unsubscribe link targets).
Unauthenticated endpoints (health, unsubscribe link targets).
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
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.curl "https://apis.io/api/v1/apis/mails-ai:mails-ai-public-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
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: Mails.ai Public API
version: 0.2.0
description: 'The Mails.ai API gives AI agents a real email identity: send and receive
transactional email. Mail received within your plan''s limits is scanned for prompt injection and
reaches you as a typed event. With classification turned on (a paid-plan feature), new mail can also
be read for intent; a reply in a thread never is.
## Authentication
All endpoints take a Bearer API key:
```
Authorization: Bearer mk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
Keys carry one or more scopes — `send`, `read`, `draft` (writes drafts, but can neither send nor
schedule one) and `manage` — and a mode: **live** (`mk_live_…`) or **test** (`mk_test_…`).
## Test mode
A `mk_test_` key exercises the entire API — real validation, persisted resources, real
`message.sent`/`*.received` events and webhooks — without sending real email or incurring cost. Build and
test your whole integration on a test key, then flip one character to `mk_live_` to go live.
`POST /v1/test/inbound` (test key only) lets you simulate inbound mail end-to-end.
## Idempotency
Send endpoints accept an `Idempotency-Key` header; a repeated key replays the stored response instead of
sending twice, with an `Idempotent-Replay: true` header.
## Pagination
List endpoints are cursor-paginated: pass `limit` (1–100) and the `next_cursor` from the previous page.
## Errors
Errors use a stable envelope: `{ "error": { "type", "code", "message", "param", "request_id" } }`. Every
response carries an `X-Request-Id` header for support correlation.'
contact:
name: Mails.ai Support
url: https://mails.ai
email: support@mails.ai
license:
name: Proprietary
identifier: LicenseRef-Proprietary
servers:
- url: https://api.mails.ai
description: Production
security:
- bearerAuth: []
tags:
- name: Public
description: Unauthenticated endpoints (health, unsubscribe link targets).
paths:
/v1/unsubscribe:
get:
tags:
- Public
summary: Unsubscribe landing page
operationId: unsubscribe
description: Public List-Unsubscribe link target (human click). Authorized by the signed `t` token, not an API key. Always returns an HTML confirmation page (200) regardless of token validity.
parameters:
- name: t
in: query
required: false
schema:
type: string
description: Signed unsubscribe token embedded in the email.
responses:
'200':
description: An HTML confirmation page.
content:
text/html:
schema:
type: string
security: []
post:
tags:
- Public
summary: One-click unsubscribe (RFC 8058)
operationId: unsubscribeOneClick
description: RFC 8058 one-click unsubscribe POST from a mail client. Authorized by the signed `t` query token. Returns an empty 200.
parameters:
- name: t
in: query
required: false
schema:
type: string
description: Signed unsubscribe token.
responses:
'200':
description: Processed (empty body).
security: []
/api/health:
get:
tags:
- Public
summary: Health check
operationId: getHealth
description: Liveness probe. Without authentication it returns `status` (`healthy` when the database answers and accepts writes, else `degraded`) and `timestamp`. The dependency detail (database, sender, classifier) is returned only to internal callers.
responses:
'200':
description: Service health.
content:
application/json:
schema:
$ref: '#/components/schemas/Health'
security: []
components:
schemas:
Health:
type: object
properties:
status:
type: string
enum:
- healthy
- degraded
description: '`healthy` when the database answers and accepts writes, `degraded` otherwise. The HTTP status is 200 either way.'
version:
type: string
description: The API's version string. Like `db`, `ses`, `classifier` and `schemas`, it is returned to internal callers only.
db:
type: object
properties:
status:
type: string
enum:
- ok
- error
description: '`ok`, or `error` when the database did not answer or is read-only.'
error:
type: string
description: What went wrong, when `status` is `error`.
required:
- status
description: The database check.
ses:
type: object
properties:
mocked:
type: boolean
description: True when the SES adapter is mocked or has no credentials, so it sends no real mail.
region:
type: string
description: The AWS region the SES adapter sends from.
required:
- mocked
- region
description: The Amazon SES adapter, which matters only when SES is the mail provider in use.
classifier:
type: object
properties:
mocked:
type: boolean
description: True when the classifier returns fixed test verdicts instead of calling its model.
model:
type: string
description: The model the classifier calls when it is not mocked.
required:
- mocked
- model
description: The inbound classifier.
schemas:
type: integer
description: How many definitions the database schema exports.
timestamp:
type: string
format: date-time
description: When the check ran (UTC).
required:
- status
- timestamp
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: mk_live_<32 hex>, mk_test_<32 hex>, or moa_<48 hex>
description: 'A Mails.ai API key, or an OAuth access token (`moa_…`, valid for 1 hour) from signing in through an app such as the CLI, Claude or ChatGPT. OAuth discovery: https://api.mails.ai/.well-known/oauth-authorization-server and https://api.mails.ai/.well-known/oauth-protected-resource. An access token''s OAuth scope maps onto these API scopes: `full_access` = `send` + `read` + `manage` (not `draft`: the draft routes take those three too), `send` = `send` + `read`, `read` = `read`. Scopes (`send`/`read`/`manage`/`draft`) are noted per operation via `x-required-scope`; when more than one scope opens an operation (the draft routes also take `draft`), `x-accepted-scopes` lists them all. `inbox` appears there too, on the triage routes (changing and trashing threads, labels, cancelling a scheduled send): only a signed-in dashboard session holds it (a workspace Member''s), never an API key or OAuth token, and `x-session-scopes` names it.'