# Create Message

`POST https://api.vultrinference.com/v1/messages`

Create a Message using the Anthropic Messages API format. This endpoint accepts Anthropic-native request payloads and returns Anthropic-native responses. The request is adapted internally to the underlying chat completions engine.

**System prompt:** Use the top-level `system` parameter for initial instructions. A later text-only `system` message may follow a `user` message; it may be last or precede an `assistant` message.

**Content blocks:** Message `content` may be a string or an array of typed content blocks (`text`, `image`, `tool_use`, `tool_result`).

**Assistant prefill:** If the final message uses the `assistant` role, the response continues immediately from that content.

**Streaming:** Set `stream: true` to receive server-sent events with typed event names (`message_start`, `content_block_start`, `content_block_delta`, `content_block_stop`, `message_delta`, `message_stop`).

**Extended thinking:** `thinking.type: enabled` requires `budget_tokens` below `max_tokens` and a model that supports enforced thinking budgets; other models reject this mode. Check `reasoning.supports_max_tokens` in `/v1/models?format=openrouter` (in the default list, a `max_tokens` property under the text output's `reasoning` parameter). `adaptive` uses the model's own thinking behavior, and `disabled` turns thinking off. Thinking blocks use API-generated signatures, and `display: omitted` hides their text while preserving a signature for continuation.

**System instructions:** A later `system` message keeps its position when forwarded to the model. Turn-scoped `clear_at` and per-message `output_config` are not supported.

**Effort:** Top-level `output_config.effort` maps through the selected model's `reasoning_config`. The `:express` model variant derives a thinking budget when the selected model supports enforced budgets and no budget is supplied.

**Tools:** Tools use `input_schema` (JSON Schema) rather than `parameters`. Tool results are sent as `tool_result` content blocks in subsequent `user` messages.

**Errors:** Errors use Anthropic's body, `{"type": "error", "error": {"type", "message"}}`. A request the gateway refuses is a 400 `invalid_request_error`; Anthropic has no 422. An unknown model is a 404 `not_found_error`, a rate-limited request a 429 `rate_limit_error` with `Retry-After`, a bad or missing key a 401 `authentication_error`, and a failure on our side or the engine's a 5xx `api_error`.

## Body (application/json)

- `model` (string, required): The model identifier to use for generation.
- `max_tokens` (integer, required): Total completion token allowance, including thinking and visible output. The gateway forwards zero if supplied; whether zero is accepted depends on the upstream engine. [at least 0]
- `messages` (array of objects, required): Input messages. Models operate on alternating `user` and `assistant` conversational turns. Consecutive `user` or `assistant` turns are combined into a single turn. If the final message uses the `assistant` role, the response content continues immediately from that message's content (assistant prefill). A text-only `system` message may follow a `user` turn, as the final message or before an `assistant` turn. Use the top-level `system` parameter for initial instructions. Turn-scoped `clear_at` and per-message `output_config` are not supported. [at least 1 items]
  - `role` (string, required): The role of the message author. A `system` message must follow `user`; initial system instructions belong in the top-level `system` field. [user, assistant, system]
  - `content` (string or array of objects, required): System messages support text blocks only.
  - `clear_at` (string): Turn-scoped system messages are not supported. [never]
- `system` (string or array of objects): System prompt providing context or instructions to the model. May be a string or an array of text blocks.
- `stream` (boolean): Whether to stream the response using server-sent events. Streaming events use typed event names: message_start, content_block_start, content_block_delta, content_block_stop, message_delta, message_stop.
- `temperature` (number (float)): Controls randomness in the model responses. Valid range: 0 to 1. [range 0–1]
- `top_p` (number (float)): Enables nucleus sampling with a cumulative probability cutoff. [range 0–1]
- `top_k` (integer): Limits sampling to the top K options.
- `stop_sequences` (array of strings): Custom sequences that, when encountered in the generated text, cause the model to stop.
- `metadata` (object): Additional metadata about the request.
  - `user_id` (string): An opaque identifier for the end-user making the request.
- `output_config` (object): Output controls. Effort is translated through the selected model's reasoning configuration. Unsupported configured levels return 400.
  - `effort` (string) [minimal, low, medium, high, xhigh, max, ultra]
- `thinking` (object): Thinking configuration. The adapter signs its own thinking blocks for continuation; it does not emit redacted thinking blocks.
  - `type` (string): `enabled` requests thinking with an exact budget on models that support enforced thinking budgets; `adaptive` leaves the thinking allocation to the model; `disabled` turns thinking off. [enabled, adaptive, disabled]
  - `budget_tokens` (integer): Required for `enabled`; must be less than `max_tokens` and the effective output limit after context clipping. Models that cannot enforce the budget reject the request. [at least 1024]
  - `display` (string): `omitted` hides thinking text while preserving an API-generated signature for continuation. It is invalid when thinking is disabled. [summarized, omitted]
- `tools` (array of objects): Definitions for tools available to the model.
  - `name` (string, required): The name of the tool. [range 1–200 characters]
  - `description` (string): A detailed description of what the tool does.
  - `input_schema` (object, required): A JSON Schema object describing the expected input format for the tool.
  - `type` (string): Accepted but ignored by the adapter. Tools are forwarded as ordinary function tools using `name` and `input_schema`; Anthropic built-in tool behavior is not implemented.
  - `cache_control` (object): Accepted for Anthropic client compatibility but ignored by the adapter; it does not create a cache breakpoint.
    - `type` (string): The cache control type. [ephemeral]
- `tool_choice` (object): Instructs how the model should use any provided tools.
  - `type` (string): How the model should use tools. `auto` lets the model decide. `any` forces at least one tool call. `tool` forces a specific tool. [auto, any, tool]
  - `name` (string): The name of the specific tool to use. Required when type is `tool`.

## Responses

- `200`: OK (anthropic-message-response-payload)
- `400`: Bad Request (invalid_request_error) (anthropic-error-payload)
- `401`: Unauthorized (authentication_error) (anthropic-error-payload)
- `404`: Model not found (not_found_error) (anthropic-error-payload)
- `429`: Rate limited (rate_limit_error) (anthropic-error-payload)
- `500`: Server error (api_error) (anthropic-error-payload)

## Example

```bash
curl https://api.vultrinference.com/v1/messages \
  -H "Authorization: Bearer $VULTR_INFERENCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4.1-flash",
    "max_tokens": 1024,
    "system": "Answer in one sentence.",
    "messages": [
      {
        "role": "user",
        "content": "Why is the sky blue?"
      }
    ]
  }'
```

```python
import os
import requests

response = requests.post(
    "https://api.vultrinference.com/v1/messages",
    headers={"Authorization": f"Bearer {os.environ['VULTR_INFERENCE_API_KEY']}"},
    json={
        "model": "deepseek-v4.1-flash",
        "max_tokens": 1024,
        "system": "Answer in one sentence.",
        "messages": [
            {
                "role": "user",
                "content": "Why is the sky blue?",
            },
        ],
    },
)
print(response.json())
```

```javascript
const response = await fetch("https://api.vultrinference.com/v1/messages", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.VULTR_INFERENCE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "deepseek-v4.1-flash",
    "max_tokens": 1024,
    "system": "Answer in one sentence.",
    "messages": [
      {
        "role": "user",
        "content": "Why is the sky blue?"
      }
    ]
  }),
});
console.log(await response.json());
```
