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

# Create a message (Anthropic Messages API)

The Anthropic Messages API on the node's own model, so Anthropic SDKs and agents built on them run against it with only the base URL and the credential changed: set `ANTHROPIC_BASE_URL` (or `base_url`) to `https://beta-api.b3os.org/v1/infer`, the same base URL as the OpenAI SDKs (`http://127.0.0.1:7700/v1/infer` inside a sandbox; the SDKs add `/v1/messages`), and send the B3OS key as a bearer token (`ANTHROPIC_AUTH_TOKEN`, or `auth_token` in the SDKs). Text, images (`base64`, or `url` sources fetched by the node through its egress guard), custom tools with `tool_use` and `tool_result` blocks, `tool_choice`, `thinking` (the reasoning arrives in `thinking` blocks; `budget_tokens` caps it), JSON Schema output through `output_config.format`, stop sequences, a trailing assistant turn that the model continues, and streaming events (`message_start` ... `message_stop`, exactly as Anthropic sends them). Models are those of `GET /v1/infer/models`; there is no gateway route here.
Parameters this node does not take return `400 unsupported_parameter` (tools Anthropic defines or runs, such as `web_search` or `bash`, `container`, `mcp_servers`, document and file sources). `cache_control`, `citations`, `metadata`, `service_tier`, `output_config.effort` and `thinking.display` are accepted and ignored (the runtime caches prompt prefixes on its own). Errors use the Anthropic shape (`{"type": "error", "error": {...}}`, with the B3OS code under `b3os`), except those raised before the request reaches the infer service (authentication, scopes, body size), which use the OpenAI shape of the rest of `/v1/infer`; Anthropic SDKs map both by HTTP status. A stream that fails after it started ends with an `error` event; one that fails before the first token is a plain HTTP error. The response head of a stream waits for the first generated token, so `Server-Timing` can carry `ttft`.
Bills input and output tokens, with the admission and limits of chat completions (the estimated prompt plus `max_tokens`, settled with the real counts; an abandoned stream is billed to its last token). 

` POST /v1/infer/v1/messages `

Create a message (Anthropic Messages API)

The Anthropic Messages API on the node's own model, so Anthropic SDKs and agents built on them run against
it with only the base URL and the credential changed: set `ANTHROPIC_BASE_URL` (or `base_url`) to
`https://beta-api.b3os.org/v1/infer`, the same base URL as the OpenAI SDKs (`http://127.0.0.1:7700/v1/infer`
inside a sandbox; the SDKs add `/v1/messages`), and send the B3OS key as a bearer token
(`ANTHROPIC_AUTH_TOKEN`, or `auth_token` in the SDKs). Text, images (`base64`, or `url` sources fetched by
the node through its egress guard), custom tools with `tool_use` and `tool_result` blocks, `tool_choice`,
`thinking` (the reasoning arrives in `thinking` blocks; `budget_tokens` caps it), JSON Schema output
through `output_config.format`, stop sequences, a trailing assistant turn that the model continues, and
streaming events (`message_start` ... `message_stop`, exactly as Anthropic sends them). Models are those
of `GET /v1/infer/models`; there is no gateway route here.

Parameters this node does not take return `400 unsupported_parameter` (tools Anthropic defines or runs,
such as `web_search` or `bash`, `container`, `mcp_servers`, document and file sources).
`cache_control`, `citations`, `metadata`, `service_tier`, `output_config.effort` and `thinking.display`
are accepted and ignored (the runtime caches prompt prefixes on its own). Errors use the Anthropic shape
(`{"type": "error", "error": {...}}`, with the B3OS code under `b3os`), except those raised before the
request reaches the infer service (authentication, scopes, body size), which use the OpenAI shape of the
rest of `/v1/infer`; Anthropic SDKs map both by HTTP status. A stream that fails after it started ends
with an `error` event; one that fails before the first token is a plain HTTP error. The response head of
a stream waits for the first generated token, so `Server-Timing` can carry `ttft`.

