Build with the API

Chat completions with tools and images

POST /v1/chat/completions sends a conversation to a chat model and returns its reply. The same chat is available as POST /v1/messages, in the form Anthropic's clients send and read: use whichever your code already uses, with the same key, models and prices. Each example below is one call, shown for every client; the choice you make is remembered across the documentation.

curl https://sven.swedishembedded.com/v1/chat/completions \
  -H "Authorization: Bearer $SVEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "messages": [
      {"role": "system", "content": "You answer in one sentence."},
      {"role": "user", "content": "Why is the sky blue?"}
    ],
    "temperature": 0.2,
    "max_tokens": 200
  }'

Parameters#

ParameterNotes
modelRequired. A chat model's id from the model list.
messagesRequired, at least one. Each has a role (system or developer for instructions, user, assistant or tool) and content.
temperature0 to 2.
top_p0 to 1.
max_tokens, max_completion_tokensThe most tokens to write. When both are sent, max_completion_tokens wins. When neither is, a default applies.
stopA string or a list of strings at which the model stops.
tools, tool_choiceFunctions the model may call. See below.
response_formatThe shape the reply must take: {"type": "json_object"} for any JSON object, or {"type": "json_schema", "json_schema": {"name", "strict", "schema"}} for JSON following your schema (at most 64 KB). Models that take it list response_format or structured_outputs in supported_parameters.
stream, stream_optionsReceive the reply as it is written. See Streaming.
nOnly 1 is accepted.

A parameter the model does not accept is refused with a 400 whose error.param names it. The model's supported_parameters in the model list says what it takes.

Tool calling#

Describe functions in tools and the model may answer with a call to one instead of text. You run the function and send its result back in a tool message that carries the call's tool_call_id. Only models whose capabilities include tools take them.

curl https://sven.swedishembedded.com/v1/chat/completions \
  -H "Authorization: Bearer $SVEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "messages": [{"role": "user", "content": "What is the weather in Malmo?"}],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "get_weather",
          "description": "The current weather in a city",
          "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"]
          }
        }
      }
    ],
    "tool_choice": "auto"
  }'

Images in a message#

A user message can carry images next to text, for a model whose input modalities include images. The content is a list of parts, and an image is base64 text, never a link: sven does not fetch addresses. BASE64_IMAGE below stands for the picture's base64 text; the Python and Node tabs of the first form show how to make it.

Send a picture at the size a model reads it: models scale an image down to about 1,568 px on its longest edge before they look at it, so anything larger costs upload time and is never seen. A screenshot or diagram reads best as PNG, a photo as JPEG. A conversation carries its images with every call; send again only the ones the next answer needs.

curl https://sven.swedishembedded.com/v1/chat/completions \
  -H "Authorization: Bearer $SVEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "text", "text": "What is in this picture?"},
          {
            "type": "image_url",
            "image_url": {"url": "data:image/png;base64,BASE64_IMAGE"}
          }
        ]
      }
    ]
  }'

Images may be PNG, JPEG, GIF or WebP, up to 10 MiB each and 20 per request. A model that does not take images refuses the request and names itself.

The response#

The reply is a chat completion object: choices[0].message holds the text or the tool calls, finish_reason says why it ended (stop, length, tool_calls or content_filter), and usage has prompt_tokens, completion_tokens and total_tokens, which is what you are charged for. Every response carries an x-request-id header.

A conversation longer than the model can take is refused with a 400 on messages.

Using Anthropic's client#

An existing Anthropic client works against POST /v1/messages unchanged, with the same key. Its base URL is the API's address without /v1, because the client adds /v1/messages itself; the Anthropic tabs above show it. The models and prices are those of the chat completions route.

  • x-api-key carries the key (a bearer token works too).
  • anthropic-version is required, 2026-10-21 or 2023-06-01. Anthropic's clients send it for you. Any other version is refused with a 400.
  • The anthropic-beta header is not supported and is refused with a 400.
  • model and max_tokens are required. You can also send system, stop_sequences, tools, tool_choice and stream, and under 2023-06-01 also temperature (0 to 1), top_p and top_k. Under 2026-10-21 those three, and a text block of yours that carries citations, are refused with a 400, as that version removed them. Images are sent as base64 sources inside a message's content, never as links.
  • Extended thinking cannot be switched on: omit thinking or send {"type": "disabled"}.
  • Errors come back as an object with type: "error" and an error holding a type and a message. The statuses match those of the rest of the API, with two differences: a model that is temporarily unavailable is 529 with overloaded_error, and an account that cannot cover the call is 402 with billing_error. See Errors.