> ## Documentation Index
> Fetch the complete documentation index at: https://docs.karta.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Sessions

> Create, fetch, and resume sessions - on the flat route family and the agent route family.

A session is the handle a conversation runs on. Create one (or resume an
existing one), then [send messages](/api-reference/messages) to it.

## Create a session

<CodeGroup>
  ```bash Flat (API key) theme={null}
  curl -X POST https://api.karta.sh/v1/sessions \
    -H "Authorization: Bearer $KARTA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"metadata": {"customer_id": "abc123"}}'
  ```

  ```bash Agent (API key) theme={null}
  curl -X POST https://agent.karta.sh/my-org/my-app/v1/sessions \
    -H "Authorization: Bearer $KARTA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{}'
  ```
</CodeGroup>

`POST /v1/sessions`, `POST /{org}/{agent}/v1/sessions`

<ParamField body="metadata" type="object">
  Arbitrary key/values to tag the session with - route and look it up by these
  later. Up to 50 keys.
</ParamField>

<ParamField body="metadata.end_user_id" type="string">
  The verified acting-user key. For per-user kartas, this also becomes the
  durable [karta](/concepts/instances-and-memory) boundary (`user_id` is
  accepted as a legacy alias). On the consumer surface a verified session
  token's subject is authoritative.
</ParamField>

<ParamField body="metadata.agent_instance_id" type="string">
  Optional technical field for naming the durable karta explicitly - for example
  a virtual employee that works with a team, one of several virtual employees,
  or a backend-job karta. Each acting user is still attributed per turn.
  Trusted only from your backend (an API key or a backend-minted token), never
  from public browser metadata.
</ParamField>

<ParamField body="session_id" type="string">
  If supplied and it exists, the session is **resumed** rather than created. A
  `session_id` belonging to another org returns `404`.
</ParamField>

### Response `200`

```json theme={null}
{
  "id": "sess_9f3a...",
  "metadata": { "customer_id": "abc123" },
  "current_agent": "karta-default",
  "status": "active",
  "created_at": "2026-06-01T12:00:00+00:00",
  "updated_at": "2026-06-01T12:00:00+00:00",
  "parent_id": null,
  "pending_input": null,
  "permission_mode": null,
  "participants": []
}
```

The agent route additionally returns an `agent` block with `ref`,
`agent_id`, and `version` (the [release](/concepts/releases) the session is
pinned to).

## Fetch a session

```bash theme={null}
curl https://api.karta.sh/v1/sessions/sess_9f3a... \
  -H "Authorization: Bearer $KARTA_API_KEY"
```

`GET /v1/sessions/{session_id}`,
`GET /{org}/{agent}/v1/sessions/{session_id}`

Returns the session object above. `404` if it does not exist, belongs to another
org, or (on the agent route) the session token is scoped to a different agent -
all shaped identically, so the route is never a tenant oracle.

## List agent sessions

`GET /{org}/{agent}/v1/sessions`

Lists resident sessions for one deployed agent. This is an API-key route for
server-side observability and CLI tooling; session tokens cannot enumerate
sessions.

| Query      | Default | Meaning                                                                 |
| ---------- | ------- | ----------------------------------------------------------------------- |
| `active`   | `false` | When `true`, return only sessions active in the recent activity window. |
| `page`     | `1`     | 1-based page number.                                                    |
| `per_page` | `50`    | Page size, clamped to `1..200`.                                         |

```json theme={null}
{
  "agent": { "ref": "my-app", "agent_id": 123 },
  "page": 1,
  "per_page": 50,
  "total": 1,
  "sessions": [
    {
      "id": "sess_9f3a...",
      "status": "active",
      "message_count": 3,
      "last_message_at": "2026-06-01T12:05:00+00:00",
      "end_user_id": "u_42"
    }
  ]
}
```

## Fetch a transcript

`GET /{org}/{agent}/v1/sessions/{session_id}/messages`

Returns the captured transcript for an agent-route session:

```json theme={null}
{
  "session": { "id": "sess_9f3a...", "status": "active" },
  "messages": [
    { "role": "user", "text": "What roasts do you have?" },
    { "role": "assistant", "text": "We've got Sunrise, Midnight, and Decaf Dusk." }
  ]
}
```

This route requires an API key with `sessions:read` scope. Transcript content is also
controlled by the organization's support-access setting; if transcript access is
disabled, the route returns `403`.

## Stop a session

`DELETE /{org}/{agent}/v1/sessions/{session_id}`

Ends an agent-route session and returns `204`. Use it when your backend knows a
conversation is done and wants Karta to release the active runtime for that
session. A later session using the same durable karta boundary can still resume
the persisted workspace state.

## Resume

Resume by creating with `session_id`, or by fetching the session and sending the
next turn. Conversation history lives in the harness, so a resumed session
continues where it left off. See
[Sessions & participants](/concepts/sessions-and-participants).

## Agent pinning

When a session is created on an agent route, it is pinned to that agent's
active release **version** at creation time. Subsequent turns run against that
pinned version even if a new release is activated mid-conversation - the
[zero-interruption cutover](/deploy/deploy-loop#what-deploy-means-here)
guarantee.

<CardGroup cols={2}>
  <Card title="Send a message" icon="paper-plane" href="/api-reference/messages">
    Send and stream turns into a session.
  </Card>

  <Card title="Authentication" icon="key" href="/api-reference/authentication">
    Which credential works on which route family.
  </Card>
</CardGroup>
