Events and payloads
Events and payloads
Anatomy of a webhook
Notifications contain a JSON payload, and HTTP headers that provide context. For example, the Invoice model webhooks include the following:
| Key | Section | Type | Description |
|---|---|---|---|
Tk-webhook-hmac-sha256 | Header | string | Signature to authenticate Perk as the sender of the request |
Tk-webhook-name | Header | string | Title used to name your webhook endpoint, specified at subscription time |
Tk-webhook-event | Header | string | Event that triggered the notification |
Tk-webhook-test | Header | string | Only set for test notifications. You can check this value to disregard the notification (however signature will always be provided) |
| JSON Payload | Body | object | Payload response with details, as per the Model the event belongs to. Check List of events for specific models used for each event |
List of events
Webhooks are available for the following events:
| Event | Model | Trigger |
|---|---|---|
invoice.issued | Invoices | When billing period closes and invoice is issued |
trip.created/updated | Trip | When a trip is:
|
Payloads
invoice.issued
invoice.issuedThe payload follows the InvoiceLine model. Refer to that page to check the required and optional attributes.
{
"billing_information": {
"legal_name": "My Company Ltd",
"vat_number": "GB123456789",
"address_line_1": "199 Bishopsgate",
"address_line_2": "Spitalfields",
"city": "London",
"postal_code": "EC2M 3TY",
"country_name": "United Kingdom"
},
"billing_period": "instant",
"currency": "GBP",
"due_date": "2020-03-14",
"from_date": "2020-03-14",
"to_date": "2020-03-24",
"issuing_date": "2020-03-14",
"lines": [
{
"id": "78d8f031-8e23-4be0-b841-1f685b8ae791",
"expense_date": "2020-03-14",
"description": "Premium Service for Trip 2494",
"quantity": 1,
"unit_price": "25.00",
"non_taxable_unit_price": "0.00",
"tax_percentage": "0.00",
"tax_amount": "0.00",
"tax_regime": "G-VAT-R",
"total_amount": "25.00",
"metadata": {
"trip_id": 2494,
"trip_name": "Gary Visits Birmingham Christmas Market 🧑🎄",
"service": "PREMIUM",
"related_vertical": "flight",
"travelers": [
{
"name": "Gary Train",
"email": "[email protected]",
"external_id": null
}
],
"booker": {
"name": "Gary Train",
"email": "[email protected]",
"external_id": null
},
"start_date": null,
"end_date": null,
"cost_center": "hr-bcn",
"labels": [],
"vendor": null,
"out_of_policy": null,
"approvers": [],
"service_location": null,
"include_breakfast": null,
"credit_card_last_4_digits": "5556"
},
...
],
"mode": "reseller",
"pdf": "https://api.travelperk.com/invoices/INV-01-1234/pdf",
"profile_id": "150d5e95-3bbc-4fab-a8a4-e403f662f6b2",
"profile_name": "Profile My Company Ltd",
"reference": "Trip #9876543",
"serial_number": "INV-01-1234",
"status": "paid",
"taxes_summary": [
{
"tax_regime": "STAR",
"subtotal": "1001.12",
"tax_percentage": "0.00",
"tax_amount": "0.00",
"total": "1001.12",
},
{
"tax_regime": "G-VAT-R",
"subtotal": "10.00",
"tax_percentage": "0.00",
"tax_amount": "0.00",
"total": "10.00",
}
],
"total": "1011.12",
"travelperk_bank_account": null
}trip.created/updated
trip.created/updated{
"id": "2655",
"trip_name": "Trip Webhook TZ Test 2",
"start": "2022-12-18T12:00:00+00:00",
"start_datetime_utc": "2022-12-18T11:00:00+00:00",
"start_datetime_local": "2022-12-18T12:00:00+01:00",
"end": "2030-04-17T08:25:00+00:00",
"end_datetime_utc": "2030-04-17T06:25:00+00:00",
"end_datetime_local": "2030-04-17T08:25:00+02:00",
"status": "booked",
"modified": "2022-11-24T15:26:34.342013+00:00",
"start_location": {
"name": "North Tara Airport",
"address": "",
"latitude": "76.5021054",
"longitude": "42.3743066",
"iata_code": "BCN"
},
"end_location": {
"name": "North Tara Airport",
"address": "",
"latitude": "76.5021054",
"longitude": "42.3743066",
"iata_code": "BCN"
},
"bookings": [
{
"id": "1434",
"start": "2022-12-18T12:00:00+00:00",
"end": "2030-04-17T08:25:00+00:00",
"type": "flight",
"status": "confirmed",
"modified": "2022-11-24T15:26:24.251116+00:00",
"trip_id": "2655",
"references": [
{
"type": "PNR",
"value": "R9T6P7"
}
],
"location": null,
"drop_off_location": null,
"legs": [
{
"segments": [
{
"origin": {
"location": {
"name": "Salasstad Airport",
"address": "",
"latitude": "15.4886261",
"longitude": "131.0075138",
"iata_code": "MAD"
},
"time": "2022-12-18T12:00:00+01:00"
},
"destination": {
"location": {
"name": "North Tara Airport",
"address": "",
"latitude": "76.5021054",
"longitude": "42.3743066",
"iata_code": "BCN"
},
"time": "2022-12-18T13:20:00+01:00"
},
"external_id": "VY1056"
}
]
},
{
"segments": [
{
"origin": {
"location": {
"name": "North Tara Airport",
"address": "",
"latitude": "76.5021054",
"longitude": "42.3743066",
"iata_code": "BCN"
},
"time": "2030-04-17T07:00:00+02:00"
},
"destination": {
"location": {
"name": "Salasstad Airport",
"address": "",
"latitude": "15.4886261",
"longitude": "131.0075138",
"iata_code": "MAD"
},
"time": "2030-04-17T08:25:00+02:00"
},
"external_id": "VY1044"
}
]
}
]
}
],
"booker_id": "96"
}The trip.created/updated payload structure can vary depending on the details of the trip booking. There may also be multiple bookings within the same trip. A single booking might be for a hotel stay, a flight, a train journey, or a car hire.
The start_location and end_location within the trip are unlikely to be useful for the purpose of calculating traveler location, as in most journeys they will both show the same value if it is a return journey. Instead, the useful location information is structured differently depending on the type of booking, as a hotel only has a single location, whereas a flight booking could contain several. Here are a few possibilities:
- A train booking may have a single leg if it is a one-way ticket, or two legs if it is a return ticket. Additionally each leg will contain one or more segments - this is to accommodate non-direct routes, ie where the traveler needs to change trains en-route. Each segment will contain an origin and a destination (corresponding to the departure and arrival stations, respectively). These will contain location information in the form of a train station name, address and longitude / latitude.
- A flight booking may also have one or two legs depending on whether it is a one-way or return flight. Additionally each leg will contain one or more segments - this is to accommodate possible multi-segment flights for long-haul routes. Each segment will contain an origin and destination (corresponding to the departure and arrival airports, respectively) containing location information in the form of: name, address, iata_code and longitude / latitude.
- A hotel booking will not contain legs or segments, and instead should contain the hotel's location information directly in the booking.
- A car hire booking will also not contain legs or segments. It will instead contain a location directly in the booking which indicates where the car is picked up from, as well as a drop_off_location which might be different from the pick-up location.
- For all the above configurations, each booking should contain a start and end date or datetime which is in naive local-time for flights and trains, and just a midnight-locked date for cars and hotels. There are additional _datetime_local and _datetime_utc versions - for flights and trains these will show the departure and arrival time of the journey, whereas for hotels and cars they will again just be midnight-to-midnight values. start_datetime_utc and end_datetime_utc are useful for import into time-management and calendar solutions as they are true UTC values. start_datetime_local and end_datetime_local are more useful for processing into systems that present user-read output, such as email notifications where the recipient might wish to know, for example, the local departure time of their flight.
- Each segment origin and destination will contain a time (that also holds the date, and is in local-time with the timezone offset indicated).
Use the Users endpoints to get the latest travelers for a trip. Customers commonly integrate with the trip.created/updated webhook to get notified when travelers change, then retrieve the updated details from the users endpoints to stay in sync.