Bills input and output tokens, with the admission and limits of chat completions (the estimated prompt
plus `max_tokens`, settled with the real counts; an abandoned stream is billed to its last token).


## Servers

- ` https://beta-api.b3os.org ` — API (API keys and CLI tokens)

- ` https://beta.b3os.org ` — Dashboard (session cookie and CSRF header; same paths)

## Authentication

The operation accepts these alternatives. Schemes within one alternative are required together.

### Alternative 1

- ` apiKey `: ` http `

  - HTTP scheme: ` bearer ` (b3os_sk_ API key or b3os_pat_ token)

  - `Authorization: Bearer <credential>`. Two credential kinds are accepted:

- **API keys** `b3os_sk_<32 base32>_<crc32>`, created in the dashboard or with `POST /v1/keys`. A key belongs to
  one project, has scopes, an optional spend cap and expiry, and is shown only once.
- **CLI tokens** `b3os_pat_<32 base32>_<crc32>`, issued by the device login (`b3os login`). They act for one
  user in the organization and project chosen at approval.

Keys are stored as SHA-256 hashes. The edge exchanges them for a 60-second node token before forwarding
a request to a node, so nodes never see your key.


### Alternative 2

- ` session `: ` apiKey `

  - Credential: ` __Host-b3os_session ` in ` cookie `

  - The dashboard session cookie on `beta.b3os.org` (host-only, `Secure`, `HttpOnly`). Requests other than
`GET`/`HEAD` must also send `x-b3os-csrf: <csrf_token>` from `GET /v1/auth/session`; SameSite is not relied
on. The cookie is never sent to `beta-api.b3os.org` or `usercontent.b3os.org`.


## Request body (required)

Content type: ` application/json `

