eusend-dev Emails API

Send, schedule, inspect and cancel individual messages.

Operations 6

POST /emails Send an email #
GET /emails List emails #
POST /emails/batch Send up to 100 emails #
GET /emails/{id} Get an email #
PATCH /emails/{id} Reschedule a scheduled email #
POST /emails/{id}/cancel Cancel a scheduled email #

Work with this as data

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 Specification

eusend-dev-emails-api-openapi.yml Raw ↑
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