Use Anthropic Messages
Send a Messages-shaped request with the Anthropic headers and base URL.
Send a Messages-shaped request with the Anthropic headers and base URL.
Set BASE_URL to your HTTPS API origin without a trailing slash or /v1, and pass API_KEY from your credential store. OpenAI-compatible SDKs use ${BASE_URL}/v1; Anthropic-compatible SDKs use BASE_URL.
Choose Messages for an Anthropic-compatible client. Its base URL is BASE_URL, without /v1. You need an organization key, an available model and credits.
printf 'x-api-key: %s\n' "$API_KEY" \
| curl -q -H @- -i "$BASE_URL/v1/messages" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"max_tokens": 64,
"messages": [
{
"role": "user",
"content": "Say hello in one sentence."
}
],
"stream": false
}'
HTTP 200 returns a message object with content blocks and usage. Text lives in text blocks; the generated words vary. To estimate input tokens without generation, call POST /v1/messages/count_tokens with the same model and messages; it still counts toward the organization's request rate. For streaming event shapes, see streaming.
This shows a completed response shape; your ID, text, and token counts will differ:
{
"id": "msg_018f3f407b447cc4b8ba3f62656c299c",
"type": "message",
"role": "assistant",
"model": "gpt-5.6-sol",
"content": [{ "type": "text", "text": "Done." }],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 12,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"output_tokens": 5
}
}
Display text blocks in content; execute tool_use in a separate cycle only after validating the input arguments. stop_reason: max_tokens means a partial answer; tool_use means the turn awaits a tool result. In Messages, input_tokens is the uncached input portion: account for cache reads and writes when evaluating context use. The finalized credit debit is on API Activity.
Use -N to see native Messages events as they arrive. Generate one idempotency key so you can retry the same logical request after a disconnect:
export UNLIMGPT_REQUEST_KEY="$(openssl rand -hex 16)"
Send the request from the same shell:
test -n "${UNLIMGPT_REQUEST_KEY:-}" \
&& printf 'x-api-key: %s\n' "$API_KEY" \
| curl -q -H @- -i -N "$BASE_URL/v1/messages" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $UNLIMGPT_REQUEST_KEY" \
-d '{
"model": "gpt-5.6-sol",
"max_tokens": 64,
"messages": [
{
"role": "user",
"content": "Count to three."
}
],
"stream": true
}'
HTTP 200 starts the stream. message_start provides the message ID; content_block_start, content_block_delta, and content_block_stop delimit each text or tool block. Read the final stop_reason and usage from message_delta, then require message_stop before marking the call complete. A mid-stream event: error or a connection close before message_stop is not a completed answer. For a retry, run only the second block with the same key and unchanged body; a new key may start another paid generation. See streaming for recovery and protocol differences.
Send the same model and messages to POST /v1/messages/count_tokens before a generation:
printf 'x-api-key: %s\n' "$API_KEY" \
| curl -q -H @- -i "$BASE_URL/v1/messages/count_tokens" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"messages": [
{
"role": "user",
"content": "Count this message."
}
]
}'
HTTP 200 returns JSON with a numeric input_tokens, for example {"input_tokens":12}; the estimate depends on the input. This call starts no generation, but it does count toward the organization's requests per minute limit. The response also includes remaining-request rate limit headers. If the model catalog or plan rejects the call, check models and limits.
Next: authentication and errors.