- ` value `: type ` object ` — Anthropic Messages parameters. Any other parameter is `400 unsupported_parameter`; `null` means unset.

  - Required fields: ` model `, ` messages `, ` max_tokens `

  - ` model `: type ` string `

    - minLength: ` 1 `

    - maxLength: ` 256 `

  - ` messages `: type ` array `

    - ` array item `: type ` unknown `

      - ` oneOf alternative 1 `: type ` object `

        - Required fields: ` role `, ` content `

        - ` role `: type ` string `

          - enum: ` ["user"] `

        - ` content `: type ` unknown `

          - ` oneOf alternative 1 `: type ` string `

          - ` oneOf alternative 2 `: type ` array `

            - ` array item `: type ` unknown `

              - ` oneOf alternative 1 `: type ` object `

                - Required fields: ` type `, ` text `

                - ` type `: type ` string `

                  - enum: ` ["text"] `

                - ` text `: type ` string `

                - ` cache_control `: type ` object `; nullable — Accepted and ignored.

                  - ` type `: type ` string `

                  - ` ttl `: type ` string `

                - ` citations `: type ` array `; nullable — Accepted and ignored.

                  - ` array item `: type ` object `

              - ` oneOf alternative 2 `: type ` object `

                - Required fields: ` type `, ` source `

                - ` type `: type ` string `

                  - enum: ` ["image"] `

                - ` source `: type ` unknown `

                  - ` oneOf alternative 1 `: type ` object `

                    - Required fields: ` type `, ` media_type `, ` data `

                    - ` type `: type ` string `

                      - enum: ` ["base64"] `

                    - ` media_type `: type ` string `

                      - enum: ` ["image/png","image/jpeg","image/webp","image/gif"] `

                    - ` data `: type ` string `; format ` byte ` — The image file, which must be a PNG, JPEG, WebP or GIF.

                  - ` oneOf alternative 2 `: type ` object `

                    - Required fields: ` type `, ` url `

                    - ` type `: type ` string `

                      - enum: ` ["url"] `

                    - ` url `: type ` string ` — Fetched by the node through its egress guard (PNG, JPEG, WebP or GIF, at most 10 MiB).

                      - pattern: ` "^https://" `

                - ` cache_control `: type ` object `; nullable — Accepted and ignored.

                  - ` type `: type ` string `

                  - ` ttl `: type ` string `

              - ` oneOf alternative 3 `: type ` object `

                - Required fields: ` type `, ` tool_use_id `

                - ` type `: type ` string `

                  - enum: ` ["tool_result"] `

                - ` tool_use_id `: type ` string `

                - ` content `: type ` unknown `

                  - ` oneOf alternative 1 `: type ` string `; nullable

                  - ` oneOf alternative 2 `: type ` array `

                    - ` array item `: type ` unknown `

                      - ` oneOf alternative 1 `: type ` object `

                        - Required fields: ` type `, ` text `

                        - ` type `: type ` string `

                          - enum: ` ["text"] `

                        - ` text `: type ` string `

                        - ` cache_control `: type ` object `; nullable — Accepted and ignored.

                          - ` type `: type ` string `

                          - ` ttl `: type ` string `

                        - ` citations `: type ` array `; nullable — Accepted and ignored.

                          - ` array item `: type ` object `

                      - ` oneOf alternative 2 `: type ` object `

                        - Required fields: ` type `, ` source `

                        - ` type `: type ` string `

                          - enum: ` ["image"] `

                        - ` source `: type ` unknown `

                          - ` oneOf alternative 1 `: type ` object `

                            - Required fields: ` type `, ` media_type `, ` data `

                            - ` type `: type ` string `

                              - enum: ` ["base64"] `

                            - ` media_type `: type ` string `

                              - enum: ` ["image/png","image/jpeg","image/webp","image/gif"] `

                            - ` data `: type ` string `; format ` byte ` — The image file, which must be a PNG, JPEG, WebP or GIF.

                          - ` oneOf alternative 2 `: type ` object `

                            - Required fields: ` type `, ` url `

                            - ` type `: type ` string `

                              - enum: ` ["url"] `

                            - ` url `: type ` string ` — Fetched by the node through its egress guard (PNG, JPEG, WebP or GIF, at most 10 MiB).

                              - pattern: ` "^https://" `

                        - ` cache_control `: type ` object `; nullable — Accepted and ignored.

                          - ` type `: type ` string `

                          - ` ttl `: type ` string `

                - ` is_error `: type ` boolean `; nullable — The result is an error; the model sees it prefixed with `Error:`.

                - ` cache_control `: type ` object `; nullable — Accepted and ignored.

                  - ` type `: type ` string `

                  - ` ttl `: type ` string `

      - ` oneOf alternative 2 `: type ` object ` — An earlier answer; as the last message, the start of the answer, which the model continues.

        - Required fields: ` role `, ` content `

        - ` role `: type ` string `

          - enum: ` ["assistant"] `

        - ` content `: type ` unknown `

          - ` oneOf alternative 1 `: type ` string `

          - ` oneOf alternative 2 `: type ` array `

            - ` array item `: type ` unknown `

              - ` oneOf alternative 1 `: type ` object `

                - Required fields: ` type `, ` text `

                - ` type `: type ` string `

                  - enum: ` ["text"] `

                - ` text `: type ` string `

                - ` cache_control `: type ` object `; nullable — Accepted and ignored.

                  - ` type `: type ` string `

                  - ` ttl `: type ` string `

                - ` citations `: type ` array `; nullable — Accepted and ignored.

                  - ` array item `: type ` object `

              - ` oneOf alternative 2 `: type ` object `

                - Required fields: ` type `, ` id `, ` name `, ` input `

                - ` type `: type ` string `

                  - enum: ` ["tool_use"] `

                - ` id `: type ` string `

                  - minLength: ` 1 `

                - ` name `: type ` string `

                - ` input `: type ` object `

                - ` cache_control `: type ` object `; nullable — Accepted and ignored.

                  - ` type `: type ` string `

                  - ` ttl `: type ` string `

              - ` oneOf alternative 3 `: type ` object `

                - Required fields: ` type `, ` thinking `

                - ` type `: type ` string `

                  - enum: ` ["thinking"] `

                - ` thinking `: type ` string `

                - ` signature `: type ` string `; nullable — Opaque; this node does not check it.

              - ` oneOf alternative 4 `: type ` object ` — Accepted in assistant turns and left out of the prompt.

                - Required fields: ` type `, ` data `

                - ` type `: type ` string `

                  - enum: ` ["redacted_thinking"] `

                - ` data `: type ` string `

  - ` max_tokens `: type ` integer `

    - minimum: ` 1 `

  - ` system `: type ` unknown ` — The system prompt; text blocks are joined with blank lines.

    - ` oneOf alternative 1 `: type ` string `; nullable

    - ` oneOf alternative 2 `: type ` array `

      - ` array item `: type ` object `

        - Required fields: ` type `, ` text `

        - ` type `: type ` string `

          - enum: ` ["text"] `

        - ` text `: type ` string `

        - ` cache_control `: type ` object `; nullable — Accepted and ignored.

          - ` type `: type ` string `

          - ` ttl `: type ` string `

        - ` citations `: type ` array `; nullable — Accepted and ignored.

          - ` array item `: type ` object `

  - ` tools `: type ` array `; nullable

    - ` array item `: type ` object ` — A custom tool. Tools Anthropic defines or runs (a `type` other than `custom`) are `unsupported_parameter`.

      - Required fields: ` name `, ` input_schema `

      - ` type `: type ` string `; nullable

        - enum: ` ["custom",null] `

      - ` name `: type ` string ` — Unique within `tools`.

        - pattern: ` "^[A-Za-z0-9_-]{1,128}$" `

      - ` description `: type ` string `; nullable

      - ` input_schema `: type ` object ` — A JSON Schema object (at most 64 KiB serialized and 32 levels deep).

      - ` strict `: type ` boolean `; nullable

      - ` cache_control `: type ` object `; nullable — Accepted and ignored.

        - ` type `: type ` string `

        - ` ttl `: type ` string `

  - ` tool_choice `: type ` object `; nullable

    - ` oneOf alternative 1 `: type ` object `

      - Required fields: ` type `

      - ` type `: type ` string ` — `any` makes the model call a tool (it needs `tools`).

        - enum: ` ["auto","any"] `

      - ` disable_parallel_tool_use `: type ` boolean `; nullable

    - ` oneOf alternative 2 `: type ` object `

      - Required fields: ` type `, ` name `

      - ` type `: type ` string `

        - enum: ` ["tool"] `

      - ` name `: type ` string ` — One of `tools`.

      - ` disable_parallel_tool_use `: type ` boolean `; nullable

    - ` oneOf alternative 3 `: type ` object `

      - Required fields: ` type `

      - ` type `: type ` string `

        - enum: ` ["none"] `

  - ` thinking `: type ` object `; nullable — `enabled` (with `budget_tokens`, at least 1024 and less than `max_tokens`) and `adaptive` let the model reason first, in `thinking` blocks; `disabled`, the default, does not. `display` is accepted and ignored. 

    - ` oneOf alternative 1 `: type ` object `

      - Required fields: ` type `, ` budget_tokens `

      - ` type `: type ` string `

        - enum: ` ["enabled"] `

      - ` budget_tokens `: type ` integer `

        - minimum: ` 1024 `

      - ` display `: type ` string `; nullable

        - enum: ` ["summarized","omitted","updates",null] `

    - ` oneOf alternative 2 `: type ` object `

      - Required fields: ` type `

      - ` type `: type ` string `

        - enum: ` ["adaptive"] `

      - ` display `: type ` string `; nullable

        - enum: ` ["summarized","omitted","updates",null] `

    - ` oneOf alternative 3 `: type ` object `

      - Required fields: ` type `

      - ` type `: type ` string `

        - enum: ` ["disabled"] `

  - ` output_config `: type ` object `; nullable

    - ` format `: type ` object `; nullable — The answer is JSON matching `schema` (at most 64 KiB serialized and 32 levels deep).

      - Required fields: ` type `, ` schema `

      - ` type `: type ` string `

        - enum: ` ["json_schema"] `

      - ` schema `: type ` object ` — A JSON Schema object, as Anthropic requires.

    - ` effort `: type ` string `; nullable — Accepted and ignored.

      - enum: ` ["low","medium","high","xhigh","max",null] `

  - ` stop_sequences `: type ` array `; nullable

    - ` array item `: type ` string `

      - minLength: ` 1 `

  - ` stream `: type ` boolean `; nullable

  - ` temperature `: type ` number `; nullable

    - minimum: ` 0 `

    - maximum: ` 1 `

  - ` top_p `: type ` number `; nullable — Nucleus sampling. `0` keeps only the most probable token (passed to the runtime as 1e-9, the same thing, since vLLM takes values above 0 only).

    - minimum: ` 0 `

    - maximum: ` 1 `

  - ` top_k `: type ` integer `; nullable

    - minimum: ` 1 `

    - maximum: ` 1000000 `

  - ` metadata `: type ` object `; nullable — Accepted and ignored.

    - ` user_id `: type ` string `; nullable

  - ` service_tier `: type ` string `; nullable — Accepted and ignored.

