FlyRail
Browse the docs

Webhooks

Add endpoints under Webhooks in the portal. We POST JSON to your URL (public https only) when something happens.

Event When
booking.ticketed Ticket issued
booking.failed Booking couldn't be completed. Money returned
booking.cancelled Booking cancelled
booking.refunded A refund reached your wallet
{ "id": "7d1f…", "type": "booking.ticketed", "created_at": "2026-12-01T10:00:00+00:00", "data": { "id": "FR-AB12CD34", "status": "ticketed", "pnr": "XK92QA", "total": 11368250 } }

Payloads carry no passenger details. Fetch the booking if you need them.

Verify the signature#

Every delivery has X-FlyRail-Signature: t=<unix time>,v1=<hex>. v1 is the HMAC-SHA256 of "<t>.<raw body>" using your endpoint's signing secret (shown once when you create it).

$header = $request->header('X-FlyRail-Signature');
preg_match('/t=(\d+),v1=([a-f0-9]+)/', $header, $m);
$expected = hash_hmac('sha256', $m[1].'.'.$request->getContent(), $secret);
abort_unless(hash_equals($expected, $m[2]) && abs(time() - (int) $m[1]) < 300, 400);

Use the raw body, compare in constant time, and reject anything older than five minutes.

Retries#

Reply 2xx within 10 seconds. Anything else is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours, then marked failed (retry it from the portal). Deliveries can repeat, so dedupe on the event id. Events aren't guaranteed to arrive in order: use status from the payload or fetch the booking.

GET /webhooks/events lists recent deliveries and their state. Send test in the portal sends a webhook.test event.