Skip to content

Expanding objects

To keep responses small, related objects are returned as bare id strings rather than full objects. For example, a reservation’s guest is just the guest’s id:

{
"object": "reservation",
"id": "resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ",
"guest": "gst_3Td9Lp0WqZ",
"party_size": 4
}

Use the expand parameter to inline a related object in the same response. Pass multiple relationships as a comma-separated list (?expand=guest,events).

ResourceExpandable relationships
reservationguest, events
guest(none)

Requesting an unknown relationship returns a 400 naming expand in error.param, so a typo never silently ships un-expanded data.

Terminal window
curl "https://api.useservice.app/v1/reservations/resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ?expand=guest" \
-H "Authorization: Bearer $SERVICE_API_KEY"

Now guest is the full guest object:

{
"object": "reservation",
"id": "resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ",
"guest": {
"object": "guest",
"id": "gst_3Td9Lp0WqZ",
"first_name": "Marie",
"last_name": "Dupont",
"email": "[email protected]"
},
"party_size": 4
}

A reservation’s lifecycle activity feed is available inline with expand=events. Without it the events key is omitted; with it you get the same event objects as the dedicated events endpoint, in chronological order — so an ETL can pull a page of reservations and their history in one request instead of one extra call per reservation.

Terminal window
curl "https://api.useservice.app/v1/reservations?expand=events&limit=25" \
-H "Authorization: Bearer $SERVICE_API_KEY"
{
"object": "reservation",
"id": "resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ",
"events": [
{
"object": "reservation_event",
"id": "evt_5pQ…",
"type": "reservation.created",
"created_at": "2026-06-28T19:30:00+02:00"
},
{
"object": "reservation_event",
"id": "evt_7rT…",
"type": "reservation.confirmed",
"created_at": "2026-06-28T19:31:12+02:00"
}
],
"party_size": 4
}
  • Expansion depth is capped at 2 levels. The graph is intentionally shallow, so this is enough to reach a reservation’s guest.
  • On list endpoints, expansion is allowed but page size is reduced. When any expand is present on a list request, the maximum limit is lowered (to 25) to bound the cost of eager-loading. See Pagination.
  • Always-embedded objects. Some related data is small enough that it is always included inline and needs no expand — for example a reservation’s tables (each with its section).

Single-resource GETs return an ETag. Send it back as If-None-Match on the next request; if nothing changed you get a 304 Not Modified with no body, saving bandwidth and a little rate-limit budget.

Terminal window
# First request — note the ETag in the response
curl -i "https://api.useservice.app/v1/reservations/resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ" \
-H "Authorization: Bearer $SERVICE_API_KEY"
# → ETag: W/"resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ-1719515575000000"
# Later — pass it back; unchanged resources return 304
curl -i "https://api.useservice.app/v1/reservations/resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ" \
-H "Authorization: Bearer $SERVICE_API_KEY" \
-H 'If-None-Match: W/"resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ-1719515575000000"'
# → HTTP/1.1 304 Not Modified