Conversations and tasks
The first message, sent without
context_id, starts a conversation. Its answer carries both ids. Send context_id with every later message of the same traveler; keep one per traveler and conversation.
Where a later message goes depends on the conversation’s open task:
You do not need to send
task_id. When you do, it must belong to the conversation, and it needs context_id: task_id alone answers 422, and a task of another conversation answers 404.
Answer a question
When a search cannot start, the answer isinput_required. message is the question to show, and question says what is missing. Some questions carry question_options, the choices to show:
A request that names no destination is not asked for one: the answer covers several destinations from the origin instead. Always show
message, whatever the value of question.
When several things are missing, the search asks for one at a time. A question runs no search, so its api_usd is 0.
Send the traveler’s answer as text, with the same context_id. With question_options, send the chosen value:
task_id, and searches. While the search runs, the answer is 202 with the early reply:
question back: the conversation knows what it asked. The traveler can also answer with a whole new request; it is read the same way.
Refine the search
Each follow-up answers with a new search that keeps the conversation’s conditions and applies the change. “Show me more” is the exception: it returns more options of the last search.has_more: true means more options of the last search are available; ask for more in the same conversation. There is no page parameter.
When the fares of the remaining options have expired, “show me more” answers with fresh options of the same search. The reply adds The earlier prices had expired; these are searched again now., notes carries repriced, and the new fares have new tokens and a new expires_at.
Notes
notes lists the assumptions made, what could not be done, and what limits the answer. Most notes carry a text to show; message often says the same.
Change the search while it runs
A message sent while a task isworking replaces it. Reading the first task then shows:
superseded_by. To stop a search without sending a new message, cancel it.
When nothing matches
A search that finds no fare within the conditions endscompleted, with no option and a reply that says so, for example No flight was found for Paris → Porto, 10 May 2027, back 17 May 2027, 1 adult, within the conditions asked. Changing a date, an airport or a filter may find some. No filter is relaxed without the traveler.
When the answer covers several destinations, each destination without an option has a per_destination row with option_id: null and an empty_reason, while the other rows keep their options:
When a search could not be completed, for example after a timeout, the answer ends
completed with a not_searched note and The search for Paris → Porto, 10 May 2027, back 17 May 2027 could not be completed. Please send the message again.
A date more than one year ahead is not searched: the answer ends completed with a beyond_booking_horizon note, for example Flights can be booked up to one year ahead (2027-10-26); nothing was searched for 3 Nov 2027, one way.
A request for something other than a flight search also ends completed, with no search, a note out_of_scope and a reply that says what to do instead:
A message that is not a request, such as a greeting or a thank-you, ends
completed with This search finds and prices flights. Tell me where from, where to and when.
Expiry
A conversation expires 24 hours after its last message.- A message sent with an expired
context_idanswers410GONE. Start a new conversation withoutcontext_id. - A task that was waiting for an answer ends
failedwitherror.codecontext_expired. - Tasks stay readable by
task_idafter the conversation expires.
trip_item_token can be added to a trip until its expires_at, at most 75 minutes after the search. See Book a result.
