Guides
Webhooks
Get a POST to your endpoint every time someone scans a QR code on one of your cards.
Webhooks are not signed
Postaged doesn't sign webhook deliveries, so a request to your endpoint can't prove it came from us. Use an endpoint URL with a long, random path that only you and Postaged know, and treat every payload as untrusted input: check its values before you act on them.
Add an endpoint
- In Postaged, open Settings > API & Webhooks. Under Webhook endpoints, choose Add endpoint.
- Enter your Endpoint URL.
- Choose All campaigns, which includes campaigns you create later, or Selected campaigns.
Your endpoint must:
- Use HTTPS on a public host. Redirects are not followed.
- Answer within 10 seconds.
Only an Owner or Admin can add, pause, or delete an endpoint.
https://hooks.example.com/postaged/7f3c1b9e5a2d48c6b0e4f19d7a6c3e85The qr.scanned event
Every recorded QR scan from a matching campaign sends one POST with a JSON body. A value we don't have is null.
- eventstringAlways
qr.scanned. - idstringThe event id. The same value as the
webhook-idheader. - scanned_atstringWhen the scan happened, in UTC (ISO 8601).
- campaignobject
id(the campaign ID, likePA-4H2K9C) andname. - recipientobjectWho the card was mailed to:
first_name,last_name,email,phone,address_1,address_2,city,state,zip. - locationobjectThe approximate scan location:
city,region,latitude,longitude. - destinationstringThe address the QR code sent the person to.
- testbooleanPresent and
trueonly on a test event.
Headers
content-type: application/jsonwebhook-id: the event id. It stays the same across retries and redeliveries, so use it to deduplicate.webhook-timestamp: when we sent this attempt, in Unix seconds.
There is no signature header. See Webhook events for the full schema.
POST /postaged/7f3c1b9e5a2d48c6b0e4f19d7a6c3e85 HTTP/1.1
content-type: application/json
webhook-id: evt_8c1f2b9d4a
webhook-timestamp: 1786651282
{
"event": "qr.scanned",
"id": "evt_8c1f2b9d4a",
"scanned_at": "2026-08-09T18:41:22Z",
"campaign": { "id": "PA-4H2K9C", "name": "Spring open house" },
"recipient": {
"first_name": "Dana",
"last_name": "Whitfield",
"email": "dana@example.com",
"phone": null,
"address_1": "18 Rowan St",
"address_2": null,
"city": "Hartford",
"state": "CT",
"zip": "06105-2214"
},
"location": {
"city": "Hartford",
"region": "CT",
"latitude": 41.76,
"longitude": -72.69
},
"destination": "https://offers.example.com/SPRING24"
}Respond quickly
Respond with any 2xx status as soon as you receive the event, then process it afterwards. Anything else, or no answer within 10 seconds, counts as a failed delivery.
Duplicates
- Every scan delivers, including repeat scans from the same device. Deduplicate by
webhook-id, which repeats only on a retry or when you choose Redeliver. - A retry, or a delivery sent again with Redeliver, carries the same
webhook-id. Keep the ids you've processed and skip one you've already seen.
HTTP/1.1 200 OKRetries and disabling
- A failed delivery retries at about 5 minutes, 15 minutes, 1 hour, and 6 hours: 5 attempts in all.
- After 20 failed delivery attempts in a row, we disable the endpoint and email your team.
- While an endpoint is paused or disabled, scans aren't queued for it and aren't sent later.
- To turn it back on, fix the endpoint, then choose Resume on it in Settings > API & Webhooks.
- Recent deliveries on an endpoint shows its last 25 deliveries, and Redeliver sends one again.
Test events
Choose Send test event on an endpoint in Settings > API & Webhooks. We send a qr.scanned event with example data and a top-level "test": true.
- A test delivery is never retried.
- It never counts toward disabling the endpoint.
{
"event": "qr.scanned",
"id": "evt_test_5d0a9c3e7f21b846",
"test": true,
"scanned_at": "2026-08-09T18:41:22Z",
"campaign": { "id": "PA-EXAMPLE", "name": "Example campaign" },
"recipient": {
"first_name": "Dana",
"last_name": "Whitfield",
"email": "dana@example.com",
"phone": null,
"address_1": "18 Rowan St",
"address_2": null,
"city": "Hartford",
"state": "CT",
"zip": "06105-2214"
},
"location": {
"city": "Hartford",
"region": "CT",
"latitude": 41.76,
"longitude": -72.69
},
"destination": "https://example.com/offers"
}