Skip to main content
When someone scans the QR code on a Mailr postcard and fills out the landing-page form, that’s a lead. You can receive leads two ways: subscribe an endpoint for instant delivery, or poll for recent leads. Required scope (both): webhooks:inbound
Only landing-page leads (source = landing_page) are delivered or polled out. Leads you sync into Mailr via POST /api/v1/tracking/lead are never fanned back out — that would round-trip a lead straight into the CRM it came from.

Subscribe

POST /api/v1/webhooks/subscribe registers a public HTTPS URL for lead.created deliveries.
200 OK
Store the signing_secret — it is shown exactly once, here at creation. Re-subscribing the same URL is idempotent and returns the existing subscription’s id with signing_secret: null — it never rotates or re-discloses a live secret, so a re-subscribe can’t silently break your verification and a compromised API key can’t recover your active secrets. Lost the secret? POST /api/v1/webhooks/rotate mints a new one and returns it once. A subscription created before signing shipped is delivered unsigned; delete and re-subscribe (or rotate) to upgrade it.
The URL is SSRF-guarded: public https only, and the hostname must resolve to public addresses — at registration and again at delivery time. event defaults to lead.created (the only supported value). To remove a subscription, DELETE /api/v1/webhooks/subscribe?id=<id> or ?target_url=<url> (org-scoped).

Rotate a lost secret

POST /api/v1/webhooks/rotate mints a replacement signing secret and returns it exactly once. Identify the subscription by id or by target_url (plus optional event, default lead.created).
curl
Rotation takes effect immediately — deliveries sign with the new secret the moment it’s issued. Update your receiver first, or tolerate a brief window where verification fails.

The lead.created delivery

Mailr POSTs the canonical enriched lead to your endpoint. It’s the same object shape the poll endpoint returns, plus a mailr_lead_id:
Each custom_fields entry is also flattened to a top-level custom_<field_id> key (semicolon-joined) for easy CRM mapping. Mailr does not inspect your response status — a delivery is considered attempted once the request completes. Non-2xx responses are ignored; timeouts and blocked hosts are recorded in Mailr’s server logs only (not in your webhook log) and are not retried. Poll GET /api/v1/integrations/leads to reconcile anything your endpoint dropped.

Signature verification

A subscription with a signing_secret receives two headers, in the same shape Stripe and Slack use: The signed string is `${timestamp}.${rawBody}` where rawBody is the exact bytes of the request body. Verify by recomputing the HMAC over the raw body you received (do not re-serialize the parsed JSON — key order or number formatting could drift), comparing in constant time, and rejecting timestamps that drift more than 300 seconds from now.

Avoiding echo loops

Because deliveries carry mailr_lead_id, a lead you receive here and then write into your CRM can be recognized if your automation fires it back at POST /api/v1/events. Always copy mailr_lead_id into record.properties.mailr_lead_id on any event derived from a Mailr lead — Mailr will skip campaign matching (reason: "loop_guard") rather than mailing an address it just sourced. See Send events → Loop guard.

Poll instead

GET /api/v1/integrations/leads?since=<ISO> returns the 50 most recent landing-page leads, newest first, filtered to created_at strictly after since. De-dupe by id.
200 OK
A brand-new org with no real leads receives exactly one clearly flagged sample lead (test: true, fixed all-zero id) so a Zap’s “Test trigger” step can map fields. It disappears once a real lead is captured.