> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.rray.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.rray.app/_mcp/server.

# Welcome

rray is a transactional email platform: you `POST` a message, we hand it to our
sending fleet and stream delivery outcomes back into the API, where you can query
them at any time.

## Base URL

```
https://api.rray.app
```

All endpoints are versioned under `/v1`. Requests and responses are JSON;
errors are [RFC 9457 problem details](/docs/concepts/errors).

## The 60-second tour

1. Create an API key on the **Keys** page of the
   [dashboard](https://dash.rray.app) — keys look like `rray_live_...` and are
   shown exactly once.
2. Send your first message — one `POST /v1/messages`, optionally with an
   [idempotency key](/docs/concepts/idempotency).
3. Track it — `GET /v1/messages/{id}` returns the live status plus the
   per-recipient delivery timeline, and `GET /v1/messages` gives you a
   [cursor-paginated](/docs/concepts/pagination), filterable feed.

Head to the [Quickstart](/docs/get-started/quickstart) to run all three now,
or browse the [API Reference](/api) — every endpoint there is annotated with
the exact errors it can return.

## The three things to know first

* **A message is one send; a delivery is one recipient's copy of it.** Every address
  across `to`, `cc` and `bcc` becomes its own delivery, with its own status and its own
  place in the timeline. [Message lifecycle](/docs/concepts/message-lifecycle) has the
  whole state machine.
* **Every message belongs to one workspace.** A workspace key carries its workspace; a
  platform key names one per request. See
  [Credentials](/docs/concepts/authentication) and
  [Workspaces](/docs/concepts/workspaces).
* **Every number the API enforces is on one page.** Batch size, attachment budget, rate
  limits, retention, id formats: [Limits & facts](/docs/get-started/limits).

## Design principles you can rely on

* **Machine-readable everything**: every error carries a stable dotted `code`
  (`message.not_found`), a `category` to switch on, and a `type` URL that
  resolves to the public [error catalog](https://api.rray.app/errors).
* **Safe retries**: sending is idempotent when you pass `Idempotency-Key`;
  reads are always safe.
* **No surprises at scale**: list endpoints paginate by cursor and never slow
  down as your history grows.