Waggish TravelsDevelopersInteractive API referenceopenapi v2openapi v1

Pagination & idempotency

Cursor pagination

List endpoints (GET /bookings, GET /invoices) return newest first and use cursors.

Query param Default Meaning
limit 25 Page size, 1–100
cursor — The nextCursor from the previous page
{
  "data": [ { "id": "bkg_42", "…": "…" } ],
  "hasMore": true,
  "nextCursor": "42"
}

Loop until hasMore is false:

let cursor;
do {
  const url = new URL("https://searchurtrip.com/api/v1/bookings");
  url.searchParams.set("limit", "100");
  if (cursor) url.searchParams.set("cursor", cursor);
  const page = await (await fetch(url, { headers: { Authorization: `Bearer ${KEY}` } })).json();
  page.data.forEach(process);
  cursor = page.hasMore ? page.nextCursor : undefined;
} while (cursor);

Treat the cursor as opaque. Because pages are keyed on a monotonic id, new bookings created while you paginate never cause duplicates or skipped items.

Idempotency

Networks fail. If a POST /bookings times out you cannot tell whether the booking was created. The Idempotency-Key header makes retrying safe.

POST /api/v1/bookings
Idempotency-Key: 3f0d6a7e-9c5b-4f0a-a1b9-2c1f7c9d5e10
KEY_ID=$(uuidgen)
curl -X POST https://searchurtrip.com/api/v1/bookings -H "Idempotency-Key: $KEY_ID" …   # creates
curl -X POST https://searchurtrip.com/api/v1/bookings -H "Idempotency-Key: $KEY_ID" …   # same booking, Idempotent-Replayed: true

POST /bookings/{id}/cancel is naturally safe to retry: a second cancel returns 409 conflict and changes nothing.