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

# Agent API reference

> Endpoints, request and response shapes, errors, and billing for the Agent API.

All endpoints live under `https://api.higgsfield.ai/v1/agent` and use the standard `Authorization: Key {key_id}:{key_secret}` header. Requests and responses are JSON.

The [Python and TypeScript v2 SDKs](/docs/how-to/sdk#agent-api) wrap this surface as `client.agents.sessions` / `client.agents.media`. See the [quickstart](/docs/agent/quickstart#use-the-sdk) for installation and usage; the reference below is the raw HTTP contract.

## Create a session

`POST /v1/agent/sessions` → `201`

```json theme={"dark"}
// Request (all fields optional)
{ "config": {} }

// Response
{ "session_id": "50eeb94c-c396-439d-b504-aee2147b7ec0", "status": "idle" }
```

Sessions are durable and keep conversation memory across turns. Create one session per logical conversation or workflow and reuse it.

## Send a message

`POST /v1/agent/sessions/{session_id}/messages` → `202`

```json theme={"dark"}
// Request
{ "content": "Generate a 10-second teaser video for..." }

// Response
{ "message_id": "4bf91fcb-abb3-44f4-815c-a74dda7817d3", "status": "processing" }
```

`content` is plain text, 1–20,000 characters. The turn runs asynchronously — poll for the result.

One turn runs per session at a time. A message sent while a turn is in flight returns `409 session_busy`; the losing request is not charged. Retry after the current turn finishes, or interrupt it.

## Read messages

`GET /v1/agent/sessions/{session_id}/messages` → `200`

Optional query parameter `after={message_id}` returns only messages created after that message — use it to poll incrementally.

```json theme={"dark"}
{
  "status": "idle",
  "messages": [
    {
      "message_id": "…",
      "role": "user",
      "status": "completed",
      "message": { "type": "text", "text": "…" },
      "created_at": "2026-09-01T14:37:53.000Z"
    },
    {
      "message_id": "…",
      "role": "assistant",
      "status": "completed",
      "message": { "id": "…", "role": "assistant", "parts": [ { "type": "text", "text": "…" } ] },
      "created_at": "2026-09-01T14:38:41.000Z"
    }
  ]
}
```

* Top-level `status` is the session status: `idle`, `processing`, or `awaiting_input`.
* Message `status` is `processing`, `completed`, or `failed`.
* A user message settles to `completed` or `failed` together with the assistant message that answers it.
* The assistant `message` is structured; concatenate its `parts` entries with `"type": "text"` for the answer text. Other part types (reasoning, tool activity) may appear and can be ignored.

Poll with backoff: start at two seconds, increase gradually to ten, and stop when the assistant message for your turn is terminal. See [Polling](/docs/concepts/polling) for the general strategy.

## Interrupt a turn

`POST /v1/agent/sessions/{session_id}/interrupt` → `202`

```json theme={"dark"}
{ "session_id": "…", "status": "processing" }
```

Asks the running turn to stop at the next safe point. The turn still settles normally (its assistant message reaches a terminal status), after which the session accepts new messages. Interrupting does not undo generations that already ran.

## Questions from the agent

When the agent needs a decision it parks the turn and the session status becomes `awaiting_input`. The parked assistant message contains the question. Answer with a regular `POST …/messages` — the reply resumes the same turn. Nothing times out on our side, but the session stays parked until you answer or interrupt.

## Upload input files

Give the agent input files by uploading them first and referencing the returned URL in your message content.

`POST /v1/agent/media` → `201`

```json theme={"dark"}
// Request
{ "extension": "png", "type": "image" }

// Response
{
  "id": "ab12cd….png",
  "type": "image",
  "content_type": "image/png",
  "upload_url": "https://…presigned…",
  "url": "https://cdn.higgsfield.ai/agent-media/…/ab12cd….png"
}
```

Then `PUT` the file bytes to `upload_url` with the returned `Content-Type` header, and confirm:

`POST /v1/agent/media/{id}/confirm` with `{ "type": "image" }`.

The confirmation response contains `status: "uploaded"` when the file is ready, or `status: "not_ready"` when it is not yet available. The SDKs return the URL only after `uploaded`; otherwise they raise `AgentError` in Python or `HiggsfieldError` in TypeScript.

Use the `url` in your message: `"content": "Animate this image: https://cdn.higgsfield.ai/agent-media/…"`. Supported types: `image`, `video`, `audio`, `file`.

## Errors

| Code  | Meaning                                                                                      |
| ----- | -------------------------------------------------------------------------------------------- |
| `401` | Missing or invalid credentials.                                                              |
| `402` | Insufficient credit balance for the message reserve.                                         |
| `403` | Agent API is not enabled for this account.                                                   |
| `404` | Session not found, or owned by a different account.                                          |
| `409` | `session_busy` — a turn is already running on this session.                                  |
| `502` | The agent backend is temporarily unavailable; the message was refunded — retry with backoff. |

A `failed` assistant message means the turn itself errored; the message reserve is refunded automatically and the session returns to `idle`.

## Billing

Two independent meters apply:

1. **Turn cost.** Sending a message places a fixed credit reserve (the per-message ceiling). When the turn completes, the reserve is reconciled to the turn's actual LLM usage and the difference is refunded automatically. Failed turns are refunded in full. The turn's actual LLM cost appears on the user message as `llm_cost_usd` (US dollars; converted to credits at your account's rate for the refund).
2. **Generations.** Every model the agent runs is billed separately at that model's listed price, identical to calling the model endpoint yourself. Failed generations are auto-refunded. The agent only uses models from the public [catalog](/docs/models).

All charges and refunds appear in your account's transaction history with the message or request id as the reference.


## Related topics

- [Client libraries](/docs/how-to/sdk.md)
- [API reference](/docs/api-reference/overview.md)
- [Agent quickstart](/docs/agent/quickstart.md)
- [Agent overview](/docs/agent/overview.md)
