api reference

Emails API

List message traffic, fetch message detail, and download raw MIME or attachment binaries.

These endpoints let you poll an inbox, read parsed message content, and download stored assets for test fixtures or workflow artifacts.

List emails

GET/api/emails

List emails for a single inbox using either the inbox address or address ID.

Auth
Authenticated and organization-scoped. API key requests must include X-Org-Id.
Success
200
  • You must provide either address or addressId.
  • after and before accept either millisecond timestamps or values parseable by Date.parse().
  • search is full-text and does not support after, before, or order=asc.

Request headers

Request headers
HeaderExampleRequirementDetails
Cookie session or X-API-KeyCookie: <better-auth session> or X-API-Key: spin_...RequiredAll documented product endpoints require an authenticated user session or a valid Better Auth API key.
X-Org-Idorg_abc123OptionalRequired for API key requests on org-scoped endpoints. Session-cookie requests can use the active organization on the session instead.

Query parameters

Query parameters
FieldTypeRequirementDetails
addressstringOptional

Normalized inbox email address to query. Required when addressId is omitted.

addressIdstringOptional

Inbox identifier to query. Required when address is omitted.

limitstringOptional

Maximum number of emails to return.

Default: 20

Constraints: Clamped to 1-100.

order"asc" | "desc"Optional

Sort order by receivedAt.

Default: desc

afterstringOptional

Lower time bound for email receivedAt filtering.

beforestringOptional

Upper time bound for email receivedAt filtering.

searchstringOptional

Full-text search over stored email content and indexed metadata for the target inbox.

Constraints: Trimmed length up to 30 characters.

Success response

Success response
FieldTypeDetails
addressstring

Normalized inbox address that matched the request.

addressIdstring

Inbox identifier that matched the request.

itemsArray<object>

Email list for the inbox.

items[].idstring

Email identifier.

items[].addressIdstring

Inbox identifier that received the message.

items[].tostring

Resolved recipient address stored for the email.

items[].fromstring

Raw sender value from the message envelope or headers.

items[].senderstring | null

Stored sender identity value when available, typically including display name and address.

items[].senderLabelstring

Display-friendly sender label derived from sender or from.

items[].subjectstring | null

Parsed subject line when present.

items[].messageIdstring | null

Parsed Message-ID header when available.

items[].rawSizenumber | null

Stored raw MIME size in bytes when tracked.

items[].rawTruncatedboolean

True when the stored raw source exceeded configured limits.

items[].isSampleboolean

True when the email was generated as a starter sample message.

items[].hasHtmlboolean

Whether an HTML body was stored for the email.

items[].hasTextboolean

Whether a text body was stored for the email.

items[].attachmentCountnumber

Number of stored attachments linked to the email.

items[].receivedAtstring | null

When the email was accepted into the inbox.

Constraints: ISO 8601 timestamp when present.

items[].receivedAtMsnumber | null

Millisecond representation of receivedAt.

Constraints: Unix timestamp in milliseconds when present.

Common error responses

Common error responses
StatusErrorWhen it happens
400address or addressId is requiredNeither address nor addressId is provided.
400search does not support after, before, or order=asc parameterssearch is combined with unsupported time filters or ascending order.
404address not foundThe supplied address or addressId does not exist in the current organization.

Example request

BashRequest emails for a specific inbox
curl --get "https://api.spinupmail.com/api/emails" \
  -H "X-API-Key: spin_..." \
  -H "X-Org-Id: org_abc123" \
  --data-urlencode "addressId=addr_123" \
  --data-urlencode "limit=20" \
  --data-urlencode "order=desc"

Example response

JSONEmails that match the requested inbox
{
  "address": "signup-test@spinupmail.dev",
  "addressId": "addr_123",
  "items": [
    {
      "id": "mail_123",
      "addressId": "addr_123",
      "to": "signup-test@spinupmail.dev",
      "from": "notifications@github.com",
      "sender": ""GitHub" <notifications@github.com>",
      "senderLabel": "GitHub",
      "subject": "Verify your email",
      "messageId": "<abc@example.com>",
      "rawSize": 13821,
      "rawTruncated": false,
      "isSample": false,
      "hasHtml": true,
      "hasText": true,
      "attachmentCount": 1,
      "receivedAt": "2026-03-08T09:45:10.000Z",
      "receivedAtMs": 1772963110000
    }
  ]
}

Get email detail

GET/api/emails/:id

Fetch the parsed email body, headers, and attachment metadata for a single stored email.

Auth
Authenticated and organization-scoped. API key requests must include X-Org-Id.
Success
200
  • raw is opt-in. If raw is omitted, the response excludes the raw field even when raw storage exists.
  • rawDownloadPath is present when the service can serve raw MIME from D1 or R2.

