POST /chat/completions call is one turn. To hold a conversation — ask a follow-up, refine a draft, react to what the model said — you continue the same chat across turns by passing its chat_id.
How it works
Every completion returns achat_id in its result envelope. Pass that value back as chat_id on your next request and the new message is appended to the same conversation:
State lives on the server
Conversation state is stored server-side and reconstructed for you on every turn. Send only the new message (plus any newfile_ids) — never re-send prior turns.
In particular, you do not echo back anything the API returned to you:
- Files stay attached. A file you sent with
file_idson an earlier turn remains available; you don’t re-attach it. - Generated outputs are remembered. Documents, emails, and diagrams returned on
result.documents/result.emails/result.diagramsare already persisted to the chat. The model can refer to and build on them without you sending them back. Those response fields are there for your convenience — to download or display — not state you must round-trip.
One turn at a time
Each turn runs as an async job. Only one turn may be in flight per chat: if you send a new message while a prior turn is stillpending or running, the request is rejected with 409. Wait for the prior turn to reach a terminal state (succeeded / failed) before sending the next.
This prevents two turns from racing on the same message history. If you long-poll (wait > 0) you’ll usually have the result before you send the next turn; with fire-and-forget (wait=0) poll GET /jobs/{id} until the turn is terminal first.
Who can continue what
Continuing a chat is scoped exactly like materialization, and only API-created chats can be continued:| Key type | Can continue |
|---|---|
Personal (u:gcai_…) | Only chats it created. |
Organization (gcai_…) | Only chats created by other organization-scoped keys. |
chat_id that doesn’t exist (or that this key can’t reach) returns 404; a chat owned by a different scope returns 403; a chat that wasn’t created through the API returns 409.
Continuing a chat does not materialize it — the conversation stays headless until you explicitly materialize it.
Related
- Create a Chat Completion: each turn; returns the
chat_id. - Chat Visibility: why API chats stay headless and how ownership scoping works.
- Asynchronous Requests: the job envelope, waiting, and polling.