## Responses

### ` 200 ` — The message, or the event stream with `stream: true`.

Content type: ` application/json `

- ` value `: type ` object `

  - Required fields: ` id `, ` type `, ` role `, ` content `, ` model `, ` stop_reason `, ` stop_sequence `, ` usage `

  - ` id `: type ` string `

  - ` type `: type ` string `

    - enum: ` ["message"] `

  - ` role `: type ` string `

    - enum: ` ["assistant"] `

  - ` content `: type ` array `

    - ` array item `: type ` object ` — A block of the answer, `text`, `tool_use` (with `id`, `name`, `input`) or `thinking` (with `signature`).

      - Required fields: ` type `

      - ` type `: type ` string `

        - enum: ` ["text","tool_use","thinking"] `

      - ` text `: type ` string `

      - ` id `: type ` string `

      - ` name `: type ` string `

      - ` input `: type ` object `

      - ` thinking `: type ` string `

      - ` signature `: type ` string `

  - ` model `: type ` string `

  - ` stop_reason `: type ` string `

    - enum: ` ["end_turn","max_tokens","stop_sequence","tool_use","refusal"] `

  - ` stop_sequence `: type ` string `; nullable — The stop sequence that ended the answer.

  - ` usage `: type ` object `

    - Required fields: ` input_tokens `, ` output_tokens `

    - ` input_tokens `: type ` integer `

    - ` output_tokens `: type ` integer `

  - ` b3os `: type ` object ` — B3OS extension; OpenAI SDKs ignore it. On a stream it rides on the last chunk: the usage chunk with `stream_options.include_usage`, else the chunk with `finish_reason`. 

    - ` route `: type ` string `

      - enum: ` ["local","gateway"] `

    - ` node `: type ` string `

    - ` timing `: type ` object ` — Server-side milliseconds from the request head (`ttft_ms` on streams, `model_ms` without).

      - ` ttft_ms `: type ` number `

      - ` model_ms `: type ` number `

      - ` total_ms `: type ` number `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Response header ` request-id ` — The request ID under the name Anthropic SDKs read (`_request_id`); `x-request-id` carries it too.

