Skip to main content
Work through these eight before you send production traffic. Each maps to behavior enforced by the API.
1

Mint an org-scoped key with the right scopes

Create an ak_ key in the Mailr app under your workspace name → Manage accountAPI keys (Owner-only). Give it events:write and/or import:write and/or webhooks:inbound as needed — or leave it unscoped (unscoped keys pass every check). A key scoped to only import:write cannot post events, and vice versa.
2

Verify the key resolves to the right org

Confirm org_id / org_name is the tenant you expect. A 403 here means either the key is missing the webhooks:inbound scope that /api/v1/me requires, or it isn’t tied to a billing owner. If you scoped the key to events:write only, add webhooks:inbound (or leave the key unscoped) to use this check.
3

Bind your automations

Send at least one live event so your event_type appears in the app’s binding picker (dry-run events write nothing, so they don’t register the event type), then set an automation’s trigger to Custom API and bind it to that event_type (and object_type if you want to pin one). Nothing mails until a binding exists — an unbound event returns matched_automations: 0.
4

Dry-run your real payload

POST your actual event with "dry_run": true and confirm the outcome is reason: "queued" for the automation you expect. Dry run exercises the full binding/filter/address/dedup path but writes nothing.
5

Get your addresses and property keys right

Ensure every reserved key is spelled exactly (street, city, state, zip, client_name, client_email, client_phone, amount, status, mailr_lead_id) and every other key is cf_-prefixed — a mis-spelled reserved key is a 422. Confirm each mailable record has street plus city or zip, or it reports no_address.
6

Subscribe your lead endpoint and verify signatures

POST /api/v1/webhooks/subscribe, store the signing_secret, and implement HMAC verification over "<X-Mailr-Timestamp>.<rawBody>" with a 300-second freshness window (see Receive leads). Use the raw request body, not re-serialized JSON.
7

Close the loop guard

On any event your automation derives from a Mailr-delivered lead, echo mailr_lead_id into record.properties.mailr_lead_id. Without it, a lead Mailr sourced can start a campaign back at its own address — an infinite echo. Confirm such an event reports reason: "loop_guard".
8

Handle limits, retries, and replay

Read Retry-After on 429/503 and back off. Treat 4xx as terminal (fix the request); treat 429/5xx as retryable. Wire stable idempotency keys (dedup_id, deal_id) so that your gap-recovery plan is simply replay the window — there is no reconciliation sweep.
Once all eight pass against a real key using dry_run and a low-volume test automation, flip your integration to full production traffic. Because every write is idempotent, a cautious first run that replays its first window is safe.