Webhook events and example payloads

Every TripWorks webhook event, when it fires, and the JSON each one sends, with example payloads you can copy from the setup screen or this page.

Written By Melanie Gannone (Super Administrator)

Updated at October 24th, 2026

TripWorks sends a webhook for 13 kinds of events: trips, guest bookings, add-ons, notes, payments, waivers, payouts, and customers. This page lists each event, when it fires, and what the JSON looks like, so you can build your receiver before the first real event arrives.

To turn webhooks on and add your URL, see Set up webhooks. To see how a delivery is sent and what your server must answer, see How webhook delivery works.

Sample data you can copy

Every event on the setup screen has an Example JSON Payload panel. Open it to see the shape of that event, and select Copy to paste it into your own tests. The examples use made-up guests and amounts, so they're safe to share with a developer or paste into a mock server.

Webhook events in TripWorks: two endpoint URLs on the Trip Create event, Add another endpoint, and the Example JSON Payload panel with a Copy button
Each event card holds its endpoint URLs and a copyable Example JSON Payload.

Events and when they fire

The value in the payload's event field is the exact identifier below (an underscore slug — the setup page shows friendlier labels).

Event (event value) Fires when
trip_created A new trip is created — including drafts and abandoned carts
trip_reserved A trip moves to Reserved (typically the first payment)
trip_updated A trip changes — date/time, guest count, custom fields. Also fires when a guest booking, resource assignment, activity, or reservation note is removed
trip_cancelled A trip is cancelled
booking_updated A guest booking within a trip changes, for example a check-in or a status change
addon_updated An add-on or product is added to or removed from a booking
note_created A reservation note is added to a trip
note_updated A reservation note is edited
payment_created Any payment or refund is processed (fires per payment, including partials)
waiver_signed A customer signs a waiver
payout A payout is sent to your bank account
customer_create A new customer profile (with an email) is created
customer_update A customer profile is modified

What the payload looks like

Each webhook is a POST with Content-Type: application/json. There's no envelope — the object's fields sit at the top level with an event key merged in, like { "event": "trip_created", "id": …, "customer": {…}, "tripOrders": [ … ] }:

{ "event": "trip_created", "id": 2088161, "confirmation_code": "BOOK-1234" }

A few things to know when you parse it:

  • Money is in integer cents. "total": 24200 means $242.00.
  • Trip events nest everything — tripOrders[] (one per activity) each contain bookings[] (one per guest), with customer, ticket type, custom fields, add-ons, and status. They also carry the reservation's current notes[].
  • Removals arrive as trip_updated. Removing a guest booking, a resource assignment, an activity, or a reservation note sends a trip_updated with the trip as it stands after the removal. There's no separate "removed" event, so compare the payload with what you stored to see what's gone. Adding a note sends note_created only, and editing one sends note_updated only; neither sends trip_updated.
  • customer_portal_url — a login-free link to the guest's portal — is included on every trip-related event. trip_created, trip_reserved, trip_updated, trip_cancelled, payment_created, note_created and note_updated (nested under trip) include it at all three levels: the root trip, each trip order, and each booking. booking_updated and addon_updated include it once, at the booking level only. It's not included on waiver_signed, payout, customer_create, or customer_update.

customer_create

Webhook payload example
{
  "event": "customer_create",
  "id": 5567611,
  "code": "CUST-1A2B",
  "first_name": "Jordan",
  "last_name": "Avery",
  "full_name": "Jordan Avery",
  "email": "jordan@example.com",
  "phone": "+15550100",
  "phone_format_intl": "+1 555-0100",
  "phone_format_164": "+15550100",
  "phone_country_code": "US",
  "mappable_position": "Denver Colorado United States",
  "location_description": "Denver, CO, USA",
  "country": {},
  "is_vip": false,
  "is_opt_in": true,
  "timezone": "America/Denver",
  "created_at": "2026-02-26T00:20:59+00:00"
}

trip_created

trip_reserved, trip_updated, and trip_cancelled share this same trip shape — the event, trip_status, and amounts differ.

