List reservations with filtering
Reservations · GET /v1/reservations
List reservations with filtering
/v1/reservationsRequest
curl https://api.repull.dev/v1/reservations?limit=50 \ -H "Authorization: Bearer $REPULL_API_KEY"
Response
{
"data": [
{
"id": "123",
"listingId": "123",
"guestId": "123",
"checkIn": "2026-06-01",
"checkOut": "2026-06-01",
"status": "confirmed",
"source": "airbnb",
"platform": "airbnb",
"confirmationCode": "Example text",
"totalPrice": "Example text",
"currency": "USD",
"guestDetails": {
"numberOfPets": 0,
"numberOfAdults": 0,
"numberOfGuests": 0,
"numberOfInfants": 0,
"numberOfChildren": 0
},
"primaryGuest": {
"id": "123",
"firstName": "Example",
"lastName": "Example",
"phone": "+15550000000",
"language": "Example text"
},
"occupancy": {
"adults": 0,
"children": 0,
"infants": 0,
"pets": 0,
"total": 0
},
"financials": {
"totalPrice": 0,
"currency": "USD",
"paymentStatus": "pending",
"cancellationPolicy": "Example text",
"host": {
"accommodation": 0,
"discounts": [],
"guestFees": [
{
"name": "Example",
"type": "guest_service",
"amount": 0,
"vat": 0
}
],
"hostFees": [
{
"name": "Example",
"type": "host_service",
"amount": 0,
"vat": 0
}
],
"taxes": [],
"revenue": 0
},
"guest": {
"totalPrice": 0,
"fees": [
{
"name": "Example",
"type": "cleaning",
"amount": 0
}
],
"taxes": []
}
},
"createdAt": "2026-06-01T12:00:00.000Z",
"updatedAt": "2026-06-01T12:00:00.000Z",
"bookedAt": "2026-06-01T12:00:00.000Z",
"guestName": "Example"
}
],
"pagination": {
"nextCursor": "eyJpZCI6MTIzfQ==",
"hasMore": true,
"total": 0
}
}Captured from a real response. Regenerated on every release, and CI fails if this shape stops matching the API.
Query Parameters
limitintegerPage size (max 100). Requests over the cap return 422.
cursorstringOpaque cursor returned in the previous response's `pagination.nextCursor`. Omit to fetch the first page.
offsetintegerFirst-class alias for cursor-based pagination. Mutually exclusive with `cursor` — passing both returns 422. Accepts integers in `[0, 10000]`; deeper walks must use `cursor` (constant per-page cost). The response always includes `pagination.nextCursor` so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying.
platformstringFilter by booking platform
statusstringFilter by lifecycle status. **Case-insensitive** — `confirmed`, `Confirmed`, and `CONFIRMED` all match. Each public value expands to the full set of internal sub-states server-side: `confirmed` matches `accept`/`confirmed`/`modified`, `cancelled` matches every cancellation sub-state (`cancelled_by_host`, `declined`, `expired`, etc.), `pending` includes `inquiry`/`awaiting_payment`. `completed` is a derived state — combine `status=confirmed` with `check_out_before=<today>` to filter for past stays.
listingIdintegerFilter to a single listing
check_in_afterdateCheck-in date >= this value
check_in_beforedateCheck-in date <= this value
check_out_afterdateCheck-out date >= this value
check_out_beforedateCheck-out date <= this value
checkInFromdateDeprecated alias for `check_in_after`.
checkInTodateDeprecated alias for `check_in_before`.
checkInAfterdateUse `check_in_after` (snake_case) instead.
checkInBeforedateUse `check_in_before` (snake_case) instead.
checkOutAfterdateUse `check_out_after` (snake_case) instead.
checkOutBeforedateUse `check_out_before` (snake_case) instead.
updated_sincedateIncremental sync: return only records whose `updatedAt` is at or after this instant. This is the only filter on record **mutation** time — every `check_*` filter targets guest **stay** dates. **Accepted formats.** ISO 8601, with `Z` or a numeric offset — both work: - `2026-08-01T00:00:00Z` - `2026-08-01T00:00:00.123Z` - `2026-08-01T00:00:00+00:00` - `2026-08-01T02:30:00-07:00` (offset colon optional: `-0700`) - `2026-08-01T00:00` (seconds optional) - `2026-08-01T00:00:00` — no zone designator, interpreted as **UTC** - `2026-08-01` — date only, means midnight UTC Anything else returns 422 `invalid_params` naming the field; the value is never silently ignored. **Ordering changes when you pass this.** Results are ordered `updatedAt ASC, id ASC` (instead of the endpoint default) and the cursor keys on the same pair. That is required for correctness: under the default ordering a record amended mid-walk can move behind the cursor and never be emitted — which is exactly the event you are polling for. Ascending mutation time is monotonic with the cursor, so anything touched during a walk resurfaces later in it or on the next poll. **Cursors are not interchangeable between the two orderings.** Keep `updated_since` on every page of an incremental walk; replaying a cursor from the other ordering returns 422 rather than a page that silently skips rows. **Watermark.** The bound is inclusive (`updatedAt >= value`), so the last row of the final page is the watermark for the next poll — re-polling with it re-emits that row. Delivery is at-least-once; upsert by `id`.
include_totalbooleanWhen `true` (default), the response's `pagination.total` carries the count of rows matching the current filter, across all pages. Pass `false` to skip the count for very large workspaces where the per-page COUNT(*) cost matters.