> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dev.gojinko.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Conversations

> Answer the questions a hotel AI search asks, refine a search with follow-ups, change it while it runs, and know when a conversation expires.

A hotel AI search is a conversation. The traveler can answer a question, add a condition, change the destination or ask for more hotels, and each message builds on what was said before.

## Conversations and tasks

| Id | Prefix | What it is |
| - | - | - |
| `context_id` | `ctx_` | The conversation with one traveler. It keeps the conditions of the search so far: destination, dates, guests, filters, the question asked and the last search. |
| `task_id` | `atk_` | One search in that conversation, with its own `status`. You read, stream and cancel a search by its `task_id`. |

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:

| When the message arrives | What happens |
| - | - |
| A task is waiting for an answer (`input_required`). | The message answers it. The same task continues, with the same `task_id`. |
| A task is still searching (`working`). | That task is canceled, with `superseded_by` set to a new task that handles the message. |
| No task is open. | A new task starts and keeps the conditions of the conversation. |

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 is `input_required`. `message` is the question to show, and `question` says what is missing:

```json theme={null}
{
  "context_id": "ctx_mvinvza31f78f689152a6387",
  "task_id": "atk_mvinvza8b1fe73f848458baa",
  "status": "input_required",
  "question": "checkin_checkout",
  "message": "What are your check-in and check-out dates in Lisbon?",
  "criteria": { "city_name": "Lisbon", "country_code": "PT", "occupancies": [{ "adults": 2, "children_ages": [] }] },
  "notes": []
}
```

| `question` | Asked when | Example `message` |
| - | - | - |
| `destination` | There is no destination, the place cannot be found, the name fits several places and none is clearly meant, or a landmark cannot be located. | `Which city would you like to stay in?` |
| `checkin_checkout` | There is no check-in date, or the dates are in the past. | `What are your check-in and check-out dates in Lisbon?` |
| `children_ages` | Children are mentioned without the age of each child. | `How old are the 2 children?` |
| `guests` | There are fewer adults than rooms; each room needs one adult. | `Each room needs at least one adult, and you asked for 3 rooms with 2 adults. How many adults and rooms?` |
| `checkout` | There is a check-in date but no check-out. The answer also carries hotels for one night, with `reference: true`, as a price reference. | `Here are 20 hotels in Lisbon for Nov 6–7 (1 night, 2 adults, 1 room), as a price reference. What is your check-out date (you arrive Nov 6)?` |

When several things are missing, the search asks for one at a time, in the order of the table.

Send the traveler's answer as `text`, with the same `context_id`:

```bash theme={null}
curl https://api.gojinko.com/v1/hotel_ai_search \
  --header "X-API-Key: $JINKO_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"text": "from November 6 to November 8", "timezone": "Europe/Paris", "context_id": "ctx_mvinvza31f78f689152a6387"}'
```

The same task continues and searches:

```json theme={null}
{
  "context_id": "ctx_mvinvza31f78f689152a6387",
  "task_id": "atk_mvinvza8b1fe73f848458baa",
  "status": "completed",
  "message": "Found 20 hotels in Lisbon for Nov 6–8 (2 nights, 2 adults, 1 room). More are available. Kept from before: Lisbon, 2 adults.",
  "criteria": { "city_name": "Lisbon", "country_code": "PT", "checkin": "2026-11-06", "checkout": "2026-11-08", "occupancies": [{ "adults": 2, "children_ages": [] }] },
  "notes": [{ "kind": "kept", "conditions": ["Lisbon", "2 adults"] }],
  "hotels": ["..."],
  "has_more": true
}
```

You do not send `question` back: the conversation knows what it asked. The traveler can also answer with a whole new request; it is read the same way.

> [!NOTE]
>
> Hotels marked `reference: true` are priced for one night from the check-in, to show prices while the check-out is asked. Ask the check-out before booking the stay.

## Refine the search

Each follow-up answers with a new search that keeps the conversation's conditions and applies the change.

