---
title: "Get a single email"
method: GET
path: "/api/emails/{id}"
tags: ["Emails"]
---

# Get a single email

`GET /api/emails/{id}`

## Request

- Base URL: `https://api.sendly.now`
- URL: `https://api.sendly.now/api/emails/{id}`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `better-auth.session_token`
  - OAuth 2 (authorization code, authorization URL `https://app.sendly.now/api/auth/oauth2/authorize`, token URL `https://app.sendly.now/api/auth/oauth2/token`, scopes: `emails:read`)

Fetch one email together with its DELIVERY history — the transitions behind `status`, oldest first.

`events` here is not the custom-event resource: the events a caller records with `POST /api/v1/events` are read from `GET /api/v1/events`, and never appear on this response.

Requires the `emails:read` scope — View the emails you have sent and their delivery status.

## Path parameters

- `id` string, uuid, required

## Response `200`

Email and its delivery history

- EmailDetailResponse: One email and its delivery history.
  - `data` EmailWithEvents, required: A transactional email together with its delivery history.
    - `bouncedAt` string, date-time, nullable, required: Bounced, or null.
    - `clickedAt` string, date-time, nullable, required: First click, or null.
    - `clicks` integer, required: Total clicks recorded.
    - `complainedAt` string, date-time, nullable, required: Spam complaint, or null.
    - `createdAt` string, date-time, required: ISO 8601 datetime string
    - `deliveredAt` string, date-time, nullable, required: Accepted by the recipient's server, or null.
    - `error` string, nullable: Why the email did not go out, as a sentence for its sender. Set only when `status` is FAILED, CANCELLED, REJECTED, RENDERING_FAILURE or BOUNCED; null otherwise, including while a send is waiting on a retry.
    - `failureKind` 'provider_paused' | 'platform_paused' | 'not_dispatched' | 'unconfirmed' | 'rate_limited' | 'content_scan_unavailable' | 'send_failed' | 'refused' | 'null', nullable: Stable class of `error`, for code that branches on it. `refused` means Sendly declined the send and `error` says why (a limit, a disabled project, a consent rule). Null when `error` is null.
    - `from` string, required
    - `id` string, uuid, required
    - `openedAt` string, date-time, nullable, required: First open, or null.
    - `opens` integer, required: Total opens recorded.
    - `projectId` string, uuid, required
    - `sentAt` string, date-time, nullable, required: Handed to the provider, or null.
    - `status` 'PENDING' | 'SENDING' | 'SENT' | 'DELIVERED' | 'RECEIVED' | 'BOUNCED' | 'FAILED' | 'REJECTED' | 'RENDERING_FAILURE' | 'DELIVERY_DELAY' | 'CANCELLED', required: Delivery lifecycle of the message. Engagement is reported separately.
    - `subject` string, required
    - `tags` string[], required
    - `to` string, required
    - `updatedAt` string, date-time, required: ISO 8601 datetime string
    - `events` EmailEvent[], required: Delivery transitions for this message, oldest first. NOT the custom events recorded with `POST /api/v1/events` — those are a separate resource.
      - `id` string, uuid, required
      - `status` 'PENDING' | 'SENDING' | 'SENT' | 'DELIVERED' | 'RECEIVED' | 'BOUNCED' | 'FAILED' | 'REJECTED' | 'RENDERING_FAILURE' | 'DELIVERY_DELAY' | 'CANCELLED', required: Delivery lifecycle of the message. Engagement is reported separately.
      - `timestamp` string, date-time, required: ISO 8601 datetime string
  - `success` true, required

## Other responses

- `400`: Validation error
- `401`: Unauthorized — missing or invalid auth
- `403`: Forbidden — insufficient permissions or project disabled
- `404`: Resource not found
- `429`: Rate limit or billing limit exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/sendly/apis/sendly-api.md) · [All operations](https://skmtc.dev/sendly/apis/sendly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sendly/apis/sendly-api/revisions/ce7cfb7f7c7e?raw)
