EmailRequest
The body of `POST /api/v1/emails`. `from`, `to` and `subject` are required, and **at least one of `html` or `text`** — an empty body is refused with a 422. Attachments go in `attachments`, in Resend's format. Unknown keys are silently ignored: a body written for Resend passes through as is.
Properties
| Name | Type | Description |
|---|---|---|
| from | string | **Required.** An address on a domain verified in the workspace — otherwise 422 `unverified_from_domain`, which hands you the list of domains you can use. `GET /api/v1/me` gives it too, before you try. |
| to | stringarray | **Required.** One recipient, or an array of 1 to 50 recipients. At most 50 addresses in all, `to`, `cc` and `bcc` together — our sending provider's limit per message; beyond, `422 validation_error`. B |
| subject | string | **Required.** The message's subject. The 998-character ceiling is the email standard's; in practice an inbox shows 40 to 60. |
| html | string | The body in HTML. `html` or `text`: at least one of the two, both if you can — a message with no text version is marked down by filters. |
| text | string | The body in plain text, for clients that do not display HTML. |
| cc | stringarray | Visible copy. One address or an array of 1 to 50. Recipients in copy see and are seen. They count against the quota and go through the same checks as `to` — suppression list included. |
| bcc | stringarray | Blind copy. One address or an array of 1 to 50. It appears in no header of the received message, including when the send carries attachments — it stays in the envelope. Same quota and same checks as ` |
| replyTo | stringarray | The address recipients will reply to, when it differs from `from`. One, or an array of 1 to 10. Same form as `to`: the bare address or “Name ”. |
| reply_to | stringarray | Alias of `replyTo`, for clients coming from Resend. The address recipients will reply to, when it differs from `from`. One, or an array of 1 to 10. Same form as `to`: the bare address or “Name |
| headers | object | Free-form headers, as name → value pairs. The ones that carry the message's identity (From, To, Reply-To, List-Unsubscribe…) are ignored: they are ours to answer for. |
| tags | objectarray | Free-form tags for your own tracking; they come back in delivery notifications and on `GET /api/v1/emails/{id}`. Two ways to write them: an object of key → value, or an array of `{name, value}` as wit |
| unsubscribe_url | string | The one-click unsubscribe address. Mailcheer then sets `List-Unsubscribe` AND `List-Unsubscribe-Post` — the two always go together, and without the second Gmail shows no button. Gmail and Yahoo have e |
| attachments | array | Attachments, in Resend's format: `filename` + `content` in base64. Twenty at most. **The limit is Amazon SES's: 40 MB per message once encoded**, which is roughly 30 MB of actual files (base64 adds a |
| track_opens | boolean | Insert an open-tracking pixel (HTML body only). Omitted, your workspace's “Track opens” setting decides (the Workspace screen of the app); sent, it overrides that setting for this email. In France, th |
| track_clicks | boolean | Track clicks: the http(s) links of the tags of the HTML go through your tracking domain. Left untouched: mailto:, tel:, anchors, unsubscribe_url and links carrying data-no-track. Without this fiel |
| verify | boolean | Verify recipients before sending (same checks as `POST /api/v1/verify`). An `invalid` recipient refuses the entire call with `422 undeliverable_recipient`; `risky` and `unknown` addresses go out. Defa |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/mailcheer-com/json-schema/mailcheer-com-email-request-schema.json",
"title": "EmailRequest",
"description": "The body of `POST /api/v1/emails`.\n\n`from`, `to` and `subject` are required, and **at least one of `html` or `text`** — an empty body is refused with a 422.\n\nAttachments go in `attachments`, in Resend's format.\n\nUnknown keys are silently ignored: a body written for Resend passes through as is.",
"x-generated": "2026-10-31",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/mailcheer-com-openapi.json#/components/schemas/EmailRequest",
"type": "object",
"required": [
"from",
"to",
"subject"
],
"properties": {
"from": {
"type": "string",
"minLength": 3,
"maxLength": 320,
"description": "**Required.** An address on a domain verified in the workspace — otherwise 422 `unverified_from_domain`, which hands you the list of domains you can use. `GET /api/v1/me` gives it too, before you try. Both forms are accepted: the bare address, or “Name <address@domain.com>” so the name shows in the inbox."
},
"to": {
"type": [
"string",
"array"
],
"description": "**Required.** One recipient, or an array of 1 to 50 recipients. At most 50 addresses in all, `to`, `cc` and `bcc` together — our sending provider's limit per message; beyond, `422 validation_error`. Beyond 50, split into several calls — or go through a campaign. Each entry accepts the form “Name <address@domain.com>” as well as the bare address, and is 3 to 320 characters long.\n\n⚠️ **Recipients see one another**: they go out in the same message, not as blind copies. For each to receive their own, make one call per person.",
"oneOf": [
{
"title": "A single recipient",
"type": "string",
"minLength": 3,
"maxLength": 320
},
{
"title": "Several recipients",
"type": "array",
"items": {
"type": "string",
"minLength": 3,
"maxLength": 320
},
"minItems": 1,
"maxItems": 50
}
]
},
"subject": {
"type": "string",
"minLength": 1,
"maxLength": 998,
"description": "**Required.** The message's subject. The 998-character ceiling is the email standard's; in practice an inbox shows 40 to 60."
},
"html": {
"type": "string",
"maxLength": 400000,
"description": "The body in HTML. `html` or `text`: at least one of the two, both if you can — a message with no text version is marked down by filters."
},
"text": {
"type": "string",
"maxLength": 400000,
"description": "The body in plain text, for clients that do not display HTML."
},
"cc": {
"type": [
"string",
"array"
],
"oneOf": [
{
"title": "One address",
"type": "string",
"minLength": 3,
"maxLength": 320
},
{
"title": "Several addresses",
"type": "array",
"items": {
"type": "string",
"minLength": 3,
"maxLength": 320
},
"minItems": 1,
"maxItems": 50
}
],
"description": "Visible copy. One address or an array of 1 to 50. Recipients in copy see and are seen. They count against the quota and go through the same checks as `to` — suppression list included."
},
"bcc": {
"type": [
"string",
"array"
],
"oneOf": [
{
"title": "One address",
"type": "string",
"minLength": 3,
"maxLength": 320
},
{
"title": "Several addresses",
"type": "array",
"items": {
"type": "string",
"minLength": 3,
"maxLength": 320
},
"minItems": 1,
"maxItems": 50
}
],
"description": "Blind copy. One address or an array of 1 to 50. It appears in no header of the received message, including when the send carries attachments — it stays in the envelope. Same quota and same checks as `to`."
},
"replyTo": {
"type": [
"string",
"array"
],
"description": "The address recipients will reply to, when it differs from `from`. One, or an array of 1 to 10. Same form as `to`: the bare address or “Name <address>”.",
"oneOf": [
{
"title": "One address",
"type": "string",
"minLength": 3,
"maxLength": 320
},
{
"title": "Several addresses",
"type": "array",
"items": {
"type": "string",
"minLength": 3,
"maxLength": 320
},
"minItems": 1,
"maxItems": 10
}
]
},
"reply_to": {
"type": [
"string",
"array"
],
"description": "Alias of `replyTo`, for clients coming from Resend. The address recipients will reply to, when it differs from `from`. One, or an array of 1 to 10. Same form as `to`: the bare address or “Name <address>”.\n\nFill in only one of the two.",
"oneOf": [
{
"title": "One address",
"type": "string",
"minLength": 3,
"maxLength": 320
},
{
"title": "Several addresses",
"type": "array",
"items": {
"type": "string",
"minLength": 3,
"maxLength": 320
},
"minItems": 1,
"maxItems": 10
}
]
},
"headers": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Free-form headers, as name → value pairs. The ones that carry the message's identity (From, To, Reply-To, List-Unsubscribe…) are ignored: they are ours to answer for."
},
"tags": {
"type": [
"object",
"array"
],
"description": "Free-form tags for your own tracking; they come back in delivery notifications and on `GET /api/v1/emails/{id}`. Two ways to write them: an object of key → value, or an array of `{name, value}` as with Resend (10 entries at most in that second form).\n\nNames and values are **rewritten, not refused**: any character outside `A-Z a-z 0-9 _ -` becomes `_`, and beyond 256 characters the value is cut. An accent or a space therefore passes without error, but not unchanged.",
"oneOf": [
{
"title": "Key/value object",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
{
"title": "Array of {name, value} (Resend form)",
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"value"
],
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"maxItems": 10
}
]
},
"unsubscribe_url": {
"type": "string",
"format": "uri",
"maxLength": 2048,
"description": "The one-click unsubscribe address. Mailcheer then sets `List-Unsubscribe` AND `List-Unsubscribe-Post` — the two always go together, and without the second Gmail shows no button. Gmail and Yahoo have expected this header since February 2024 on any send to people who did not write to you first; without it, the only way out you offer is the Spam button, and it is your sending domain's reputation that pays. Must be https. The header itself is still rejected inside `headers`: Mailcheer writes it, you only provide the target. It also says what kind of send this is: with it, a newsletter or prospecting, refused to an address that unsubscribed; without it, an individual email, which an unsubscribe does not stop."
},
"attachments": {
"type": "array",
"items": {
"type": "object",
"required": [
"filename",
"content"
],
"properties": {
"filename": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "The file name as it will appear in the inbox. Line breaks and path separators are stripped from it."
},
"content": {
"type": "string",
"description": "The file, encoded in **base64**. That is the only accepted form."
},
"content_type": {
"type": "string",
"maxLength": 127,
"description": "The MIME type. Optional: inferred from the extension when missing (`.pdf` → `application/pdf`), falling back to `application/octet-stream`."
},
"contentType": {
"type": "string",
"maxLength": 127,
"description": "Alias of `content_type`."
},
"content_id": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Makes the attachment an **inline image**: reference it in the HTML with `cid:` (`<img src=\"cid:logo\">`). It goes out with a `Content-ID` header in a `multipart/related` part and shows in place instead of as a download. Letters, digits, `.`, `_`, `-`, `@`, no spaces; unique within the message."
},
"contentId": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Alias of `content_id`."
}
}
},
"maxItems": 20,
"description": "Attachments, in Resend's format: `filename` + `content` in base64. Twenty at most.\n\n**The limit is Amazon SES's: 40 MB per message once encoded**, which is roughly 30 MB of actual files (base64 adds a third). Beyond that the call is refused with a 422 naming the file, its size and the size reached — no message goes out without its attachment.\n\nRejected, and always out loud: extensions inbox providers reject (`.exe`, `.bat`, `.js`, `.vbs`…), a `content` that is not valid base64, and Resend's `path` field — our server will not fetch a file from an address you choose; encode it.\n\nWithout an attachment, nothing changes in the way the message goes out."
},
"track_opens": {
"type": "boolean",
"description": "Insert an open-tracking pixel (HTML body only). Omitted, your workspace's “Track opens” setting decides (the Workspace screen of the app); sent, it overrides that setting for this email. In France, the CNIL's recommendation of 14 April 2026 makes measuring opens with a pixel, to track campaign performance, subject to the recipient's prior consent."
},
"track_clicks": {
"type": "boolean",
"description": "Track clicks: the http(s) links of the <a> tags of the HTML go through your tracking domain. Left untouched: mailto:, tel:, anchors, unsubscribe_url and links carrying data-no-track. Without this field, the workspace's “Track clicks” setting decides — on by default, for every email, individual ones included. `false` leaves a message untouched. Login, verification and reset links (recognized by their address or a token) always stay untouched."
},
"verify": {
"type": "boolean",
"description": "Verify recipients before sending (same checks as `POST /api/v1/verify`). An `invalid` recipient refuses the entire call with `422 undeliverable_recipient`; `risky` and `unknown` addresses go out. Default false."
}
}
}
Work with this as data
Every JSON Schema 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 schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.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.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/json-schemas/mailcheer-com-email-request"
curl "https://apis.io/api/v1/json-schemas?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.