リファレンスHTTP APISession control

Finish the session: drain, checkpoint, close for good

POST
/v1/sessions/{id}/close

Ends a session whose work is done. Unlike terminate, nothing is killed: the running turn finishes, its checkpoint commits, and the session ends closed, which nothing reopens. Unlike a recovery close (POST /v1/sessions/{id}/recovery-decisions, decision: close), it is the owner's call on a healthy session, needs sessions:control rather than sessions:recover, and its receipt operation is close rather than recovery_decision. The API guide compares the three.

  • active with a live worker: the worker drains as for a pause and the session goes closing. The receipt stays accepted until the execution is observed gone with a checkpoint covering every turn that ran; then the session is closed and the receipt succeeded. A drain over 60 seconds shows attention.code: CLOSE_BLOCKED with the reason; nothing is killed for it. An open question or approval holds the close until it is answered or the turn interrupted. If the drain cannot commit, the receipt fails and the session goes back to active (or recovery_required for a turn whose outcome is unknown), with its queued input intact; a terminate overtakes it (CONTROL_SUPERSEDED).
  • active with no live worker, paused, or a stopped session that can be resumed: closed in this request. With an execution still bound the receipt is accepted until it is observed gone; otherwise succeeded in the response.

Queued input is cancelled in the transaction that closes the session (each input's receipt fails with SESSION_CLOSED). Push requests are left alone; request a push of the result after the close has succeeded, since a push requested inside the last turn is refused CHECKPOINT_MOVED once the close commits that turn's checkpoint. The receipt result is {resulting_admission_state, checkpoint_revision, cancelled_turn_count}. The stream carries a status event for closing and for closed, and a system event {subtype: session_closed, closed_by: close, close_receipt_id, checkpoint_revision, cancelled_turn_count}. A caller closing its own session from inside a turn must not wait on the receipt: the drain waits for that turn to end. After the close, messages and controls answer 409 SESSION_CLOSED.

Scope: sessions:control (API key or cookie session). Idempotency-Key: required.

Authorization

headerAuthorizationBearer <token>

For servers and scripts: an API key sent as an HTTP bearer token, Bearer <key>. It holds exactly the scopes it was issued with; a key issued before scopes existed holds none. It never needs the CSRF header, and it cannot manage agents, members, teams or API keys. Issue one in the web console under Settings → API keys; each operation names the scope it needs.

Scope: sessions:control

Path Parameters

id*string

The session's id.

Match^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
Formatuuid

Header Parameters

Idempotency-Key*string

Required, 1–255 characters; a UUID per user intent works. A retry with the same key and the same body returns the original response and runs the command once; the same key with a different body answers 409 IDEMPOTENCY_CONFLICT. A missing or invalid key answers 400 BAD_REQUEST, after the body is read.

Length1 <= length <= 255
X-Requested-With?"werft-web"

Required with a cookie session: the literal werft-web.

Value in"werft-web"

Request Body

application/json
  1. body
expected_revision*integer
Range0 <= value <= 2147483647
reason?string
Length1 <= length

Response Body

The close is stored (accepted), or the session had nothing to wait on and is closed already (succeeded).

application/json
  1. response
receipt_id*string
Match^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
Formatuuid
receipt_status*string
Value in"accepted""succeeded""failed""unknown"
Example Request
curl -X POST 'https://example.com/v1/sessions/497f6eca-6276-4993-bfeb-53cbbbba6f08/close' \  -H 'Idempotency-Key: string' \  -H 'Content-Type: application/json' \  -d '{  "expected_revision": 7,  "reason": "Work is done"}'
Example Response
{  "receipt_id": "c4a1e9d2-7b3f-4e8a-a6c5-1d2e3f4a5b6c",  "receipt_status": "accepted"}