- ` value `: type ` string `

Example:

```json
{
  "id": "msg_9f1c2a7e4b5d4e0f8a6b3c2d1e0f9a8b",
  "type": "message",
  "role": "assistant",
  "model": "b3os/qwen3.5-9b",
  "content": [
    {
      "type": "tool_use",
      "id": "chatcmpl-tool-7f3a",
      "name": "get_weather",
      "input": {
        "city": "Eugene"
      }
    }
  ],
  "stop_reason": "tool_use",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 61,
    "output_tokens": 18
  },
  "b3os": {
    "route": "local",
    "node": "n1"
  }
}
```

### ` 400 ` — The request is invalid (`invalid_request`, `unsupported_parameter`, `context_length_exceeded`, `unsupported_media_type`).

Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "web_search_20250305 is a tool Anthropic defines or runs; this node takes custom tools (name, description, input_schema)"
  },
  "request_id": "req_01m5t4yg394wegr3j4y01qb363",
  "b3os": {
    "code": "unsupported_parameter",
    "param": "tools.0.type"
  }
}
```

### ` 401 ` — Missing or invalid credentials (`unauthorized`), checked before the request reaches the infer service (OpenAI shape).

Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "error": {
    "message": "API key checksum does not match; check that the whole key was copied",
    "type": "authentication_error",
    "param": null,
    "code": "unauthorized"
  }
}
```

