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/eusend-dev:eusend-dev-emails-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: eusend Emails API
version: 1.0.0
summary: EU-native transactional and marketing email API.
description: 'eusend sends transactional and marketing email from infrastructure that stays inside the European Union — processing, storage and delivery alike.
**When to use this API.** Reach for eusend to send application email from server-side code: password resets, receipts, verification codes, notifications, and opt-in marketing broadcasts to a list you own. It is a good fit when GDPR or EU data residency is a requirement, when you are migrating off Resend, SendGrid, Mailgun, Postmark or SES, or when you need SMTP relay rather than an HTTP call. It is not a fit for inbox hosting, for reading a user’s mailbox, or for sending to purchased or scraped lists.
**Getting started.** Create an account, verify a sending domain by publishing the DNS records the domain endpoints hand back, then `POST /emails`. A key prefixed `eu_test_` exercises the whole pipeline without delivering anything.
**Authentication.** Every authenticated endpoint takes `Authorization: Bearer `. Keys are `eu_live_…` or `eu_test_…`, and carry either `full_access` or the send-only `sending_access` permission.
**Errors.** Non-2xx responses are always `{ "error": string, "code": string }`. Branch on `code`; the list is enumerated on the `Error` schema.
**Conventions.** Request bodies use snake_case and reject unknown properties. Response bodies use camelCase, except the pagination cursor and a handful of endpoints noted inline. List endpoints are cursor-paginated, newest first. Every response carries `X-Request-Id`.'
termsOfService: https://eusend.dev/legal/terms
contact:
name: eusend support
email: support@eusend.dev
url: https://eusend.dev/support
license:
name: Proprietary
url: https://eusend.dev/legal/terms
servers:
- url: https://api.eusend.dev
description: Production
security:
- bearerAuth: []
tags:
- name: Emails
description: Send, schedule, inspect and cancel individual messages.
paths:
/emails:
post:
operationId: sendEmail
summary: Send an email
description: Queues one message for delivery and returns its id immediately. The sending domain must be verified. Pass `scheduled_at` to send later. Set an `Idempotency-Key` header to make a retried request return the original email instead of sending twice.
tags:
- Emails
parameters:
- name: Idempotency-Key
in: header
required: false
description: Client-chosen key, up to 255 characters. A repeat with the same key returns the original result.
schema:
type: string
maxLength: 255
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SendEmailRequest'
responses:
'200':
description: Queued.
content:
application/json:
schema:
$ref: '#/components/schemas/SendEmailResponse'
'400':
description: The request body or query failed validation (`VALIDATION_ERROR`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing, malformed, or revoked API key (`UNAUTHORIZED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: 'Refused before queueing: unverified sending domain (`DOMAIN_NOT_VERIFIED`), every recipient suppressed (`ALL_SUPPRESSED`), no deliverable recipient domain (`RECIPIENT_DOMAIN_UNDELIVERABLE`), sending suspended or on hold (`SENDING_SUSPENDED`, `ACCOUNT_RESTRICTED`, `SERVICE_PAUSED`), an additional workspace with no live subscription (`WORKSPACE_INACTIVE`), a display name claiming a brand the domain has no relationship to (`SENDER_NOT_PERMITTED`), or a list-shaped send held for review (`LIST_SEND_HELD`).'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited, or a sending ceiling reached (`RATE_LIMITED`, `DAILY_LIMIT_EXCEEDED`, `MONTHLY_LIMIT_EXCEEDED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected server error (`INTERNAL_ERROR`). Carries `request_id`.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
get:
operationId: listEmails
summary: List emails
description: Newest first, cursor-paginated. Filters combine with AND. Use `next_cursor` from the response as the next `cursor`.
tags:
- Emails
parameters:
- name: limit
in: query
description: Items per page.
schema:
type: integer
minimum: 1
maximum: 100
default: 10
- name: cursor
in: query
description: The `next_cursor` from the previous page.
schema:
type: string
format: uuid
- name: status
in: query
schema:
type: string
enum:
- queued
- scheduled
- canceled
- sending
- sent
- delivered
- bounced
- complained
- suppressed
- failed
- name: from
in: query
description: Exact sender address match.
schema:
type: string
- name: to
in: query
description: Case-insensitive match against any recipient.
schema:
type: string
- name: tag
in: query
description: Repeatable. `category:password_reset` matches that exact pair; a bare `category` matches any email carrying the tag. Several are ANDed.
explode: true
schema:
type: array
items:
type: string
responses:
'200':
description: A page of emails.
content:
application/json:
schema:
$ref: '#/components/schemas/ListEmailsResponse'
'400':
description: The request body or query failed validation (`VALIDATION_ERROR`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing, malformed, or revoked API key (`UNAUTHORIZED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The key exists but may not reach this resource — a `sending_access` key outside the send paths, a test-mode key writing live state, or an account on hold (`FORBIDDEN`, `ACCOUNT_RESTRICTED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded (`RATE_LIMITED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected server error (`INTERNAL_ERROR`). Carries `request_id`.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/emails/batch:
post:
operationId: sendEmailBatch
summary: Send up to 100 emails
description: The body is a top-level array of email objects. Each item is accepted or refused independently — a failed item never fails the batch, and the response maps positionally to the request. Attachments and `scheduled_at` are not supported here; send those individually.
tags:
- Emails
requestBody:
required: true
content:
application/json:
schema:
type: array
minItems: 1
maxItems: 100
items:
$ref: '#/components/schemas/SendEmailRequest'
responses:
'200':
description: Per-item outcomes.
content:
application/json:
schema:
$ref: '#/components/schemas/BatchSendResponse'
'400':
description: The request body or query failed validation (`VALIDATION_ERROR`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing, malformed, or revoked API key (`UNAUTHORIZED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The key exists but may not reach this resource — a `sending_access` key outside the send paths, a test-mode key writing live state, or an account on hold (`FORBIDDEN`, `ACCOUNT_RESTRICTED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded (`RATE_LIMITED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected server error (`INTERNAL_ERROR`). Carries `request_id`.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/emails/{id}:
get:
operationId: getEmail
summary: Get an email
description: The message with its full delivery event history, oldest event first.
tags:
- Emails
parameters:
- name: id
in: path
required: true
description: The email id.
schema:
type: string
format: uuid
responses:
'200':
description: The email.
content:
application/json:
schema:
$ref: '#/components/schemas/Email'
'401':
description: Missing, malformed, or revoked API key (`UNAUTHORIZED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The key exists but may not reach this resource — a `sending_access` key outside the send paths, a test-mode key writing live state, or an account on hold (`FORBIDDEN`, `ACCOUNT_RESTRICTED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: No such resource on this organization (`NOT_FOUND`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded (`RATE_LIMITED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected server error (`INTERNAL_ERROR`). Carries `request_id`.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
operationId: rescheduleEmail
summary: Reschedule a scheduled email
description: Only an email still in `scheduled` status can be moved. Once sending has started this returns 409. Moving it onto another day takes that day's sending allowance, and returns 429 `DAILY_LIMIT_EXCEEDED` (leaving the email where it was) when the new day is full.
tags:
- Emails
parameters:
- name: id
in: path
required: true
description: The email id.
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateEmailRequest'
responses:
'200':
description: Rescheduled.
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateEmailResponse'
'400':
description: The request body or query failed validation (`VALIDATION_ERROR`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing, malformed, or revoked API key (`UNAUTHORIZED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The key exists but may not reach this resource — a `sending_access` key outside the send paths, a test-mode key writing live state, or an account on hold (`FORBIDDEN`, `ACCOUNT_RESTRICTED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: No such resource on this organization (`NOT_FOUND`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The email is no longer reschedulable (`CONFLICT`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded (`RATE_LIMITED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected server error (`INTERNAL_ERROR`). Carries `request_id`.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/emails/{id}/cancel:
post:
operationId: cancelEmail
summary: Cancel a scheduled email
description: Only an email still in `scheduled` status can be cancelled. Once sending has started this returns 409.
tags:
- Emails
parameters:
- name: id
in: path
required: true
description: The email id.
schema:
type: string
format: uuid
responses:
'200':
description: Cancelled.
content:
application/json:
schema:
$ref: '#/components/schemas/CancelEmailResponse'
'401':
description: Missing, malformed, or revoked API key (`UNAUTHORIZED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The key exists but may not reach this resource — a `sending_access` key outside the send paths, a test-mode key writing live state, or an account on hold (`FORBIDDEN`, `ACCOUNT_RESTRICTED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: No such resource on this organization (`NOT_FOUND`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The email is no longer cancellable (`CONFLICT`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded (`RATE_LIMITED`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected server error (`INTERNAL_ERROR`). Carries `request_id`.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
EmailEvent:
type: object
required:
- id
- type
- metadata
- createdAt
properties:
id:
type: string
format: uuid
type:
type: string
enum:
- sent
- delivered
- opened
- clicked
- bounced
- complained
metadata:
type: object
additionalProperties: true
createdAt:
type: string
format: date-time
UpdateEmailResponse:
type: object
required:
- id
- status
- scheduled_at
properties:
id:
type: string
format: uuid
status:
type: string
enum:
- scheduled
scheduled_at:
type: string
format: date-time
EmailListItem:
type: object
required:
- id
- from
- to
- subject
- status
- tags
- testMode
- createdAt
properties:
id:
type: string
format: uuid
from:
type: string
to:
type: array
items:
type: string
subject:
type: string
status:
type: string
enum:
- queued
- scheduled
- canceled
- sending
- sent
- delivered
- bounced
- complained
- suppressed
- failed
tags:
type: object
additionalProperties:
type: string
testMode:
type: boolean
createdAt:
type: string
format: date-time
UpdateEmailRequest:
type: object
required:
- scheduled_at
additionalProperties: false
properties:
scheduled_at:
type: string
maxLength: 100
description: The new send time. Same parsing as `scheduled_at` on send.
BatchItemResult:
description: 'Per-item outcome, positionally mapped to the request array. Branch on the presence of `id`: a failed item never fails the whole batch.'
oneOf:
- type: object
required:
- id
properties:
id:
type: string
format: uuid
- type: object
required:
- error
- code
properties:
error:
type: string
code:
type: string
enum:
- UNAUTHORIZED
- FORBIDDEN
- NOT_FOUND
- VALIDATION_ERROR
- RATE_LIMITED
- MONTHLY_LIMIT_EXCEEDED
- DAILY_LIMIT_EXCEEDED
- PLAN_LIMIT_EXCEEDED
- ALL_SUPPRESSED
- RECIPIENT_DOMAIN_UNDELIVERABLE
- DOMAIN_NOT_VERIFIED
- SENDING_SUSPENDED
- ACCOUNT_RESTRICTED
- WORKSPACE_INACTIVE
- SENDER_NOT_PERMITTED
- SERVICE_PAUSED
- LIST_SEND_HELD
- BROADCAST_HELD
- ATTACHMENT_STORAGE_ERROR
- INTERNAL_ERROR
- CONFLICT
- BAD_REQUEST
- PAYLOAD_TOO_LARGE
Error:
type: object
description: Every non-2xx response from the API has this shape. `code` is stable and safe to branch on; `error` is a human sentence that may change.
required:
- error
- code
properties:
error:
type: string
description: Human-readable explanation of the failure.
code:
type: string
enum:
- UNAUTHORIZED
- FORBIDDEN
- NOT_FOUND
- VALIDATION_ERROR
- RATE_LIMITED
- MONTHLY_LIMIT_EXCEEDED
- DAILY_LIMIT_EXCEEDED
- PLAN_LIMIT_EXCEEDED
- ALL_SUPPRESSED
- RECIPIENT_DOMAIN_UNDELIVERABLE
- DOMAIN_NOT_VERIFIED
- SENDING_SUSPENDED
- ACCOUNT_RESTRICTED
- WORKSPACE_INACTIVE
- SENDER_NOT_PERMITTED
- SERVICE_PAUSED
- LIST_SEND_HELD
- BROADCAST_HELD
- ATTACHMENT_STORAGE_ERROR
- INTERNAL_ERROR
- CONFLICT
- BAD_REQUEST
- PAYLOAD_TOO_LARGE
description: Stable machine-readable error code.
request_id:
type: string
description: Correlation id, returned on 500s and echoed in the `X-Request-Id` header on every response. Quote it in support requests.
ListEmailsResponse:
type: object
required:
- data
- next_cursor
properties:
data:
type: array
items:
$ref: '#/components/schemas/EmailListItem'
next_cursor:
type:
- string
- 'null'
format: uuid
description: Pass as `cursor` to fetch the next page. Null on the last page.
SendEmailResponse:
type: object
required:
- id
properties:
id:
type: string
format: uuid
description: The queued email id.
CancelEmailResponse:
type: object
required:
- id
- status
properties:
id:
type: string
format: uuid
status:
type: string
enum:
- canceled
SendEmailRequest:
type: object
description: A single message. At least one of `html`, `text` or `template_id` is required. Unknown properties are rejected.
required:
- from
- to
additionalProperties: false
properties:
from:
type: string
description: Sender address, bare (`hello@acme.com`) or with a display name (`Acme <hello@acme.com>`). The domain must be verified on your account.
to:
$ref: '#/components/schemas/EmailAddresses'
cc:
$ref: '#/components/schemas/EmailAddresses'
bcc:
$ref: '#/components/schemas/EmailAddresses'
reply_to:
$ref: '#/components/schemas/EmailAddresses'
subject:
type: string
minLength: 1
description: Line breaks are rejected.
html:
type: string
text:
type: string
template_id:
type: string
format: uuid
description: Render a stored template instead of inline `html`/`text`.
variables:
type: object
additionalProperties: true
description: Values substituted into the template or into `{{placeholders}}` in the body.
headers:
type: object
additionalProperties:
type: string
description: Extra MIME headers. Line breaks in names or values are rejected.
tags:
$ref: '#/components/schemas/Tags'
track_opens:
type: boolean
description: Overrides the organization default.
track_clicks:
type: boolean
description: Overrides the organization default.
attachments:
type: array
maxItems: 20
items:
$ref: '#/components/schemas/Attachment'
scheduled_at:
type: string
maxLength: 100
description: Send in the future, at most 30 days out. An ISO 8601 timestamp or natural language (`in 1 hour`, `tomorrow at 9am`). Relative phrasings resolve against the server clock in UTC.
Email:
type: object
description: A single message with its full delivery event history.
required:
- id
- from
- to
- subject
- status
- tags
- testMode
- createdAt
- events
properties:
id:
type: string
format: uuid
from:
type: string
to:
type: array
items:
type: string
cc:
type: array
items:
type: string
bcc:
type: array
items:
type: string
replyTo:
type: array
items:
type: string
subject:
type: string
html:
type:
- string
- 'null'
text:
type:
- string
- 'null'
status:
type: string
enum:
- queued
- scheduled
- canceled
- sending
- sent
- delivered
- bounced
- complained
- suppressed
- failed
tags:
type: object
additionalProperties:
type: string
testMode:
type: boolean
description: True when sent with an `eu_test_` key; no mail left the system.
templateId:
type:
- string
- 'null'
format: uuid
scheduledAt:
type:
- string
- 'null'
format: date-time
createdAt:
type: string
format: date-time
events:
type: array
items:
$ref: '#/components/schemas/EmailEvent'
EmailAddresses:
description: A single address, or a list of them. Accepts `Name <user@example.com>` form.
oneOf:
- type: string
format: email
- type: array
items:
type: string
format: email
BatchSendResponse:
type: object
required:
- data
properties:
data:
type: array
items:
$ref: '#/components/schemas/BatchItemResult'
Tags:
description: Labels for log filtering and webhook routing. Accepts a flat object or Resend’s `[{ name, value }]` array; responses always use the object form. Up to 10 tags; names and values are ASCII letters, digits, underscores and dashes.
oneOf:
- type: object
additionalProperties:
type: string
- type: array
maxItems: 10
items:
type: object
required:
- name
- value
properties:
name:
type: string
value:
type: string
Attachment:
type: object
description: One file on a message. Supply exactly one of `content` (inline base64) or `path` (a URL fetched at send time). Up to 20 attachments, 10 MB combined.
required:
- filename
properties:
filename:
type: string
maxLength: 256
description: Name the recipient sees.
content:
type: string
format: byte
description: Base64-encoded file bytes.
path:
type: string
format: uri
maxLength: 2048
description: Public URL the server fetches at send time.
content_type:
type: string
maxLength: 255
description: MIME type; inferred from the filename when omitted.
content_id:
type: string
maxLength: 128
description: Content-ID for an inline attachment, referenced from HTML as `cid:<content_id>`.
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: 'An eusend API key, sent as `Authorization: Bearer eu_live_…`. Create one in the dashboard under API keys.'
externalDocs:
description: eusend documentation
url: https://eusend.dev/docs