Request headers

Request headers
HeaderExampleRequirementDetails
Cookie session or X-API-KeyCookie: <better-auth session> or X-API-Key: spin_...RequiredAll documented product endpoints require an authenticated user session or a valid Better Auth API key.
X-Org-Idorg_abc123OptionalRequired for API key requests on org-scoped endpoints. Session-cookie requests can use the active organization on the session instead.

Path parameters

Path parameters
FieldTypeRequirementDetails
idstringRequired

Email identifier.

Query parameters

Query parameters
FieldTypeRequirementDetails
rawstringOptional

Set to 1 or true to include the stored raw MIME content inline in the JSON response.

Success response

Success response
FieldTypeDetails
idstring

Email identifier.

addressIdstring

Inbox identifier.

addressstring

Inbox email address.

tostring

Resolved recipient address.

fromstring

Raw sender value.

senderstring | null

Stored sender identity value when available.

senderLabelstring

Display-friendly sender label derived from sender data.

subjectstring | null

Parsed subject line.

messageIdstring | null

Parsed Message-ID header.

headersunknown

Parsed header structure. Falls back to an empty array when stored headers cannot be parsed.

htmlstring | null

Stored HTML body, when available.

textstring | null

Stored text body, when available.

rawstring | null

Included only when raw=1 or raw=true is requested and raw content is stored in D1.

rawSizenumber | null

Stored raw MIME size in bytes when tracked.

rawTruncatedboolean

Whether the stored raw payload was truncated.

isSampleboolean

True when the email was generated as a starter sample message.

rawDownloadPathstring

Relative API path for raw MIME download when a raw source is available from D1 or R2.

attachmentsArray<object>

Stored attachment metadata.

attachments[].idstring

Attachment identifier.

attachments[].filenamestring

Original attachment filename after sanitization for downloads.

attachments[].contentTypestring

Detected attachment MIME type.

attachments[].sizenumber

Attachment size in bytes.

attachments[].dispositionstring | null

Content-Disposition header value when available.

attachments[].contentIdstring | null

Content-ID value for inline attachments when available.

attachments[].downloadPathstring

Relative API path for the attachment download endpoint.

attachments[].inlinePathstring

Relative API path that requests inline rendering for safe image attachments.

receivedAtstring | null

When the email was accepted.

Constraints: ISO 8601 timestamp when present.

receivedAtMsnumber | null

Millisecond representation of receivedAt.

Constraints: Unix timestamp in milliseconds when present.

Common error responses

Common error responses
StatusErrorWhen it happens
404email not foundThe requested email does not exist in the current organization.

Example request

BashRequest detailed email content
curl --get "https://api.spinupmail.com/api/emails/mail_123" \
  -H "X-API-Key: spin_..." \
  -H "X-Org-Id: org_abc123" \
  --data-urlencode "raw=1"

Example response

JSONParsed email body, headers, and attachment metadata
{
  "id": "mail_123",
  "addressId": "addr_123",
  "address": "signup-test@spinupmail.dev",
  "to": "signup-test@spinupmail.dev",
  "from": "notifications@github.com",
  "sender": ""GitHub" <notifications@github.com>",
  "senderLabel": "GitHub",
  "subject": "Verify your email",
  "messageId": "<abc@example.com>",
  "headers": [{ "name": "from", "value": "notifications@github.com" }],
  "html": "<p>Verify your email</p>",
  "text": "Verify your email",
  "raw": "From: notifications@github.com\n...",
  "rawSize": 13821,
  "rawTruncated": false,
  "isSample": false,
  "rawDownloadPath": "/api/emails/mail_123/raw",
  "attachments": [
    {
      "id": "att_987",
      "filename": "receipt.pdf",
      "contentType": "application/pdf",
      "size": 48211,
      "disposition": "attachment",
      "contentId": null,
      "downloadPath": "/api/emails/mail_123/attachments/att_987",
      "inlinePath": "/api/emails/mail_123/attachments/att_987?inline=1"
    }
  ],
  "receivedAt": "2026-03-08T09:45:10.000Z",
  "receivedAtMs": 1772963110000
}

Download raw email

GET/api/emails/:id/raw

Download the raw MIME source for an email when raw storage is available in D1 or R2.

Auth
Authenticated and organization-scoped. API key requests must include X-Org-Id.
Success
200
  • The response is a binary/text download, not JSON, on success.
  • raw download availability depends on whether raw MIME was stored in D1 or R2.

Request headers

