Quickstart

From API key to delivered email in three requests

1. Get an API key

Create a key in the dashboard. You’ll get a rray_live_... (or rray_test_...) secret — store it safely, it is shown exactly once.

Every request authenticates with a Bearer header:

$export RRAY_API_KEY="rray_live_..."

2. Send an email

$curl -X POST https://api.rray.app/v1/emails \
> -H "Authorization: Bearer $RRAY_API_KEY" \
> -H "X-Workspace-Id: ws_..." \
> -H "Idempotency-Key: order-1042-receipt" \
> -H "Content-Type: application/json" \
> -d '{
> "from": "receipts@yourdomain.com",
> "to": "customer@example.com",
> "subject": "Your receipt",
> "html": "<h1>Thanks!</h1>",
> "text": "Thanks!"
> }'

A 202 Accepted returns the email object:

1{
2 "id": "em_01J8ZQ3M9V...",
3 "object": "email",
4 "status": "sent",
5 "from": "receipts@yourdomain.com",
6 "to": "customer@example.com",
7 "subject": "Your receipt",
8 "workspace_id": "ws_...",
9 "created_at": "2026-07-05T12:00:00Z"
10}

Two headers worth understanding before production:

3. Track delivery

Statuses progress queued → sent → delivered (or bounced / deferred). Poll one email:

$curl https://api.rray.app/v1/emails/em_01J8ZQ3M9V... \
> -H "Authorization: Bearer $RRAY_API_KEY"

Or list recent deliveries with a filter:

$curl "https://api.rray.app/v1/emails?status=delivered&limit=20" \
> -H "Authorization: Bearer $RRAY_API_KEY"

List responses are cursor-paginated — follow pagination.next_cursor for older emails, pagination.prev_cursor for newer ones (how it works).

If something goes wrong

Errors are flat application/problem+json bodies with a stable code to match on and a request_id to quote to support:

1{
2 "type": "https://api.rray.app/errors/validation.workspace_header_required",
3 "title": "X-Workspace-Id header required",
4 "status": 400,
5 "code": "validation.workspace_header_required",
6 "request_id": "d41d8cd9...",
7 "instance": "/v1/emails"
8}

The full catalog lives at GET /errors and in the Errors guide.