Skip to content
Get an API key

Build

Updated

Conversations

Create a conversation, label it with metadata, read and edit the items in it, and hand its id to a response.

A conversation is the history the API keeps for you. Every response belongs to one, so a later turn sends only the new input rather than replaying what came before.

You do not have to create one. A plain POST /v1/responses keeps your history for you, and previous_response_id continues it. Create one yourself when you want to hold its id, label it, seed it with turns that happened somewhere else, or read its history back.

The Node and Python examples use a client set up for this API.

Terminal window
curl https://api.helping.io/v1/conversations \
-H "Authorization: Bearer $HELPINGIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"metadata": {"customer": "acme"}}'
{
"id": "conv_…",
"object": "conversation",
"created_at": 1758330000,
"metadata": { "customer": "acme" }
}

created_at is in seconds since the Unix epoch. metadata is always present; a conversation with no labels reports {}.

You can seed the conversation at the same time by passing items, up to 20 of them. See Items.

Creating a conversation, updating its metadata and adding items all honor the Idempotency-Key header, with the same rules as creating a response. A retry with the same key and the same body returns the first answer and stores nothing new, so seeded items never appear twice. The same key with a different body is a 409. Each of the three keeps its own keys, and a key is remembered for 24 hours. See Idempotency.

A retry answers with the conversation as it is now, not a copy of the first answer: if its metadata changed since, the retry shows the change. A retry of adding items answers with the items that request added, leaving out any you have removed since. A retry of creating or updating a conversation that it cannot read, because the conversation has been deleted since or because the retry came from a different API key, is a 409 with the code idempotency_conflict. A retry of adding items to a conversation deleted since is a 404, the answer any request naming that conversation gets.

Pass its id as conversation. The conversation’s items are the context for the response, and the response’s input and output are added to it.

Terminal window
curl https://api.helping.io/v1/responses \
-H "Authorization: Bearer $HELPINGIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-5",
"input": "What did I ask you first?",
"conversation": "conv_…"
}'

conversation also accepts the object form, {"id": "conv_…"}. The response comes back carrying "conversation": {"id": "conv_…"}, so you can read the id off the response instead of tracking it yourself. A request that names no conversation gets "conversation": null, matching the OpenAI API.

A conversation your key did not create, one that does not exist, and one you have deleted are all the same 404. A conversation is never created implicitly by naming it: a stale id is an error rather than a fresh, empty history.

The first response on a conversation you created needs a model, exactly like any first turn. After that the conversation keeps its model, and later turns may omit it.

Terminal window
# read
curl https://api.helping.io/v1/conversations/conv_… \
-H "Authorization: Bearer $HELPINGIO_API_KEY"
# replace the labels
curl https://api.helping.io/v1/conversations/conv_… \
-H "Authorization: Bearer $HELPINGIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"metadata": {"customer": "globex"}}'
# delete
curl -X DELETE https://api.helping.io/v1/conversations/conv_… \
-H "Authorization: Bearer $HELPINGIO_API_KEY"

An update replaces metadata rather than merging into it. Send the whole map, or {"metadata": {}} to clear it. metadata is required: an update without it is a 400.

A delete answers {"id": "conv_…", "object": "conversation.deleted", "deleted": true}. The conversation and its history stop being readable and it can no longer be continued. Deleting the same conversation twice is not an error.

Its content (messages, the model requests and responses, tool inputs and outputs, stored outputs and attached files) is erased 30 days after the delete. Deleting a conversation does not remove what you were charged or the record of the calls that produced it. Your spend history and invoices are unaffected.

Rule Limit
Pairs per conversation 16
Key length 64 characters
Value length 512 characters
Value type string

Anything outside these is a 400 naming the rule it broke. Metadata is stored for you to read back; no route filters or searches on it, and it is never sent to a model.

The items of a conversation are its turns: the messages, the tool calls, the tool results and the reasoning that make up its history.

Terminal window
curl "https://api.helping.io/v1/conversations/conv_…/items?limit=20" \
-H "Authorization: Bearer $HELPINGIO_API_KEY"
{
"object": "list",
"data": [{ "type": "message", "id": "msg_…", "role": "user", "status": "completed", "content": [{ "type": "input_text", "text": "hello" }] }],
"has_more": false,
"first_id": "msg_…",
"last_id": "msg_…"
}
Parameter Meaning
limit Items per page, 1 to 500. Defaults to 20
order asc for oldest first, the default, or desc
after Continue after this item. Pass the previous page’s last_id
include reasoning.encrypted_content to include reasoning payloads

include is accepted repeated (include=a&include=b), bracketed (include[]=a), or comma separated, and it works the same way on the single-item read and when adding items. A value this API does not define is a 400 naming it, so a request that asks for something unavailable is told rather than answered as though it had asked for nothing.

An item that is stored but could not be read is left out of data and named in helpingio:unreadable by its id. The rest of the page is returned, it still counts toward has_more and can be the page’s last_id, and retrieving it returns the item_unreadable error.

after is exclusive, so no item appears on two pages. An after that names no item in this conversation is a 400 rather than an empty page, so a client never mistakes a bad cursor for the end of the history.

Up to 20 per call. This is how you hand the API a conversation that started somewhere else.

Every item you add is stored whole and reads back exactly as you sent it. What the next response’s model sees is less than that, and how much less depends on the kind, so the table below says it per kind rather than promising one rule.

Terminal window
curl https://api.helping.io/v1/conversations/conv_…/items \
-H "Authorization: Bearer $HELPINGIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{"type": "message", "role": "user", "content": "What is the capital of France?"},
{"type": "message", "role": "assistant", "content": "Paris."}
]
}'

The answer is the items you just added, in an item list.

Unlike the input of a response, items here may carry the assistant, system and developer roles, and may be function_call, function_call_output or reasoning items. An item reference is a 400, here and when you create the conversation with items: send the item itself.

Item you add What the next response’s model sees
message with role user or assistant The text, as that role
message with role system or developer The text, but as a user turn rather than as an instruction. To steer the model, send instructions on the response
function_call paired with its function_call_output A real tool call and its result, with the tool’s name and the correlation between them intact
function_call with no matching output, or an output with no call Nothing. A call with no result asks the model to answer something the history does not contain, and a result with no call refers to nothing
reasoning Nothing. It is stored and reads back in full, and no part of it is sent. If the model needs what the reasoning concluded, add that as an assistant message

Apart from a paired tool exchange, the text of an item is what reaches the model. An item carrying an image, file or video part is refused with a 400 naming it, because media input is not supported.

Terminal window
curl https://api.helping.io/v1/conversations/conv_…/items/msg_… \
-H "Authorization: Bearer $HELPINGIO_API_KEY"
curl -X DELETE https://api.helping.io/v1/conversations/conv_…/items/msg_… \
-H "Authorization: Bearer $HELPINGIO_API_KEY"

A delete answers with the conversation, not a deleted-object shape.

Two kinds of thing in a conversation are absent from the list:

  • A tool call that failed on our side. The response that made the call reports the failure as a function_call_output carrying helpingio:error (When this API refuses a call), but the conversation’s item list does not show it.
  • Response lifecycle. Whether a response started, finished, failed or was canceled is on the response object, not in the conversation’s items.