### ` 403 ` — The key lacks `infer:run` (`forbidden`, OpenAI shape), or the egress guard refused an image URL (`egress_denied`).

Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

### ` 404 ` — The model is not served on this node (`model_not_available`).

Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "error",
  "error": {
    "type": "not_found_error",
    "message": "claude-sonnet-4-5 is not served on this node; GET /v1/infer/models lists the models that are"
  },
  "b3os": {
    "code": "model_not_available",
    "param": "model"
  }
}
```

### ` 413 ` — The request body exceeds the model's `max_request_bytes` (`payload_too_large`).

Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "error",
  "error": {
    "type": "request_too_large",
    "message": "Request body is 12582912 bytes; b3os/qwen3.5-9b accepts at most 10485760"
  },
  "b3os": {
    "code": "payload_too_large"
  }
}
```

### ` 415 ` — The body is not JSON (`unsupported_media_type`): send `Content-Type: application/json`.

Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "expected Content-Type: application/json"
  },
  "b3os": {
    "code": "unsupported_media_type"
  }
}
```

### ` 429 ` — A limit applies (`rate_limited` for requests, tokens or remote image bytes per minute, `concurrency_limited` for requests in flight for the organization).

Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Response header ` Retry-After ` — Seconds to wait before retrying or polling again.

- ` value `: type ` integer `

  - minimum: ` 0 `

Response header ` RateLimit-Limit ` — Requests allowed in the current window for the limit that applies to this operation.

- ` value `: type ` integer `

Response header ` RateLimit-Remaining ` — Requests left in the current window.

- ` value `: type ` integer `

Response header ` RateLimit-Reset ` — Seconds until the current window resets.

- ` value `: type ` integer `

Example:

```json
{
  "type": "error",
  "error": {
    "type": "rate_limit_error",
    "message": "200000 tokens per minute allowed on b3os/qwen3.5-9b; retry in 9 seconds"
  },
  "b3os": {
    "code": "rate_limited"
  }
}
```

### ` 500 ` — Something failed inside B3OS (`internal`).

Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "error",
  "error": {
    "type": "api_error",
    "message": "internal error (request req_01m5t4yg394wegr3j4y01qb363)"
  },
  "b3os": {
    "code": "internal"
  }
}
```

### ` 503 ` — The model runtime is restarting, overloaded or not set up on this node (`infer_backend_unavailable`), or
the node is unavailable (`node_unavailable`, OpenAI shape).


Content type: ` application/json `

- ` value `: type ` unknown ` — The Anthropic error body, or the OpenAI one for errors raised before the request reaches the infer service.

  - ` oneOf alternative 1 `: type ` object ` — The Anthropic error body, with the B3OS code and the offending parameter (a dotted path) under `b3os`.

    - Required fields: ` type `, ` error `

    - ` type `: type ` string `

      - enum: ` ["error"] `

    - ` error `: type ` object `

      - Required fields: ` type `, ` message `

      - ` type `: type ` string `

        - enum: ` ["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","request_too_large","rate_limit_error","api_error","timeout_error","overloaded_error"] `

      - ` message `: type ` string `

    - ` request_id `: type ` string `

    - ` b3os `: type ` object `

      - Required fields: ` code `

      - ` code `: type ` string `

      - ` param `: type ` string `

  - ` oneOf alternative 2 `: type ` object ` — The OpenAI error body. `code` is the B3OS error code; `x-request-id` carries the request ID.

    - Required fields: ` error `

    - ` error `: type ` object `

      - Required fields: ` message `, ` type `, ` param `, ` code `

      - ` message `: type ` string `

      - ` type `: type ` string ` — `invalid_request_error`, `authentication_error`, `permission_error`, `rate_limit_error` or `server_error`.

      - ` param `: type ` string `; nullable

      - ` code `: type ` string `; nullable

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Response header ` Retry-After ` — Seconds to wait before retrying or polling again.

