ReachlySend API

REST over HTTPS, JSON request/response. Tokens are workspace-scoped and behave the same as a logged-in session. Issue and revoke them at app.reachlysend.com/settings.

Endpoints

Authentication

Pass an Authorization: Bearer <token> header on every request. Workspace-scoped endpoints also need X-Workspace-Id: wsp_….

Base URL: https://api.reachlysend.com

curl https://api.reachlysend.com/api/tests \
  -H "Authorization: Bearer rls_live_xxxxxxxxxxxx" \
  -H "X-Workspace-Id: wsp_xxxxxxxxxxxx"

Tests

GET/api/tests

List tests (most recent first). Query: limit (1–100, default 50), offset.

GET/api/tests/:id

Full report — analyzer findings, category scores, placement results, delivery timeline, raw headers.

GET/api/tests/:id/eml

Returns the parsed body, attachments, and embedded image/tracking-pixel inventory.

POST/api/tests/:id/reanalyze

Re-runs the analyzer against the stored .eml. Useful while iterating on rules; no fresh send needed.

CSV export

GET/api/tests/export.csv

Streams every test for the workspace as CSV. Columns: id, received_at, from, subject, status, composite, inbox_rate, spam_rate, promo_rate, spf, dkim, dmarc. Capped at 5,000 rows. Set ?limit=N to lower.

Dispatch a sample test

POST/api/tests/send-test

Sends a sample message through AWS SES to the workspace's active seed inbox. Cloudflare Email Routing receives it and the analyzer runs end to end — useful for smoke-testing the pipeline without hooking up a real ESP.

curl -X POST https://api.reachlysend.com/api/tests/send-test \
  -H "Authorization: Bearer rls_live_xxx" \
  -H "X-Workspace-Id: wsp_xxx" \
  -H "Content-Type: application/json" \
  -d '{"subject":"My sample","from":"[email protected]"}'

Dashboard summary

GET/api/dashboard/summary

Returns the same KPIs and trend slices used by the in-app dashboard: deliverability score, inbox/spam/promo rates, recent tests, top issues of the week.

Domain monitor

GET/api/domains

List monitored domains and the latest SPF/DKIM/DMARC/BIMI verdicts.

POST/api/domains

Body: { domain, dkimSelector? }. Adds a domain to the hourly cron sweep.

POST/api/domains/:id/recheck

Force-recheck on demand (rate-limited).

DELETE/api/domains/:id

Alert webhooks

Slack, Discord, or generic JSON webhooks for three events: domain.drift, test.low_score, email.bounce_complaint.

GET/api/alerts

POST/api/alerts

{
  "label": "#deliverability",
  "url": "https://hooks.slack.com/services/...",
  "kind": "slack",
  "events": ["domain.drift", "test.low_score"],
  "thresholdScore": 60
}

PATCH/api/alerts/:id

DELETE/api/alerts/:id

POST/api/alerts/:id/test

Fires a one-off test ping at the configured URL.

Integrations

GET/api/integrations

Returns all supported providers and which the workspace has connected.

GET/api/integrations/:provider/connect

Returns the OAuth authorization URL. Open in a browser; the callback finishes the connection.

DELETE/api/integrations/:id

Errors & rate limits

Errors return JSON: { "error": "<code>" } with an HTTP status. Common codes:

Auth endpoints are rate-limited to 30 requests / 60 seconds per IP. Other endpoints inherit Cloudflare's per-Worker default; we don't apply additional throttling, but keep concurrency reasonable.