Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Mailcheer Com Workspace API
version: 1.0.0
contact:
name: Mailcheer
url: https://mailcheer.com/docs/api
email: contact@mailcheer.com
license:
name: Mailcheer Terms of Sale
url: https://mailcheer.com/terms
description: 'Operations tagged Workspace across 2 of this provider''s published API definitions: openapi.json, mailcheer-com-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://mailcheer.com
description: 'Production. There is no separate test environment: try it on a workspace of your own, with an address of your own. Every path below already includes the `/api/v1` prefix.'
security:
- bearerAuth: []
- apiKeyHeader: []
tags:
- name: Workspace
description: Who the key belongs to.
paths:
/api/v1:
get:
operationId: getApiMap
tags:
- Workspace
summary: The API map
description: 'No key required: lists the endpoints, the permissions and the address of the documentation.'
security: []
responses:
'200':
description: The map.
content:
application/json:
schema:
$ref: '#/components/schemas/Carte'
servers:
- url: https://mailcheer.com
description: 'Production. There is no separate test environment: try it on a workspace of your own, with an address of your own. Every path below already includes the `/api/v1` prefix.'
/api/v1/tracking-domain:
get:
operationId: getTrackingDomain
tags:
- Workspace
summary: The workspace's tracking domain
description: The domain that carries the links and pixel of the workspace's emails (`click.your-domain.com`), its status and the DNS records to add. `hostname` is `null` until one is declared. No particular permission is required.
responses:
'200':
description: The tracking domain.
content:
application/json:
schema:
type: object
properties:
object:
type: string
const: tracking_domain
hostname:
type:
- string
- 'null'
status:
type:
- string
- 'null'
description: pending_dns, verifying, issuing_certificate, active or failed.
active:
type: boolean
reason:
type:
- string
- 'null'
detail:
type:
- string
- 'null'
dns_records:
type: array
items:
type: object
properties:
type:
type: string
name:
type: string
value:
type: string
required:
type: boolean
links_origin:
type:
- string
- 'null'
description: The address that links and the pixel of new emails carry today.
created_at:
type:
- string
- 'null'
format: date-time
activated_at:
type:
- string
- 'null'
format: date-time
last_checked_at:
type:
- string
- 'null'
format: date-time
post:
operationId: createTrackingDomain
tags:
- Workspace
summary: Declare the tracking domain
description: '`{ "hostname": "click.your-domain.com" }`, or `{}` for the name suggested from a verified sending domain. Then add the CNAME to `clients.clickmailcheer.com` (DNS only): the domain becomes active as soon as a real HTTPS request comes back through it. Requires `emails:send`.'
requestBody:
required: false
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
hostname:
type: string
maxLength: 253
responses:
'201':
description: Declared.
content:
application/json:
schema:
type: object
properties:
object:
type: string
const: tracking_domain
hostname:
type:
- string
- 'null'
status:
type:
- string
- 'null'
description: pending_dns, verifying, issuing_certificate, active or failed.
active:
type: boolean
reason:
type:
- string
- 'null'
detail:
type:
- string
- 'null'
dns_records:
type: array
items:
type: object
properties:
type:
type: string
name:
type: string
value:
type: string
required:
type: boolean
links_origin:
type:
- string
- 'null'
description: The address that links and the pixel of new emails carry today.
created_at:
type:
- string
- 'null'
format: date-time
activated_at:
type:
- string
- 'null'
format: date-time
last_checked_at:
type:
- string
- 'null'
format: date-time
'409':
description: The workspace already has a tracking domain, or the name is taken.
'422':
description: Name refused.
servers:
- url: https://mailcheer.com
description: 'Production. There is no separate test environment: try it on a workspace of your own, with an address of your own. Every path below already includes the `/api/v1` prefix.'
/api/v1/me:
get:
operationId: getAccount
tags:
- Workspace
summary: Who this key belongs to
description: 'Workspace, the key''s permissions, plan, this month''s usage (sent, queued, remaining, reset date), billing status and any scheduled plan change, member and domain limits, the daily limit of a new workspace, sending domains and senders. Call this first: it is what tells you which address to write from — and, before a send, whether it fits. No particular permission is required.'
responses:
'200':
description: The state of the workspace.
content:
application/json:
schema:
$ref: '#/components/schemas/Account'
headers:
Mailcheer-Mode:
$ref: '#/components/headers/Mailcheer-Mode'
Mailcheer-Quota-Limit:
$ref: '#/components/headers/Mailcheer-Quota-Limit'
Mailcheer-Quota-Used:
$ref: '#/components/headers/Mailcheer-Quota-Used'
Mailcheer-Quota-Remaining:
$ref: '#/components/headers/Mailcheer-Quota-Remaining'
Mailcheer-Quota-Reset:
$ref: '#/components/headers/Mailcheer-Quota-Reset'
Mailcheer-Key-Quota-Limit:
$ref: '#/components/headers/Mailcheer-Key-Quota-Limit'
Mailcheer-Key-Quota-Used:
$ref: '#/components/headers/Mailcheer-Key-Quota-Used'
Mailcheer-Key-Quota-Remaining:
$ref: '#/components/headers/Mailcheer-Key-Quota-Remaining'
'401':
$ref: '#/components/responses/NonAuthentifie'
'429':
$ref: '#/components/responses/TropDAppels'
servers:
- url: https://mailcheer.com
description: 'Production. There is no separate test environment: try it on a workspace of your own, with an address of your own. Every path below already includes the `/api/v1` prefix.'
components:
headers:
Mailcheer-Key-Quota-Limit:
description: 'Only for a key with a monthly limit: the limit set on THIS key (Settings → API). Absent otherwise.'
schema:
type: string
examples:
- '2400'
Mailcheer-Quota-Remaining:
description: What can still be sent this month, queue already deducted — never negative. `unlimited` on an unlimited plan.
schema:
type: string
examples:
- '565'
- unlimited
Mailcheer-Quota-Used:
description: Emails sent this month **plus** those waiting in the queue (campaigns being sent, API sends in progress). The same count as `usage.emails_sent + usage.emails_in_flight` in `GET /api/v1/me`.
schema:
type: string
examples:
- '2435'
Mailcheer-Key-Quota-Used:
description: 'Only for a key with a monthly limit: what this key sent this month (its emails and the campaigns it launched), plus what is still queued.'
schema:
type: string
examples:
- '1830'
Mailcheer-Mode:
description: '`live`, or `test` when the call was made with a test key (`mch_test_…`): nothing is sent and the quota is not touched.'
schema:
type: string
enum:
- live
- test
Mailcheer-Key-Quota-Remaining:
description: 'Only for a key with a monthly limit: what this key can still send this month — never negative. It resets with the workspace quota (`Mailcheer-Quota-Reset`).'
schema:
type: string
examples:
- '570'
Retry-After:
description: Seconds to wait before trying again. Present on EVERY `429` and every `423`.
schema:
type: integer
minimum: 1
Mailcheer-Quota-Reset:
description: 'When the counter resets, in ISO 8601: the 1st of next month, 00:00 UTC.'
schema:
type: string
format: date-time
examples:
- '2026-10-01T00:00:00.000Z'
Mailcheer-Quota-Limit:
description: Emails a month included in the workspace's plan, or `unlimited`.
schema:
type: string
examples:
- '3000'
- unlimited
responses:
NonAuthentifie:
description: Key missing, unknown or revoked.
content:
application/json:
schema:
$ref: '#/components/schemas/Erreur'
TropDAppels:
description: 'More than 600 requests per minute for this key (`rate_limit_exceeded` — a batch of N subscribers counts as N), or a new workspace reached its daily limit (`daily_quota_exceeded`: 1,000 emails per rolling 24 hours until it is verified). `Retry-After` always says how many seconds to wait.'
headers:
Retry-After:
$ref: '#/components/headers/Retry-After'
X-RateLimit-Limit:
schema:
type: integer
X-RateLimit-Remaining:
schema:
type: integer
X-RateLimit-Reset:
schema:
type: integer
Mailcheer-Mode:
$ref: '#/components/headers/Mailcheer-Mode'
Mailcheer-Quota-Limit:
$ref: '#/components/headers/Mailcheer-Quota-Limit'
Mailcheer-Quota-Used:
$ref: '#/components/headers/Mailcheer-Quota-Used'
Mailcheer-Quota-Remaining:
$ref: '#/components/headers/Mailcheer-Quota-Remaining'
Mailcheer-Quota-Reset:
$ref: '#/components/headers/Mailcheer-Quota-Reset'
content:
application/json:
schema:
$ref: '#/components/schemas/Erreur'
schemas:
Carte:
type: object
description: The API's table of contents, readable without a key.
properties:
name:
type: string
examples:
- Mailcheer API
version:
type: string
examples:
- '1'
documentation:
type: string
format: uri
openapi:
type: string
format: uri
description: This document.
mcp:
type: string
format: uri
description: The MCP server's address.
authentication:
type: object
properties:
type:
type: string
header:
type: string
where:
type: string
scopes:
type: array
items:
type: string
enum:
- emails:send
- subscribers:read
- subscribers:write
- campaigns:read
- campaigns:write
description: Every permission a key can carry.
rate_limit:
type: string
examples:
- 600 requests per minute per key
endpoints:
type: array
description: Each endpoint and the permission it requires.
items:
type: object
properties:
method:
type: string
path:
type: string
scope:
type: string
description: '`—` if no particular permission is required.'
Erreur:
type: object
properties:
error:
type: object
properties:
code:
type: string
enum:
- missing_api_key
- invalid_api_key
- revoked_api_key
- insufficient_scope
- rate_limit_exceeded
- validation_error
- unverified_from_domain
- suppressed_recipient
- undeliverable_recipient
- quota_exceeded
- free_plan_domain_used
- key_quota_exceeded
- reputation_blocked
- sending_blocked
- sending_paused
- daily_quota_exceeded
- commitment_required
- not_found
- conflict
- idempotency_key_reused
- idempotency_key_in_use
- send_failed
- internal_error
description: Write your code against this field, never against `message`.
message:
type: string
description: Written to be read by a human; may be rephrased without notice.
details:
type: object
description: 'What you need to fix things without guessing: `issues` (the offending field and why) on a validation error, `verifiedDomains` on a refused domain, `available` on an unknown sender, and on `quota_exceeded` the numbers `plan`, `quota`, `sent`, `in_flight`, `remaining`, `requested`, `resets_at`, and on `free_plan_domain_used` the `domain`, its `root_domain`, the `period` and `resets_at`, and on `key_quota_exceeded` the key''s `key_id`, `key_name`, `limit`, `used`, `remaining`, `requested` and `resets_at`. A `429` and a `423` also give `retry_after_seconds` when the refusal comes from a daily limit or a safety review — the same value as `Retry-After`.'
additionalProperties: true
statusCode:
type: integer
examples:
- 422
message:
type: string
description: The same text as `error.message` — written for a human.
name:
type: string
enum:
- missing_api_key
- invalid_api_key
- revoked_api_key
- insufficient_scope
- rate_limit_exceeded
- validation_error
- unverified_from_domain
- suppressed_recipient
- undeliverable_recipient
- quota_exceeded
- free_plan_domain_used
- key_quota_exceeded
- reputation_blocked
- sending_blocked
- sending_paused
- daily_quota_exceeded
- commitment_required
- not_found
- conflict
- idempotency_key_reused
- idempotency_key_in_use
- send_failed
- internal_error
description: The same value as `error.code`. Write your logic against it.
description: Two readings of the same content. `error` is Mailcheer's shape, structured. `statusCode`, `message` and `name` follow Resend's shape, so that code written against that API shows a correct message without being rewritten. `name` carries the same value as `error.code`, and `message` the same text as `error.message`.
examples:
- error:
code: unverified_from_domain
message: 'Domain “example.com” is not verified in this workspace. Verified domains: yourdomain.com.'
details:
from: hello@example.com
verifiedDomains:
- yourdomain.com
statusCode: 422
message: 'Domain “example.com” is not verified in this workspace. Verified domains: yourdomain.com.'
name: unverified_from_domain
Account:
type: object
description: 'What the key gives access to, and what is left to use. The first call to make: it gives the verified domains and the registered senders — that is, the only addresses your sends will pass with — and everything a send can be refused for: the monthly quota (queue included), the daily limit of a new workspace, the billing status.'
properties:
object:
type: string
const: account
organization:
type: object
description: The workspace the key belongs to. `null` if the workspace has been deleted.
properties:
id:
type: string
name:
type: string
slug:
type: string
key:
type: object
description: The key used for this call. Its secret is never returned.
properties:
id:
type: string
description: The key's identifier (not its secret) — the `key_id` of a `key_quota_exceeded`.
name:
type: string
description: The name you gave it.
scopes:
type: array
items:
type: string
enum:
- emails:send
- subscribers:read
- subscribers:write
- campaigns:read
- campaigns:write
- webhooks:read
- webhooks:write
description: The permissions of THIS key. A call outside this list returns 403.
mode:
type: string
enum:
- live
- test
description: '`live`, or `test` for a test key (`mch_test_…`): its sends are checked and simulated, nothing goes out.'
language:
type: string
enum:
- en
- fr
description: The language of this key's messages when a call asks for none (`Accept-Language` absent, or not English or French). Set under Settings → API; `en` by default.
monthly_limit:
type:
- object
- 'null'
description: 'The key''s own monthly limit and what it used this month (its emails and the campaigns it launched, copies included, queue included). `null` when the key has none — only the workspace quota counts then. Beyond it: `402 key_quota_exceeded`.'
properties:
limit:
type: integer
used:
type: integer
remaining:
type: integer
resets_at:
type: string
format: date-time
plan:
type: object
properties:
id:
type: string
name:
type: string
emails_per_month:
type:
- integer
- 'null'
description: '`null` = unlimited.'
usage:
type: object
properties:
period:
type: string
description: The current month, `YYYY-MM`.
examples:
- 2026-09
emails_sent:
type: integer
description: This month's sends accepted by our provider — campaigns, automations, tests and API together.
emails_in_flight:
type: integer
description: 'Promised but not yet sent: campaign messages waiting in the queue or being sent, reserved automation sends. Already deducted from `emails_remaining`.'
emails_remaining:
type:
- integer
- 'null'
description: 'What can still be sent this month: quota − `emails_sent` − `emails_in_flight`, never negative. `null` = unlimited. A send asking for more than this returns `402 quota_exceeded`.'
resets_at:
type: string
format: date-time
description: 'When the monthly counter resets: the 1st of next month at 00:00 UTC (ISO 8601).'
examples:
- '2026-10-01T00:00:00.000Z'
billing:
type: object
description: 'The subscription as our payment provider reports it. It explains a `plan` that is not the one being paid for: when a payment fails for good, the workspace runs on the free plan''s limits while `subscribed_plan` still names the plan that was bought.'
properties:
status:
type: string
enum:
- none
- active
- trialing
- past_due
- unpaid
- canceled
- incomplete
- incomplete_expired
- paused
description: '`none` = never subscribed (free plan, nothing to pay). Otherwise the provider''s status: `active`, `trialing`, `past_due` (a payment failed, access kept while it retries), `unpaid` (retries abandoned: free plan limits apply), `canceled`, `incomplete`, `incomplete_expired`, `paused`.'
subscribed_plan:
type:
- string
- 'null'
enum:
- starter
- pro
- agency
- null
description: The plan being billed, while a subscription is alive; `null` otherwise. It can differ from `plan.id` (see `status`).
current_period_end:
type:
- string
- 'null'
format: date-time
description: End of the period already paid for; `null` without a live subscription.
cancel_at_period_end:
type: boolean
description: '`true` when the subscription has been cancelled and stops at the end of the period.'
trial_ends_at:
type:
- string
- 'null'
format: date-time
description: 'End of the free week — offered once per workspace, on its first move to a paid plan — when `status` is `trialing`: the plan already applies and the first charge falls on this date (ISO 8601). `null` otherwise.'
scheduled_change:
type:
- object
- 'null'
description: 'A change that will take effect later — a downgrade, or a cancellation (`plan: "free"`); `null` if none.'
properties:
plan:
type: string
enum:
- free
- starter
- pro
- agency
description: The plan that will apply.
effective_at:
type: string
format: date-time
description: When it takes effect (ISO 8601).
manage_url:
type: string
format: uri
description: The billing screen where the owner or an administrator changes plan, card or invoices. In the language of the call (`Accept-Language`).
limits:
type: object
description: The other limits of the plan, and how much of each is used.
properties:
members:
type: object
description: Seats in the workspace. A pending, unexpired invitation takes a seat.
properties:
used:
type: integer
description: Current members.
pending_invitations:
type: integer
description: Invitations sent and still valid.
max:
type:
- integer
- 'null'
description: The plan's maximum; `null` = unlimited.
sending_domains:
type: object
description: Sending domains, verified or not.
properties:
used:
type: integer
description: Domains added to the workspace.
max:
type:
- integer
- 'null'
description: The plan's maximum; `null` = unlimited.
daily:
type:
- object
- 'null'
description: 'The daily limit of a new workspace, over a rolling 24 hours: 1,000 emails until the workspace is verified (automatically, at its first send), then none. `null` when it does not apply. A send above it returns `429 daily_quota_exceeded`.'
properties:
limit:
type: integer
description: Emails allowed per rolling 24 hours.
used:
type: integer
description: Accepted over the last 24 hours, plus what is waiting in the queue.
remaining:
type: integer
description: What can still go out now; never negative.
next_limit:
type:
- integer
- 'null'
description: The next limit (`500`), or `null` when the next step lifts it.
changes_at:
type:
- string
- 'null'
format: date-time
description: When the limit changes (ISO 8601).
subscribers:
type: integer
description: Subscribers with status `subscribed` — the ones a campaign would reach.
sending_domains:
type: array
description: 'The workspace''s domains. Only those with `verified: true` can serve as `from`.'
items:
type: object
properties:
domain:
type: string
examples:
- yourdomain.com
verified:
type: boolean
senders:
type: array
description: The registered senders. A CAMPAIGN can only go out from one of them; an individual email, on the other hand, accepts any address on a verified domain.
items:
type: object
properties:
id:
type: string
description: To pass as `sender_id` when creating a campaign.
from:
type: string
format: email
name:
type:
- string
- 'null'
description: The name shown in the inbox.
default:
type: boolean
description: The one a campaign takes if you designate none.
examples:
- object: account
organization:
id: org_3f9
name: Your brand
slug: your-brand
key:
id: cmu8k1a2b00001n7nkey0prod
name: Production
scopes:
- emails:send
- subscribers:read
mode: live
language: en
monthly_limit:
limit: 2400
used: 1830
remaining: 570
resets_at: '2026-10-01T00:00:00.000Z'
plan:
id: pro
name: Pro
emails_per_month: 150000
usage:
period: 2026-09
emails_sent: 1240
emails_in_flight: 60
emails_remaining: 148700
resets_at: '2026-10-01T00:00:00.000Z'
billing:
status: active
subscribed_plan: pro
current_period_end: '2026-10-18T09:12:40.000Z'
cancel_at_period_end: false
trial_ends_at: null
scheduled_change: null
manage_url: https://mailcheer.com/reglages/facturation
limits:
members:
used: 3
pending_invitations: 1
max: 25
sending_domains:
used: 1
max: 25
daily: null
subscribers: 3182
sending_domains:
- domain: yourdomain.com
verified: true
senders:
- id: snd_71a
from: hello@yourdomain.com
name: Your brand
default: true
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: 'An API key for the workspace, created under Settings → API in your Mailcheer workspace. Shape: `mch_live_…` — or `mch_test_…` for a test key, which checks everything and sends nothing (see Test mode).
`Authorization: Bearer mch_live_…`
The key carries permissions (`scopes`): every operation states which one it requires, and `GET /api/v1/me` states the ones yours carries. A key belongs to ONE workspace — there is no cross-workspace call.'
apiKeyHeader:
type: apiKey
in: header
name: X-Api-Key
description: 'The same key, in a dedicated header. Strictly equivalent to the Bearer form: some enterprise clients and gateways do not let `Authorization` through. Do not send both.'
externalDocs:
description: The written documentation, with per-language examples.
url: https://mailcheer.com/docs/api
x-refined-from:
- openapi.json
- mailcheer-com-openapi.json