Ingram Cloud

Documentation

Conversations

Conversations

A conversation is a first-class, listable handle on a thread of runs: create one, drive turns inside it, and read its transcript back — so an in-app chat tab gets a history list, titles, and delete without storing any of that yourself. It maps onto the OpenAI Conversations API, so the openai client library talks to it unchanged.

A conversation is independent of memory. Memory is durable facts a smith carries across every conversation; a conversation is one thread of turns. A conversation works whether or not the smith has any memory, and deleting one never touches memory.

The object

{
  "id": "cnv_7Yh…",
  "object": "conversation",
  "created_at": 1718900000,
  "updated_at": 1718900042,
  "title": "What did I spend on travel in May?",
  "smith_id": "smt_3xK…",
  "metadata": {}
}

created_at / updated_at are unix seconds (every OpenAI object is). title, smith_id, and updated_at are Ingram Cloud extensions — OpenAI's object has no title and no list endpoint, both of which a console history list needs. title is null until you run inside the conversation over the Responses API (passing its id as conversation), which auto-sets it from the first user message; set it yourself any time.

A conversation belongs to one smith. A smith token acts on its own conversations; a tenant-admin token names the smith with an IC-Smith-Id header.

Create one

# Authorization: smith token (browser-safe, scoped to one smith)
curl https://api.cloud.ingram.tech/v1/conversations \
  -H "Authorization: Bearer $IC_SMITH_TOKEN" \
  -H "IC-Api-Version: 2026-05-01" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Travel spend" }'

title and metadata are both optional — POST /v1/conversations with an empty body mints an untitled conversation you can run in straight away.

Run inside it

Pass the cnv_ id as conversation on the Responses API. You send only the new input; Ingram Cloud replays the conversation's prior turns for the model, stamps the run onto the conversation, and auto-titles it from the first user turn.

# Authorization: smith token (browser-safe, scoped to one smith)
curl https://api.cloud.ingram.tech/v1/responses \
  -H "Authorization: Bearer $IC_SMITH_TOKEN" \
  -H "IC-Api-Version: 2026-05-01" \
  -H "Content-Type: application/json" \
  -d '{ "model": "", "conversation": "cnv_7Yh…",
        "input": "What did I spend on travel in May?" }'

You can also drive the same thread over Chat Completions by passing the cnv_ id as IC-Thread-Id — history replay, the activity stamp, and auto-titling all work the same. Both hold in the client-tool loop too: a stateful turn that sends tools still lands on the conversation, tool steps and all.

Only one turn runs at a time, and the limit is the smith, not the conversation — running in a second conversation while the first is still going returns 400 conversation_locked. See one run at a time.

Read the transcript

GET /v1/conversations/{cnvId}/items returns the conversation's transcript, reconstructed from its runs, in OpenAI's list envelope — oldest first, or ?order=desc for newest first. When has_more is true, pass the page's last_id as ?after= to fetch the next page. The transcript is faithful to the run: alongside message items it carries the tool steps, so a chat UI can re-render a turn in full on reload —

  • function_call / function_call_output — a client-side tool the model asked you to run and the result you sent back (call_id, name, arguments, output).
  • mcp_call — a tool the run loop executed server-side for you (name, arguments, output, server_label).
{
  "object": "list",
  "data": [
    { "id": "run_9…​.i0", "type": "message", "role": "user",
      "status": "completed",
      "content": [{ "type": "input_text", "text": "What did I spend on travel in May?" }] },
    { "id": "run_9…​.mcp0", "type": "mcp_call", "status": "completed",
      "server_label": "ingram-cloud", "name": "search_expenses",
      "arguments": "{\"month\":\"May\"}", "output": "{\"total\":412}" },
    { "id": "run_9…​.o", "type": "message", "role": "assistant",
      "status": "completed",
      "content": [{ "type": "output_text", "text": "€412 across 3 trips." }] }
  ],
  "first_id": "run_9…​.i0",
  "last_id": "run_9…​.o",
  "has_more": false
}

Items are read-only — they accrue from the runs you drive over the Responses API; there is no write-item endpoint. Item ids are opaque and stable.

List, rename, delete

# List — newest first, in OpenAI's list envelope; page by passing last_id as ?after=
curl "https://api.cloud.ingram.tech/v1/conversations?limit=20" \
  -H "Authorization: Bearer $IC_SMITH_TOKEN" -H "IC-Api-Version: 2026-05-01"

# Rename (or merge metadata)
curl https://api.cloud.ingram.tech/v1/conversations/cnv_7Yh… \
  -H "Authorization: Bearer $IC_SMITH_TOKEN" -H "IC-Api-Version: 2026-05-01" \
  -H "Content-Type: application/json" -d '{ "title": "May travel" }'

# Delete — removes the handle; the underlying runs are untouched
curl -X DELETE https://api.cloud.ingram.tech/v1/conversations/cnv_7Yh… \
  -H "Authorization: Bearer $IC_SMITH_TOKEN" -H "IC-Api-Version: 2026-05-01"

Delete returns the OpenAI { "id": …, "object": "conversation.deleted", "deleted": true } acknowledgement.

Scopes

conversations:read for GET; conversations:write for create, update, and delete. A smith token carries the scopes minted into it; see Auth & tokens.