Prefer Swagger UI? Click hereThe same API in the classic OpenAPI explorer.
POST/v1/threads/{thread_id}/runs

Runs

Execute an Assistant against a Thread: the model reads the thread, optionally calls tools, and writes its reply back as a new message. Stream the events over SSE or poll the run until it reaches a terminal status. When the assistant calls one of your function tools the run pauses at requires_action and waits for you to submit_tool_outputs.

Request
HTTP
POST
URL
/v1/threads/{thread_id}/runs
Auth
api_key
Try it
# start a run (polling style)
curl https://api.fightclub.pro/v1/threads/thread_abc/runs \
  -H "Authorization: Bearer $FC_API_KEY" -H "Content-Type: application/json" \
  -d '{"assistant_id":"asst_xyz"}'
# => { "id":"run_...", "status":"queued", ... }  then poll GET the run

# if status=requires_action, answer the tool calls
curl https://api.fightclub.pro/v1/threads/thread_abc/runs/run_123/submit_tool_outputs \
  -H "Authorization: Bearer $FC_API_KEY" -H "Content-Type: application/json" \
  -d '{"tool_outputs":[{"tool_call_id":"call_1","output":"{\"ok\":true}"}]}'

Example response

{
  "id": "run_6Aa9",
  "object": "thread.run",
  "created_at": 1782300000,
  "thread_id": "thread_5Yz8",
  "assistant_id": "asst_4Tn7",
  "status": "completed",
  "model": "openai/gpt-4o-mini",
  "tools": [ { "type": "file_search" } ],
  "usage": { "prompt_tokens": 820, "completion_tokens": 96, "total_tokens": 916 }
}

A representative 200 body. Ids and timestamps are illustrative.

Body parameters

NameTypeDefaultDescription
assistant_id*stringThe assistant (asst_*) to run against this thread.
modelstringoptionalOverride the assistant model for this run.
instructionsstringoptionalReplace the assistant instructions for this run only.
additional_instructionsstringoptionalAppend to the assistant instructions for this run only.
additional_messagesarrayoptionalExtra messages appended to the thread before the run starts.
toolsarrayoptionalOverride the assistant tools for this run. Attach stores here: [{ type:"file_search", file_search:{ vector_store_ids:["vs_..."] } }].
tool_choicestring | objectoptionalauto | none | required, or force a specific tool.
temperaturenumberoptionalSampling temperature for this run, 0-2.
top_pnumberoptionalNucleus sampling for this run, 0-1.
response_formatstring | objectoptionalauto or a json_schema to force structured output for this run.
metadataobjectoptionalFree-form metadata on the run.
streambooleanfalseStream run + message-delta events as SSE instead of polling.

* required.

Response fields

NameTypeDescription
idstringRun id (run_*).
objectstring"thread.run".
created_atintegerUnix timestamp.
thread_idstringThe thread this run executes on.
assistant_idstringThe assistant being run.
statusstringqueued | in_progress | requires_action | cancelling | cancelled | completed | failed | expired.
required_actionobject | nullWhen status=requires_action: { type:"submit_tool_outputs", submit_tool_outputs:{ tool_calls:[...] } }.
last_errorobject | nullOn failure: { code, message }.
usageobject | null{ prompt_tokens, completion_tokens, total_tokens }, set on completion.
modelstringThe model that ran.
started_at / expires_at / completed_at / cancelled_at / failed_atinteger | nullLifecycle timestamps as they occur.

Errors

  • 401missing_tokenNo Authorization header was sent.
  • 401invalid_auth_schemeThe scheme was neither Bearer nor Client.
  • 401invalid_token_formatA Bearer token not prefixed ko_.
  • 401invalid_tokenThe API key is unknown, revoked or expired.
  • 403insufficient_scopeThe key is valid but lacks the required scope.
  • 400invalid_assistant_idassistant_id is missing or malformed.
  • 400invalid_additional_messagesadditional_messages is malformed.
  • 400invalid_modelmodel override is not a valid ref.
  • 400invalid_tool_call_idsubmit_tool_outputs referenced an unknown tool_call_id.
  • 409thread_lockedA run is already active on this thread.
  • 409run_not_in_requires_actionsubmit_tool_outputs called when the run is not waiting for tools.
  • 409run_already_completedcancel called on a run that already reached a terminal status.
  • 404not_foundNo such thread, assistant or run (also cross-tenant).

See the full error reference.

Related routes

GET/v1/threads/{thread_id}/runsList runs on a thread.
GET/v1/threads/{thread_id}/runs/{run_id}Retrieve a run (poll its status).
POST/v1/threads/{thread_id}/runs/{run_id}Modify run metadata.
POST/v1/threads/{thread_id}/runs/{run_id}/cancelCancel a queued/in-progress run (409 run_already_completed if terminal).
POST/v1/threads/{thread_id}/runs/{run_id}/submit_tool_outputsAnswer the tool calls: { tool_outputs:[{ tool_call_id, output }] }. Supports stream:true.

Notes

  • ·The run loop: create a run -> if status=requires_action, read required_action.submit_tool_outputs.tool_calls, execute them, POST submit_tool_outputs -> repeat until status=completed.
  • ·Only one run can be active on a thread at a time (the thread is locked while it runs).
  • ·Stream:true emits run lifecycle + message-delta events over SSE; otherwise poll GET the run.
  • ·Spend lands on the customer named in the thread metadata, if any.

Examples