Webhook payload example
{
  "event": "trip_created",
  "id": 2088161,
  "confirmation_code": "BOOK-1234",
  "display_name": "Jordan Avery",
  "created_at": "2026-02-26T00:05:34+00:00",
  "reserved_at": "2026-02-26T00:05:57+00:00",
  "sale_date": "2026-02-28T00:00:00+00:00",
  "trip_status": { "slug": "draft", "name": "Draft" },
  "trip_method": { "name": "Walkup", "color": "#3498eb", "slug": "walkup" },
  "customer_portal_url": "https://portal.tripworks.com/t/abc123",
  "customer": {
    "first_name": "Jordan",
    "last_name": "Avery",
    "full_name": "Jordan Avery",
    "email": "jordan@example.com",
    "phone": "+15550100",
    "phone_format_intl": "+1 555-0100"
  },
  "tripOrders": [
    {
      "created_at": "2026-02-26T00:05:34+00:00",
      "experience_total": 20000,
      "addons_total": 3000,
      "products_total": 0,
      "pickup_total": 0,
      "promo_code_total": 0,
      "voucher_code_discount": 0,
      "total_sales": 23000,
      "customer_portal_url": "https://portal.tripworks.com/t/abc123?order=1",
      "experience": {
        "id": 105,
        "name": "Hiking",
        "internal_name": "Hiking",
        "duration": 480,
        "color": "#4e5dc1"
      },
      "experience_timeslot": {
        "label": "11:00 AM",
        "start_time": "2026-02-28T11:00:00+00:00",
        "end_time": "2026-02-28T19:00:00+00:00"
      },
      "status": { "id": 1, "slug": "booked", "name": "Booked" },
      "pax_count": 1,
      "addons_cnt": 2,
      "bookings": [
        {
          "id": 5201661,
          "created_at": "2026-02-26T00:05:34+00:00",
          "status": { "id": 15, "name": "Not Checked In" },
          "is_complimentary": false,
          "customer_portal_url": "https://portal.tripworks.com/t/abc123?booking=1",
          "customer": {
            "first_name": "Jordan",
            "last_name": "Avery",
            "full_name": "Jordan Avery",
            "email": "jordan@example.com",
            "phone": "+15550100"
          },
          "experience_customer_type": {
            "id": 195,
            "name": "Adult",
            "description": "price per person"
          },
          "custom_field_values": [],
          "booking_resources": [],
          "addons": [
            { "id": 371942, "name": "Ultimate Hike", "price": 25000, "experience_addon": { "id": 31, "title": "Ultimate Hike" } },
            { "id": 371943, "name": "Lunch", "price": 1000, "experience_addon": { "id": 6515, "title": "Lunch" } }
          ]
        }
      ]
    }
  ],
  "custom_field_values": [
    { "custom_field": { "internal_name": "Team Color" } },
    { "custom_field": { "internal_name": "Shirts Needed" } }
  ],
  "payments": [],
  "subtotal": 23000,
  "total": 24200,
  "paid": 0,
  "due": 24200,
  "total_sales": 24200,
  "products_cnt": 0,
  "addons_cnt": 2,
  "reseller_commission": 0,
  "session_ip_address": "203.0.113.10",
  "session_browser_name": "Chrome",
  "session_browser_os": "Apple",
  "session_location_label": "Denver, Colorado US",
  "created_by_user_avatar": {
    "id": 58,
    "first_name": "Taylor",
    "last_name": "Reed",
    "full_name": "Taylor Reed",
    "abbrev_name": "Taylor R."
  }
}

note_created

note_updated has the same shape. The note sits at the top level, with the whole trip nested under trip.

Webhook payload example
{
  "event": "note_created",
  "id": 177715,
  "text": "Guest requested a 9am pickup instead of 8am.",
  "created_at": "2026-02-27T15:12:00+00:00",
  "user_avatar": { "id": 42, "full_name": "Jamie Ops" },
  "trip": {
    "id": 2088161,
    "confirmation_code": "BOOK-1234",
    "trip_status": { "slug": "reserved", "name": "Reserved" },
    "customer_portal_url": "https://portal.tripworks.com/t/abc123",
    "customer": { "full_name": "Jordan Avery", "id": 5567611 },
    "tripOrders": [
      {
        "id": 2206774,
        "experience": { "id": 105, "name": "Hiking" },
        "status": { "id": 1, "slug": "booked", "name": "Booked" }
      }
    ]
  }
}

payment_created

A payment (or refund) wraps the trip under a trip key.

