Quickstart

This walks you from nothing to a delivered, security-scanned first send in about a minute, using the rly command-line tool. Every step below is the same one a customer runs — the send goes to a standard success-simulator address that accepts any message and never bounces, so you need no real recipient to prove the workflow.

You'll: install the CLI, get an API key, create a mailbox, send a message, and read it back with its scan verdict.

1. Install the CLI

The CLI is published as rly on both npm and PyPI. Pick one:

npm install -g rly        # Node.js 22+
# or
pipx install rly          # bundled native launcher, no Node toolchain needed

Both installs expose the rly and replylayer commands (they are identical — the examples here use the shorter rly).

Alpine/musl base images can't run the prebuilt binary — install with npm i -g rly on host Node 22+ instead. Full install options, platform support, and signature verification are covered in the CLI reference.

2. Get an API key

Auth is a single API key. Where it comes from:

  1. Sign up at app.replylayer.ai. Signup is invite-gated, and a new account is inert until a human completes both signup checks — a 6-digit code emailed to you and a 6-digit code sent by SMS to the mobile number supplied at signup. This is by design (anti-abuse): agents operate with a key a human has already provisioned and verified.
  2. Create an API key in the dashboard and copy it. Keys look like rly_live_<public_id>.<secret> — the secret is shown once, so store it now.

Keys can be scoped admin (full account) or agent (bound to specific mailboxes). For your first send an admin key is simplest. See Authentication for scoping and rotation.

If a later call returns EMAIL_NOT_VERIFIED or PHONE_NOT_VERIFIED, the human bootstrap above is incomplete — finish the indicated check in the dashboard; don't retry the protected call in a loop. The CLI equivalents are rly auth verify --code <email-code> and rly auth verify-phone --code <sms-code>.

3. Point the CLI at your key

Provide the key via the REPLYLAYER_API_KEY environment variable, which wins over any stored credential:

export REPLYLAYER_API_KEY=rly_live_<public_id>.<secret>

Production (https://api.replylayer.ai) is the default endpoint — real clients set nothing else. Confirm auth and connectivity:

rly doctor --json
# → { "ok": true, "checks": [ ... ] }

ok: true with the auth check reporting ok means your key is live.

4. Create a mailbox

A mailbox is your send/receive email address. Create one:

rly mailbox create support-bot --json
# → { "id": "<mailbox-id>", "name": "support-bot", "address": "support-bot@..." }

The returned address is where inbound mail (and replies) will land.

5. Send your first message

Send to ReplyLayer's own first-party simulator address — it accepts every message without bouncing, so no recipient confirmation is needed even on the free Sandbox tier. The send is accepted immediately and a genuine message.delivered webhook fires a few seconds later. The email simulator guide covers the bounce, complaint, suppression, inbound, and webhook-test scenarios:

rly send \
  --from support-bot \
  --to [email protected] \
  --subject "hello" \
  --body "first send" \
  --json
{
  "status": "sent",
  "message_id": "<message-id>",
  "scan": { "verdict": "clean" }
}

Branch on the JSON status, not on the exit code. status is one of sent, quarantined, blocked, or pending_review; a clean first send is sent. A send that produced a message exits 0 regardless of verdict — so a scanner block is also exit 0 with status: "blocked", while a gate-reject (rate limit, blocked recipient, and so on) exits non-zero with a stable error code and creates no message. The CLI machine interface documents the full exit-code contract, and Message states & scan verdicts covers what each status means and which are releasable.

6. Read it back

Read the message by id to see its stored scan result:

rly inbox read <message-id> --json
# → the message, including scan.verdict and scan.findings

When a real correspondent replies, the reply lands in your mailbox and you read it the same way. To block until the next inbound arrival (for an agent loop), anchor a cursor and wait:

SINCE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
rly --json inbox wait --mailbox support-bot --since "$SINCE" --timeout 30
# exit 0 with "message": null means "polled cleanly, nothing arrived" — not an error.

About the Sandbox tier

The Sandbox is a free 30-day trial that only sends to confirmed recipients (the success simulator above is exempt), so you can prove the workflow before you pay. The four exact first-party simulator scenarios also bypass the cold-send recipient-domain cap, so one Sandbox account can run all four in the same 24-hour period. They still consume daily and cumulative Sandbox allowances. Daily send caps, tiers, and quotas are covered in the limits reference.

Next steps

  • Authentication — key format, admin vs agent scoping, and rotation.
  • REST API reference — the full send / reply / read contract.
  • Webhooks — receive delivery, bounce, and inbound-message events instead of polling.
  • Email simulator — exercise delivery, bounce, complaint, inbound scanning, and quarantine without a real recipient.
  • SDKs and MCP — TypeScript/Python libraries and the Model Context Protocol server, if you'd rather not shell out to the CLI.
  • Building for agents — the machine-facing contracts: scan verdicts, send gates, error envelopes, and the safety model.