Integrate with Reach

Reach is a multi-tenant transactional email API. Your customers are tenants: create one per customer, verify their domain, then send as them.

Two ways to authenticate

Both reach the same /v1 API. Both are scoped to exactly one organisation and project. Pick by who holds the credential.

API key

For your own backend sending on behalf of your own customers. You create a project API key (rk_…) in the console. It holds every scope and does not expire until you revoke it.

API key quickstart

OAuth

For a platform connecting its customers' Reach organisations. An admin approves a set of scopes on the consent page; you receive a 1-hour access token (ro_at_…) and a rotating refresh token (ro_rt_…). Authorization Code + PKCE (S256), confidential clients only.

OAuth integration guide

Base URLs

Two public hosts. https://api.tryreach.email serves /v1, /oauth/token, /oauth/revoke, /health and /openapi.json. https://tryreach.email is the console and serves the OAuth consent page. The console's /account endpoints are internal to the console and are not on the public API host. The examples use these hosts directly; keep them in environment variables or settings in your own code.

Environment
# Keep the base URLs in configuration rather than scattering them through your code.
export REACH_API_URL="https://api.tryreach.email"         # where /v1 and /oauth/* live
export REACH_CONSOLE_URL="https://tryreach.email" # where the consent page lives (OAuth only)

# API key integration (your own backend)
export REACH_API_KEY="rk_..."

# OAuth integration (a platform connecting its customers' organisations)
export REACH_CLIENT_ID="rc_..."
export REACH_CLIENT_SECRET="..."

Conventions that hold everywhere

API conventions
RuleDetail
Authorization: Bearer …Exactly one credential on /v1: an rk_ key or an ro_at_ access token.
ErrorsAlways { "error": { "code", "message", "details?", "requestId" } }. Branch on code, never on the message. Quote requestId to support.
ListsReturn { "rows", "total" }, scoped to the caller's project, with limit and offset.
Unknown query parameterA 422, never ignored. A filter that was dropped and one that was applied must never look the same.
Other project's resource404, never 403.
JSON in, JSON outExcept /oauth/token and /oauth/revoke, which take application/x-www-form-urlencoded (RFC 6749).

Postman collection

A Postman v2.1 collection generated from the same OpenAPI document as these docs: every /v1 operation grouped by tag, the OAuth flow (PKCE pre-request script, token requests that store the tokens for you), and the health check (the console-internal /account endpoints are not included). Import it, then set the baseUrl, consoleUrl and apiKey collection variables. It holds no secrets; baseUrl and consoleUrl default to the hosts above.

Download Postman collection

Where to go next