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/asap-cool:asap-cool-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: ASAP Platform Emails API
description: 'Public HTTP API for ASAP Platform (api.asap.cool).
All `/v1` responses are wrapped in a standard envelope. Success responses are `{ "data": , "meta": { "request_id", "next_cursor"?, "has_more"? } }` — the schema documented for each operation describes the inner `data` value. Errors are `{ "error": { "code", "message", "field"?, "request_id" } }`. Every response also carries an `X-Request-Id` header matching `meta.request_id` / `error.request_id`.'
license:
name: BUSL-1.1
version: 0.0.0
servers:
- url: https://api.asap.cool
description: Production
tags:
- name: Emails
description: 'Outbound email journal: delivery history and the Resend delivery-event webhook.'
paths:
/v1/emails:
get:
tags:
- Emails
summary: Serve one page of the org's outbound email journal, newest first
operationId: listEmails
parameters:
- name: limit
in: query
description: Page size, 1..=100 (defaults to 50).
required: false
schema:
type:
- integer
- 'null'
format: int32
minimum: 0
- name: cursor
in: query
description: Opaque cursor from a previous page's `meta.next_cursor`.
required: false
schema:
type:
- string
- 'null'
- name: q
in: query
description: Free-text search over the subject and the recipient address.
required: false
schema:
type:
- string
- 'null'
- name: status
in: query
description: 'Filter to one lifecycle status (`queued`, `sending`, `sent`,
`delivered`, `bounced`, `complained`, `failed`).'
required: false
schema:
type:
- string
- 'null'
- name: template
in: query
description: Filter to one render template (`quote_sent`, `reminder`, …).
required: false
schema:
type:
- string
- 'null'
- name: contact_id
in: query
description: Filter to emails sent to one contact (UUID).
required: false
schema:
type:
- string
- 'null'
- name: document_id
in: query
description: Filter to emails about one invoice document (UUID).
required: false
schema:
type:
- string
- 'null'
- name: from
in: query
description: Inclusive lower bound on the send date (RFC 3339).
required: false
schema:
type:
- string
- 'null'
- name: to
in: query
description: Exclusive upper bound on the send date (RFC 3339).
required: false
schema:
type:
- string
- 'null'
responses:
'200':
description: Page of journal entries (newest first).
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/EmailMessageView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: Invalid limit, cursor or filter.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
post:
tags:
- Emails
summary: Compose and send an ad-hoc email to one of the org's contacts
operationId: composeEmail
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ComposeRequest'
required: true
responses:
'202':
description: Dispatched; a journal entry was opened for it.
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: No such contact or template in this org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: Invalid subject or body, or the contact has no address.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'500':
description: The render sidecar or the mail transport failed.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
/v1/emails/scheduled:
get:
tags:
- Emails
summary: Serve the org's pending scheduled sends, soonest first
operationId: listScheduledEmails
parameters:
- name: limit
in: query
description: How many upcoming sends to return, 1..=500 (defaults to 100).
required: false
schema:
type:
- integer
- 'null'
format: int64
responses:
'200':
description: Pending scheduled sends, soonest first.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/ScheduledEmailView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: Invalid limit.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
/v1/emails/scheduled/{kind}/{id}:
delete:
tags:
- Emails
summary: Call off one pending scheduled send
operationId: cancelScheduledEmail
parameters:
- name: kind
in: path
description: Source of the schedule, from the listing's `source` field (`invoice_reminder`, `signature_reminder`).
required: true
schema:
type: string
- name: id
in: path
description: Identifier of the scheduled row.
required: true
schema:
type: string
format: uuid
responses:
'204':
description: The send was called off.
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: Nothing pending under that id.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
/v1/emails/templates:
get:
tags:
- Emails
summary: List the org's saved composition templates
operationId: listEmailTemplates
responses:
'200':
description: The org's templates, newest first.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/EmailTemplateView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
post:
tags:
- Emails
summary: Save a new composition template
operationId: createEmailTemplate
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/EmailTemplateRequest'
required: true
responses:
'201':
description: The saved template.
content:
application/json:
schema:
$ref: '#/components/schemas/EmailTemplateView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'409':
description: That name is already taken.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: Invalid name, subject, body or variable.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
/v1/emails/templates/{id}:
delete:
tags:
- Emails
summary: Delete a saved template
operationId: deleteEmailTemplate
parameters:
- name: id
in: path
description: Template id.
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Deleted.
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: No such template in this org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
patch:
tags:
- Emails
summary: Replace a saved template's name, subject and body
operationId: updateEmailTemplate
parameters:
- name: id
in: path
description: Template id.
required: true
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/EmailTemplateRequest'
required: true
responses:
'200':
description: The updated template.
content:
application/json:
schema:
$ref: '#/components/schemas/EmailTemplateView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: No such template in this org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'409':
description: That name is already taken.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: Invalid name, subject, body or variable.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
/v1/emails/webhook/resend:
post:
tags:
- Emails
summary: '`POST /v1/emails/webhook/resend`'
operationId: resendEmailWebhook
requestBody:
description: Raw Resend event payload (Svix-signature-verified before parsing).
content:
application/json: {}
responses:
'200':
description: Event recorded, ignored, or already seen.
'400':
description: Missing or invalid Svix signature.
'503':
description: The webhook is not configured on this instance.
/v1/emails/{id}:
get:
tags:
- Emails
summary: Serve one journal entry together with its delivery timeline
operationId: getEmail
parameters:
- name: id
in: path
description: Journal entry id.
required: true
schema:
type: string
format: uuid
responses:
'200':
description: The entry and its delivery events.
content:
application/json:
schema:
$ref: '#/components/schemas/EmailDetailView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: No such entry in this org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
/v1/emails/{id}/preview:
get:
tags:
- Emails
summary: Serve the stored HTML body as a sandboxed standalone document
operationId: previewEmail
parameters:
- name: id
in: path
description: Journal entry id.
required: true
schema:
type: string
format: uuid
responses:
'200':
description: The rendered HTML body, sandboxed.
content:
text/html: {}
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: No such entry, or its body was purged.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
/v1/emails/{id}/resend:
post:
tags:
- Emails
summary: Dispatch a journaled email again, replaying its stored parts
operationId: resendEmail
parameters:
- name: id
in: path
description: Journal entry to replay.
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Dispatched; a fresh journal entry was opened for it.
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing emails:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: No such entry, or its body was purged.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: The recorded recipient is invalid or suppressed.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'500':
description: The mail transport failed.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- session: []
components:
schemas:
ComposeRequest:
type: object
description: Body of `POST /v1/emails`.
required:
- contact_id
properties:
body_html:
type:
- string
- 'null'
description: Rich-text body. Required unless `template_id` is set.
contact_id:
type: string
format: uuid
description: Contact to write to. Their recorded address is the recipient.
document_id:
type:
- string
- 'null'
format: uuid
description: Invoice document whose sealed PDF should ride along.
subject:
type:
- string
- 'null'
description: Subject line. Required unless `template_id` is set.
template_id:
type:
- string
- 'null'
format: uuid
description: 'Saved template to start from. When set, `subject`/`body_html` are
ignored and the template''s own copy is used.'
EmailDetailView:
allOf:
- $ref: '#/components/schemas/EmailMessageView'
description: The entry itself.
- type: object
required:
- events
properties:
events:
type: array
items:
$ref: '#/components/schemas/EmailEventView'
description: Delivery events, oldest first.
description: A journal entry plus its delivery timeline.
EmailTemplateRequest:
type: object
description: 'Body of `POST` / `PATCH /v1/emails/templates`.
Named `Email…` rather than `TemplateRequest`: the signature module already
exposes a schema under that name, and two components sharing one name
silently overwrite each other in the generated client.'
required:
- name
- subject
- body_html
properties:
body_html:
type: string
description: 'Rich-text body; may carry `{{variable}}` placeholders. Sanitized on
save — what is stored is not necessarily what was sent.'
name:
type: string
description: Name, unique within the org.
subject:
type: string
description: Subject line; may carry `{{variable}}` placeholders.
EmailEventView:
type: object
description: 'One entry on a message''s delivery timeline.
The raw provider payload is not exposed: it is kept for re-interpretation
on our side, and it repeats recipient data the view already carries.'
required:
- id
- kind
- occurred_at
properties:
id:
type: string
format: uuid
description: Event id.
kind:
type: string
description: What happened (`delivered`, `opened`, `bounced`, …).
occurred_at:
type: string
description: When it happened, as reported by the provider, RFC 3339.
EmailMessageView:
type: object
description: 'One journal entry, as served by the list and detail endpoints.
The rendered bodies are deliberately absent: they are large, they hold
recipient PII, and a listing has no use for them. `has_body` tells a client
whether `GET /v1/emails/{id}/preview` will return something.'
required:
- id
- template
- status
- to_email
- subject
- locale
- has_body
- created_at
properties:
booking_id:
type:
- string
- 'null'
format: uuid
description: Linked calendar booking.
contact_id:
type:
- string
- 'null'
format: uuid
description: Linked contact.
created_at:
type: string
description: When the entry was opened (the listing's sort key), RFC 3339.
delivered_at:
type:
- string
- 'null'
description: When the provider confirmed delivery, RFC 3339.
document_id:
type:
- string
- 'null'
format: uuid
description: Linked invoice document.
envelope_id:
type:
- string
- 'null'
format: uuid
description: Linked signature envelope.
failure_reason:
type:
- string
- 'null'
description: Why the dispatch failed, when it did.
has_body:
type: boolean
description: 'Whether the stored bodies are still available for preview (they are
dropped by the retention purge).'
id:
type: string
format: uuid
description: Journal entry id.
locale:
type: string
description: Interface-chrome locale the message was rendered with.
provider_message_id:
type:
- string
- 'null'
description: Provider message id — the support handle for a delivery investigation.
reply_to:
type:
- string
- 'null'
description: '`Reply-To`, when the send overrode it.'
sender_name:
type:
- string
- 'null'
description: '`From` display name, when the send overrode it.'
sent_at:
type:
- string
- 'null'
description: When the provider accepted the message, RFC 3339.
status:
type: string
description: Lifecycle status (`queued`/`sent`/`delivered`/`bounced`/…).
subject:
type: string
description: Rendered subject.
template:
type: string
description: Render-template discriminator (`quote_sent`, `reminder`, …).
to_email:
type: string
description: Recipient address.
ErrorBody:
type: object
description: 'Generic error body returned by API handlers when they fail. `code` is a
stable machine-readable token; `message` is human-friendly and meant for
surfacing to end users.'
required:
- code
- message
properties:
code:
type: string
description: Stable machine token (e.g. `invalid_credentials`).
field:
type:
- string
- 'null'
description: Offending request field for validation errors, when known.
message:
type: string
description: Human-readable message.
ScheduledEmailView:
type: object
description: 'An email that has not been sent yet.
Scheduled sends are **not** journal rows: nothing has been rendered or
dispatched. They are read from the business tables that hold the schedule
(`invoice.reminder`, `signature.envelope`), so this view is a projection
over several sources rather than one table.'
required:
- id
- source
- kind
- scheduled_at
properties:
contact_id:
type:
- string
- 'null'
format: uuid
description: Linked contact.
document_id:
type:
- string
- 'null'
format: uuid
description: Linked invoice document.
envelope_id:
type:
- string
- 'null'
format: uuid
description: Linked signature envelope.
id:
type: string
format: uuid
description: Identifier of the underlying scheduled row, unique within its `source`.
kind:
type: string
description: 'What will be sent (`before_due`, `overdue_7`, `quote_before_expiry`,
`signature_reminder`, …).'
label:
type:
- string
- 'null'
description: Human label of the subject matter (document number, envelope subject).
scheduled_at:
type: string
description: When it is due to go out, RFC 3339.
source:
type: string
description: 'Which schedule this comes from (`invoice_reminder` — one row per
occurrence; `signature_reminder` — the envelope''s next occurrence).
Together with `id`, addresses it for cancellation.'
to_email:
type:
- string
- 'null'
description: Intended recipient, when the source knows it.
EmailTemplateView:
type: object
description: A saved composition template.
required:
- id
- name
- subject
- body_html
- created_at
- updated_at
properties:
body_html:
type: string
description: Sanitized body, with `{{variable}}` placeholders left in place.
created_at:
type: string
description: Creation timestamp, RFC 3339.
id:
type: string
format: uuid
description: Template id.
name:
type: string
description: Name, unique within the org.
subject:
type: string
description: Subject line, with `{{variable}}` placeholders left in place.
updated_at:
type: string
description: Last update, RFC 3339.
securitySchemes:
api_key:
type: http
scheme: bearer
session:
type: apiKey
in: cookie
name: asap_session