| The traveler says | What changes |
| - | - |
| "with a pool", "4 stars", "with breakfast", "refundable only" | The condition is added, or replaces the earlier value of the same kind. Dates, guests and destination are kept. |
| "Make it Rome instead" | The destination changes. Dates, guests, rooms and filters are kept; a landmark of the old destination is cleared. |
| "without the pool" | The condition is removed. Landmark, star rating, guest rating, budget, board, refundable, brand, facilities and property types can be removed; dates, guests and rooms are changed, not removed. |
| "show more" | The next hotels of the same search, without those already shown: `Here are 20 more hotels.` When there are none left: `There are no more hotels for this search.` |
| "somewhere quieter", "cheaper" | The order of the hotels changes; none is filtered out. The reply then says `sorted by how well they fit: …`. |

`has_more: true` means more hotels match the search; ask for more in the same conversation. There is no page parameter.

### Notes

`notes` lists the assumptions and changes the answer made. `message` already says the same in words.

| `kind` | Fields | Example sentence in `message` |
| - | - | - |
| `kept` | `conditions` | `Kept from before: Paris, from Oct 24, 2 adults, 4 stars or more.` |
| `dropped` | `conditions` | `Dropped: near Louvre.` |
| `default_occupancy` | `adults`, `rooms` | `Guests were set to the default (1 adult, 1 room); tell me if you need to change them.` |
| `ambiguous_destination` | `searched`, `candidates` | `I searched Paris, France; tell me if you meant Paris, Texas, United States instead.` |
| `areas_not_searched` | `places` | `Belém could not be searched; its hotels are not included.` |
| `budget_per_night` | `amount`, `currency` | `Your total budget was applied as at most EUR 300 per night and room.` |
| `budget_by_cheapest_rate` | `amount`, `currency` | `A hotel is within EUR 200 per night and room by its cheapest rate; it can also show rates above that.` |
| `first_stay_of_period` | `start`, `end` | `These are the first dates that fit between Dec 1 and Dec 10; tell me if you prefer others.` |
| `budget_currency` | `currency` | `Prices are in EUR, the currency of your budget.` |
| `star_rating_whole` | `bound` (`min` or `max`), `asked`, `searched` | `Hotel star ratings are whole numbers, so 3.5 stars or more was searched as 4 stars or more.` |
| `requested_hotel` | `name`, `hotel_id` (null when no hotel of that name was found), `available` (null when not found), `within_filters` | `The Hoxton, Shoreditch has no rooms for these dates.` It is the first sentence of `message`. |

## Change the search while it runs

A message sent while a task is `working` replaces it. Reading the first task then shows:

```json theme={null}
{
  "context_id": "ctx_mvinwb3gc054723987d01351",
  "task_id": "atk_mvinwb3j1cf34dee951fc702",
  "status": "canceled",
  "superseded_by": "atk_mvinwbgbd34d5e7c92c823ff"
}
```

Follow the task in `superseded_by`. To stop a search without sending a new message, [cancel it](https://docs.dev.gojinko.com/ai/hotel-search/waiting-for-results.md#cancel-a-search).

## When nothing matches

A search that finds no hotel ends `completed`, with `hotels: []` and a reply that names the filters, for example `No hotel in Paris for Oct 24–25 (1 night, 2 adults, 1 room) matched all of: 4 stars or more, swimming pool. Tell me which condition to relax.` Filters are never widened without the traveler.

A message that is not a hotel request, such as a greeting or a thank-you, also ends `completed`: `Tell me where and when you'd like to stay, and I'll search hotels.` A request for something other than hotels, such as a flight or a booking, answers `I can only search for hotels. To book one, use its offer id with the booking tools.`

## Expiry

A conversation expires 24 hours after its last message.

* A message sent with an expired `context_id` answers `410` `GONE`. Start a new conversation without `context_id`.
* A task that was waiting for an answer ends `failed` with `error.code` `context_expired`.
* Tasks stay readable by `task_id` after the conversation expires.

## Related

* [Hotel AI search](https://docs.dev.gojinko.com/ai/hotel-search/overview.md)
* [Waiting for results](https://docs.dev.gojinko.com/ai/hotel-search/waiting-for-results.md)
* [Statuses and errors](https://docs.dev.gojinko.com/ai/hotel-search/statuses-and-errors.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.