Skip to content

Webhooks

A webhook is a message Project Expedition sends to your system the moment something happens to one of your bookings, such as a new booking or a date change. You don’t have to keep checking the booking_updates endpoint to find out.

  1. You provide a web address on your system that accepts HTTPS POST requests (e.g., https://yoursite.com/pe-webhook).
  2. Project Expedition sets it up on your account — no API call required on your side.
  3. Whenever one of your bookings is placed, changes, is canceled or has its commission paid, PE sends a short JSON message to that address describing what happened.

To set up a webhook, email partners@projectexpedition.com with your endpoint URL.

Staging: Webhooks can be configured for the staging environment as well, allowing you to test your handler before going live.

Every message has a type field that says what happened:

type What happened
New Booking A booking was placed (confirmed or pending confirmation). Sent again when a pending booking is confirmed
Booking Update Something changed on a confirmed booking after it was placed, such as the date or time, pickup, number of travelers, traveler names or contact details, price or payments, cancellation date, operator notes or voucher. Changes made close together arrive as one message, at most one per booking every 5 minutes
Cancel Booking The booking was canceled
Commission Paid Project Expedition has paid your commission for the booking

This is what a message looks like. The first three fields are always there. The data part is a copy of the booking, included if you ask for it when the webhook is set up.

{
"booking_reference": "PE2847391",
"type": "Booking Update",
"timestamp": "2026-09-23 14:05:00",
"data": {
"iata": "12345678",
"business_unit": "Example Consortium",
"agency_name": "Doe Travel Agency",
"agent_name": "Jane Doe",
"agent_email": "jane@doetravelagency.com",
"booking_reference": "PE2847391",
"voucher": "https://www.projectexpedition.com/account/voucher/PE2847391",
"status": "Confirmed",
"payment_status": "Fully Paid",
"travel_date": "2026-10-15",
"purchase_date": "2026-09-01",
"latestcancellation_date": "2026-10-13",
"percent_norefund": "0",
"end_date": "2026-10-15",
"product_type": "Private Single Day Tour",
"product_id": "PRD129761",
"town": "Agra",
"country": "India",
"product": "Private Taj Mahal Tour",
"number_of_passengers": "2",
"lead_passenger": "John Smith",
"gross_amount": "450.00",
"net_amount": 405.5,
"commission": "44.50"
}
}

data shows the booking as it was when the message was sent. You can always look up the latest version of the booking with GET /booking?id=PE2847391.

Field What it means
booking_reference The booking’s reference number, the same one GET /booking?id= uses
type What happened, from the table above
timestamp When the message was sent, in US Eastern time (YYYY-MM-DD HH:MM:SS)
data.status Booking status, e.g. Confirmed, Pending Confirmation, Canceled
data.payment_status Payment status, e.g. Fully Paid, Deposit Paid, Partial Payment, Hold without Payment, Returned to Traveler
data.travel_date, data.end_date First and last day of the tour or trip (YYYY-MM-DD)
data.purchase_date Day the booking was placed (YYYY-MM-DD)
data.latestcancellation_date, data.percent_norefund Last day to cancel under the cancellation policy, and the non-refundable percentage when the policy has one
data.gross_amount, data.commission, data.net_amount Booking total, your commission, and the total minus your commission. gross_amount and commission are sent as strings (e.g. "450.00"); net_amount is sent as a number (e.g. 405.5)
data.product_id PRD followed by the product number (the same number as the product’s PE id elsewhere in this API)
data.voucher Link to the booking voucher
  • Reply quickly. Send back a success status (any 2xx, such as 200 OK) within 10 seconds. PE sends each message once and does not retry. If your system was down, use booking_updates to catch up on anything you missed.
  • Expect repeats. The same type can arrive more than once for a booking. For example, New Booking arrives when a booking is placed and again when it is confirmed. Check booking_reference and data.status so each change is handled only once.
  • Check the signature (optional). To confirm a message really came from Project Expedition, ask for a shared secret when the webhook is set up. PE then signs every message with base64(HMAC-SHA256(raw request body, secret)) and sends the result in a request header agreed during setup. Compute the same value over the message exactly as received, before parsing the JSON, and reject any message where the two don’t match.