Request headers
HeaderExampleRequirementDetails
Cookie session or X-API-KeyCookie: <better-auth session> or X-API-Key: spin_...RequiredAll documented product endpoints require an authenticated user session or a valid Better Auth API key.
X-Org-Idorg_abc123OptionalRequired for API key requests on org-scoped endpoints. Session-cookie requests can use the active organization on the session instead.

Path parameters

Path parameters
FieldTypeRequirementDetails
idstringRequired

Email identifier.

Success response

Success response
FieldTypeDetails
Content-Typemessage/rfc822

Raw MIME content type. R2-backed responses may use stored HTTP metadata instead.

Content-Dispositionattachment

Download filename in the form <emailId>.eml.

Cache-Controlstring

private, max-age=0, must-revalidate

Common error responses

Common error responses
StatusErrorWhen it happens
404email not foundThe requested email does not exist in the current organization.
404raw source not availableThe email exists but no raw MIME source is available from D1 or R2.

Example request

BashRequest raw MIME source for an email
curl -L "https://api.spinupmail.com/api/emails/mail_123/raw" \
  -H "X-API-Key: spin_..." \
  -H "X-Org-Id: org_abc123" \
  --output mail_123.eml

Download attachment

GET/api/emails/:id/attachments/:attachmentId

Stream a single attachment binary from R2 for a stored email.

Auth
Authenticated and organization-scoped. API key requests must include X-Org-Id.
Success
200
  • Attachment download requires R2_BUCKET to be configured.
  • Successful responses stream binary content with attachment headers instead of JSON.
  • inline rendering is only allowed for safe inline image content types.

Request headers

Request headers
HeaderExampleRequirementDetails
Cookie session or X-API-KeyCookie: <better-auth session> or X-API-Key: spin_...RequiredAll documented product endpoints require an authenticated user session or a valid Better Auth API key.
X-Org-Idorg_abc123OptionalRequired for API key requests on org-scoped endpoints. Session-cookie requests can use the active organization on the session instead.

Path parameters

Path parameters
FieldTypeRequirementDetails
idstringRequired

Email identifier.

attachmentIdstringRequired

Attachment identifier.

Query parameters

Query parameters
FieldTypeRequirementDetails
inlinestringOptional

Set to 1 or true to request inline rendering for safe image attachments.

Success response

Success response
FieldTypeDetails
Content-Typestring

Attachment MIME type or application/octet-stream fallback.

Content-Dispositionattachment

Sanitized filename for the downloaded attachment.

Content-Lengthstring

Attachment size in bytes.

Cache-Controlstring

private, max-age=0, must-revalidate

Common error responses

Common error responses
StatusErrorWhen it happens
503Attachment storage is not configuredR2_BUCKET is not bound in the Worker environment.
404Attachments are disabledEMAIL_ATTACHMENTS_ENABLED is false for the Worker.
404attachment not foundThe attachment metadata does not exist in the current organization.
415attachment content cannot be rendered inlineinline rendering is requested for a non-inline-safe attachment type.
404attachment content not foundAttachment metadata exists but the R2 object cannot be found.

Example request

BashRequest a binary attachment download
curl -L "https://api.spinupmail.com/api/emails/mail_123/attachments/att_987" \
  -H "X-API-Key: spin_..." \
  -H "X-Org-Id: org_abc123" \
  --output receipt.pdf

Delete email

DELETE/api/emails/:id

Delete a stored email, its attachment metadata, and the related raw/attachment R2 objects when present.

Auth
Authenticated and organization-scoped. API key requests must include X-Org-Id.
Success
200

Request headers

Request headers
HeaderExampleRequirementDetails
Cookie session or X-API-KeyCookie: <better-auth session> or X-API-Key: spin_...RequiredAll documented product endpoints require an authenticated user session or a valid Better Auth API key.
X-Org-Idorg_abc123OptionalRequired for API key requests on org-scoped endpoints. Session-cookie requests can use the active organization on the session instead.

Path parameters

Path parameters
FieldTypeRequirementDetails
idstringRequired

Email identifier to delete.

Success response

Success response
FieldTypeDetails
idstring

Deleted email identifier.

deletedboolean

Always true on success.

Common error responses

Common error responses
StatusErrorWhen it happens
404email not foundThe requested email does not exist in the current organization.
500failed to clean up email filesThe email exists but R2 cleanup fails before deletion completes.

Example request

BashRequest to delete a stored email
curl -X DELETE "https://api.spinupmail.com/api/emails/mail_123" \
  -H "X-API-Key: spin_..." \
  -H "X-Org-Id: org_abc123"

Example response

JSONDeleted email confirmation
{
  "id": "mail_123",
  "deleted": true
}