Webhook Event Processing

👍

Scopes required: Webhook_Create, Webhook_Get, Webhook_Update, Webhook_GetFailedMessages (recovery re-fetches also need the relevant *_Get scopes, e.g. Booking_Get)

1. Register your endpoint

curl -X POST https://api.roller.app/webhooks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://marketplace.example.com/hooks/roller",
    "enabled": true,
    "authentication": { "apiKey": "shared-secret-known-only-to-you" },
    "webhooks": {
      "booking": {
        "events": ["Created", "Updated", "Cancelled"],
        "include": { "tickets": true, "payments": true, "externalId": true }
      },
      "signedWaiver": { "events": ["Created"] }
    }
  }'

2. Handle deliveries idempotently

Each message carries a unique id — store processed IDs and skip duplicates. Respond 200 immediately and process asynchronously:

app.post("/hooks/roller", async (req, res) => {
  if (req.headers["x-api-key"] !== SHARED_SECRET) return res.status(401).end();
  const { id, type, eventType, eventDate, data } = req.body;
  if (await alreadyProcessed(id)) return res.status(200).end();
  await queue.publish({ id, type, eventType, eventDate, data });
  res.status(200).end(); // ack fast — retries fire on non-2xx
});

Events can arrive out of order — use eventDate (not arrival time) when applying state changes.

3. Monitor failed deliveries

ROLLER retries failed deliveries up to 7 times. Poll the failed-messages endpoint (e.g. every 15 minutes) to catch persistent failures:

curl "https://api.roller.app/webhooks/messages/failed" -H "Authorization: Bearer $TOKEN"
[
  {
    "webhookId": 311,
    "uniqueId": "0f0d6c1e-...",
    "status": "Attempt3Failed",
    "webhookType": "Booking",
    "webhookEventType": "Updated",
    "nextRetryDate": "2026-06-11T05:00:00Z",
    "history": [
      { "status": "Attempt3Failed", "httpResponseStatus": 502, "detail": "Bad Gateway", "createdDate": "2026-06-11T04:00:00Z" }
    ]
  }
]

4. Recover missed events

For messages with status: "Failed" (terminal), reconcile by re-fetching the affected entities — e.g. GET /bookings?modifiedFromDate=... to sweep bookings changed since your last known-good event, then upsert into your system.

5. Operational tips

  • Alert when the failed list grows or any message reaches Attempt5Failed+.
  • Webhook target outages longer than the retry window require a reconciliation sweep (step 4).
  • Keep webhook configurations under change control: GET /webhooks lists them; PUT /webhooks/{webhookId} updates in place.

Did this page help you?