An interest holds no stock. A member who takes a week to decide can still lose the
last unit - which is honest, where a silent hold would let one undecided member freeze
inventory indefinitely. Check
availability on the offer to show what is left.Registering an interest
POST /v1/interests takes the offer and, optionally, everything the member already
knows about their plans.
conversationId. That thread is live immediately - pass it to
sendMessage or the SSE stream and the member is talking to a concierge.
string | null
required
The concierge conversation. The redemption that follows inherits it, so this id stays
valid for the whole journey.
Intake | null
required
What the member told us, or
null if they told us nothing yet.Dates are calendar dates
preferredDates and blackoutDates are YYYY-MM-DD strings, not datetimes. A
datetime is rejected rather than parsed: it moves a date across a day boundary for
anyone west of UTC, in the direction that loses the member their first choice.
Preferred dates are stored in the order you send them - first choice first. Up to
five preferred and twenty blackout dates.
Two kinds of intake, handled differently
The three health fields are accepted only on
PUT /v1/interests/{id}/intake, never
on the create. Sending one to POST /v1/interests is refused with
INTAKE_SENSITIVE_INLINE rather than ignored - a create can fail, and details for a
booking that never existed are details we should not have received.
PUT replaces the whole intake, so send the complete answer each time. A partial
merge over a set of dates has no sane meaning - is an omitted preferredDates
“unchanged” or “I have none”?
About phone
Optional, E.164, and stored. It is the only contact detail Expys ever holds for a
member - your platform owns their identity, and we deliberately keep no email address.
contactMethod: "PHONE" is therefore an instruction to you, not to us. We record it
and show it to the concierge team, and we reach the member in chat.
Verifying the phone number
A number is display-only until it is verified. The concierge team will not text an unverified one — a single typo is all it takes to send a stranger somebody else’s itinerary.{ "verified": true | false }. false is not an error — it means
the code was wrong or expired, which is an ordinary thing for somebody to do. Ask again.
We store no code: Twilio generates it and owns its expiry, so there is no column here
holding a one-time code and none to leak one from.
Once verified and with contactMethod: "SMS", concierge messages are relayed by text and
the member can simply reply. Those replies land in the same conversation the app shows —
one thread, two transports.
STOP works, and it is honoured before anything else. A member who texts STOP is
switched to app chat across every booking carrying that number, not just the one they
replied to. START turns it back on.Committing
Pass the interest when you create the redemption:- inherits the interest’s conversation - no second thread is opened, and
redemption.conversationIdis the interest’s id, not the redemption’s - carries the intake across, dates and order included
- closes the interest, so it leaves our concierge queue
interest is optional. Redeeming without one behaves exactly as it always has.