Expanding objects
Related objects are ids by default
Section titled “Related objects are ids by default”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}Expanding
Section titled “Expanding”Use the expand parameter to inline a related object in the same response. Pass
multiple relationships as a comma-separated list (?expand=guest,events).
What you can expand, per resource
Section titled “What you can expand, per resource”| Resource | Expandable relationships |
|---|---|
reservation | guest, events |
guest | (none) |
Requesting an unknown relationship returns a 400 naming expand in
error.param, so a typo never silently ships un-expanded data.
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", }, "party_size": 4}Expanding events
Section titled “Expanding events”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.
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}Rules and limits
Section titled “Rules and limits”- 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
expandis present on a list request, the maximumlimitis 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’stables(each with itssection).
Caching with ETags
Section titled “Caching with ETags”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.
# First request — note the ETag in the responsecurl -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 304curl -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