- ` value `: type ` integer `

  - minimum: ` 0 `

Example:

```json
{
  "type": "error",
  "error": {
    "type": "overloaded_error",
    "message": "The model runtime on n1 is restarting; retry in 5 seconds"
  },
  "b3os": {
    "code": "infer_backend_unavailable"
  }
}
```

## Request examples

### cURL

```curl
curl -X POST 'https://beta-api.b3os.org/v1/infer/v1/messages' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
  "model": "string",
  "messages": [
    {
      "role": "user",
      "content": "string"
    }
  ],
  "max_tokens": 1,
  "system": "string",
  "tools": [
    {
      "type": "custom",
      "name": "string",
      "description": "string",
      "input_schema": {},
      "strict": true,
      "cache_control": {
        "type": "string",
        "ttl": "string"
      }
    }
  ],
  "tool_choice": {},
  "thinking": {},
  "output_config": {
    "format": {
      "type": "json_schema",
      "schema": {}
    },
    "effort": "low"
  },
  "stop_sequences": [
    "string"
  ],
  "stream": true,
  "temperature": 0,
  "top_p": 0,
  "top_k": 1,
  "metadata": {
    "user_id": "string"
  },
  "service_tier": "string"
}'
```

### JavaScript

```javascript
const response = await fetch('https://beta-api.b3os.org/v1/infer/v1/messages', {
  method: 'POST',
  headers: {
      "Authorization": "Bearer YOUR_API_TOKEN",
      "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "model": "string",
    "messages": [
      {
        "role": "user",
        "content": "string"
      }
    ],
    "max_tokens": 1,
    "system": "string",
    "tools": [
      {
        "type": "custom",
        "name": "string",
        "description": "string",
        "input_schema": {},
        "strict": true,
        "cache_control": {
          "type": "string",
          "ttl": "string"
        }
      }
    ],
    "tool_choice": {},
    "thinking": {},
    "output_config": {
      "format": {
        "type": "json_schema",
        "schema": {}
      },
      "effort": "low"
    },
    "stop_sequences": [
      "string"
    ],
    "stream": true,
    "temperature": 0,
    "top_p": 0,
    "top_k": 1,
    "metadata": {
      "user_id": "string"
    },
    "service_tier": "string"
  })
});

const data = await response.json();
console.log(data);
```

### Python

```python
import requests

headers = {
    'Authorization': 'Bearer YOUR_API_TOKEN'
}

response = requests.post('https://beta-api.b3os.org/v1/infer/v1/messages', headers=headers, json={
  "model": "string",
  "messages": [
    {
      "role": "user",
      "content": "string"
    }
  ],
  "max_tokens": 1,
  "system": "string",
  "tools": [
    {
      "type": "custom",
      "name": "string",
      "description": "string",
      "input_schema": {},
      "strict": true,
      "cache_control": {
        "type": "string",
        "ttl": "string"
      }
    }
  ],
  "tool_choice": {},
  "thinking": {},
  "output_config": {
    "format": {
      "type": "json_schema",
      "schema": {}
    },
    "effort": "low"
  },
  "stop_sequences": [
    "string"
  ],
  "stream": true,
  "temperature": 0,
  "top_p": 0,
  "top_k": 1,
  "metadata": {
    "user_id": "string"
  },
  "service_tier": "string"
})
print(response.json())
```