API reference

Webhook events

The qr.scanned event: its headers, its payload, and example deliveries.

Generated from /openapi.json.

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.

qr.scanned

Sent as a POST with a JSON body to every active endpoint for each recorded scan of a QR code on your mail, including repeat scans from the same device. A test event carries a top-level "test": true.

Headers

  • content-typeheader
    Always application/json.
  • webhook-idheader
    The event id, stable across retries and redeliveries. Use it to deduplicate.
  • webhook-timestampheader
    When this delivery attempt was sent, in Unix seconds.

There is no signature header.

Payload

  • eventstring
    Always qr.scanned.
  • idstring
    The event id, also sent as webhook-id.
  • testboolean
    Present only on a test event. Always true.
  • scanned_atstring
    When the scan happened, in UTC (ISO 8601).
  • campaignobject
    The campaign whose card was scanned.
    • idstring
      The campaign ID (PA- followed by 6 characters).
    • namestring
      The campaign's name.
  • recipientobject
    Who the card was mailed to. A value we don't have is null.
    • first_namestring or null
    • last_namestring or null
    • emailstring or null
    • phonestring or null
    • address_1string or null
    • address_2string or null
    • citystring or null
    • statestring or null
    • zipstring or null
  • locationobject
    The approximate scan location, from the scanning device's network.
    • citystring or null
    • regionstring or null
    • latitudenumber or null
    • longitudenumber or null
  • destinationstring
    Where the QR code sent the person.
Scan delivery
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"
}
Test event delivery
POST /postaged/7f3c1b9e5a2d48c6b0e4f19d7a6c3e85 HTTP/1.1
content-type: application/json
webhook-id: evt_test_5d0a9c3e7f21b846
webhook-timestamp: 1786651282

{
  "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"
}

Your response

Received. Any 2xx counts as delivered.

Retries, automatic disabling, and test events are described in the Webhooks guide.