Webhook payload example
{
  "event": "payment_created",
  "id": 1277113,
  "created_at": "2026-02-26T00:20:05+00:00",
  "amount": 5000,
  "net_amount": 5000,
  "tip": 0,
  "currency": "USD",
  "is_card_present": false,
  "status": { "id": 6, "name": "Successful" },
  "type": { "id": 1, "name": "Cash" },
  "direction": { "id": 1, "name": "Payment" },
  "owner": {
    "id": 58,
    "first_name": "Taylor",
    "last_name": "Reed",
    "full_name": "Taylor Reed"
  },
  "trip": {
    "id": 2086899,
    "confirmation_code": "BOOK-5678",
    "trip_status": { "slug": "reserved", "name": "Reserved" },
    "customer_portal_url": "https://portal.tripworks.com/t/def456",
    "subtotal": 96000,
    "total": 106377,
    "paid": 5000,
    "due": 101377
  }
}

waiver_signed

Webhook payload example
{
  "event": "waiver_signed",
  "id": 1081786,
  "created_at": "2026-02-26T00:27:50+00:00",
  "full_name": "Jordan Avery",
  "first_name": "Jordan",
  "last_name": "Avery",
  "email": "jordan@example.com",
  "phone": "+15550100",
  "dob": "2006-04-14T00:00:00+00:00",
  "is_waiver_adult": true,
  "experience_name": "Swimming",
  "waiver_type": { "id": 2, "name": "Liability Waiver" },
  "signer_category": "lead",
  "booking_id": 5197289,
  "signed_pdf": "https://cdn-images.tripworks.com/tenants/profiles/example/waivers/example.pdf"
}

Match a customer to their trips

Every embedded customer object carries the customer's stable id and code: the numeric TripWorks customer ID and its short code, such as "id": 5567611, "code": "CUST-1A2B". The customer_create and customer_update events send the same identifiers at their root, so you have a durable key to join a customer event to that customer's trips.

The identifiers appear wherever a customer object is embedded:

  • The top-level customer on trip_created, trip_reserved, trip_updated, and trip_cancelled, and the customer nested under each tripOrders[].bookings[].
  • The customer nested under trip on payment_created, booking_updated, and addon_updated.
  • The customer on waiver_signed.

To connect a customer change to their reservation, take the id (or code) from a customer_update event and match it to customer.id on any trip or booking payload you've received. Because every delivery carries its own copy of the customer's id, the match is unambiguous even for a customer with several trips, and you don't have to match on email or phone, which are editable and can be shared across records.

Examples

  • Find the guest's portal link in a booking event: read customer_portal_url on the trip, trip order, or booking, and send it in your own confirmation text.
  • Find what was removed from a trip: compare the trip_updated payload with the copy you stored, because removals arrive as updates with the trip as it now stands.
  • Find the real dollar amount: divide any money field by 100, so 24200 becomes $242.00.
  • Find a waiver signer: read the waiver_signed payload, then match it to the guest's booking in your own system.
  • Find every trip for a customer who just changed: take the id from customer_update and match it to customer.id on the trips you stored.
  • Find a brand new customer: listen for customer_create, which fires when a profile with an email is created.

Frequently asked questions

Is there an envelope around the payload?

No. The object's fields sit at the top level, with an event key added so you can tell events apart.

Why is a money amount ten or a hundred times too big?

Amounts are in integer cents. Divide by 100, so 24200 is $242.00.

Will new fields be added to payloads over time?

It can happen as TripWorks grows. Write your receiver to ignore fields it doesn't recognize instead of rejecting the whole message.

Which event tells me a guest was removed from a trip?

trip_updated. Removals don't have their own event, so compare the new payload with what you stored.

Does the example on the setup screen match what is really sent?

The examples show the real shape with made-up values. Real events carry your own activities, guests, and amounts, and some optional fields appear only when they apply.

Can I get only some events?

Yes. Add a URL only to the events you want. Events with no URL send nothing.

  • Set up webhooks
  • How webhook delivery works
  • Test and troubleshoot webhooks

Built for attractions, tours & activities

Wire TripWorks into everything else

See how attractions, tours, and activities push bookings, payments, and waivers into their own systems in real time on TripWorks. Book a demo and make the switch.

Can't find what you're looking for?

Our team is here to help. Reach out and we'll get back to you as soon as possible.

Contact us →