Search guests — one result per human
const url = 'https://quikstik-core.fly.dev/guests?q=example&limit=20';const options = { method: 'GET', headers: { 'x-tenant-id': '2489E9AD-2EE2-8E00-8EC9-32D5F69181C0', Authorization: 'Bearer <token>' }};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://quikstik-core.fly.dev/guests?q=example&limit=20' \ --header 'Authorization: Bearer <token>' \ --header 'x-tenant-id: 2489E9AD-2EE2-8E00-8EC9-32D5F69181C0'A guest is not a row: identity is spread across persons, booking buyers
(commerce_obligations.notify_*), thread counterparties and prospects. Every hit is grouped
by lower(email) — the join key — with fallbacks person:{person_id} (a person
with no email) and booking:{obligation_ref} (a booking with neither). The text decides the
leg: QS- + 4–8 hex digits (confirmation number) or VIA-/GET- + digits (channel code) →
reference; contains @ → email (exact, case-insensitive); at least 7 digits once spaces,
-, (, ), . and + are stripped → phone (suffix match, so country-code variants
hit); anything else → name (person display name) and text (buyer name/email, rider
names; the booking search needs 3+ characters).
bookings_count, the departure stamps and the balance count active (non-cancelled)
bookings only. currency is null when the guest has no priced booking (the balance is then
0). Order: exact email/reference matches first, then next_departure_at_ms ascending
(none last), then last_departure_at_ms descending. limit is clamped to 1..50.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Tenant identifier (UUID).
Authn/authz semantics are intentionally TBD for this contract slice; this header exists to keep the contract explicitly multi-tenant from day 0.
Query Parameters
Section titled “Query Parameters”What the operator has — a surname, email, phone or reference. At least 2 characters.
Maximum guests returned; values outside 1..50 are clamped.
Responses
Section titled “Responses”The matching guests (possibly none).
object
object
Stable id: lower-cased email, person:{uuid} or booking:{uuid}.
Person’s name, else the most recent booking’s buyer name, else the email’s local part, else the booking reference.
Lower-cased join key.
As the buyer gave it (newest booking with one), else a thread’s counterparty phone.
Active (non-cancelled) bookings.
Earliest active departure at or after now.
Latest active departure before now.
Sum of gross − settled over active bookings in currency, minor units.
ISO 4217 code; null when the guest has no priced booking.
Threads in state awaiting_us.
Hub sends held for a human on this guest’s threads.
Latest inbound or outbound stamp across the guest’s threads.
The strongest leg that found this guest.
Example
{ "guests": [ { "match": "reference" } ]}Missing or invalid session bearer token
object
Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).
Example
{ "reason": "sold_out"}The session’s effect authority does not cover this operation
object
Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).
Example
{ "reason": "sold_out"}q is shorter than 2 characters (reason query_too_short) or limit is not an integer (reason bad_limit).
object
Stable machine-readable error code
Human-readable explanation (never leaks SQL, URLs, or secrets)
Example generated
{ "code": "example", "message": "example"}No durable backend is wired for this operation (fail-closed)
object
Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).
Example
{ "reason": "sold_out"}