curl https://kymaapi.com/v1/messages \
-H "x-api-key: kyma-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello!"}
]
}'
from anthropic import Anthropic
client = Anthropic(base_url="https://kymaapi.com", api_key="kyma-your-api-key")
message = client.messages.create(
model="deepseek-v4-flash",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
Endpoints
Messages (Anthropic format)
Send a conversation in the Anthropic Messages format and get an Anthropic-shaped reply from any Kyma chat model.
POST
/
v1
/
messages
curl https://kymaapi.com/v1/messages \
-H "x-api-key: kyma-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello!"}
]
}'
from anthropic import Anthropic
client = Anthropic(base_url="https://kymaapi.com", api_key="kyma-your-api-key")
message = client.messages.create(
model="deepseek-v4-flash",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
Use this endpoint when your client speaks the Anthropic Messages API (the Anthropic SDKs, Claude Code, and agents built on them). Point the SDK’s base URL at
Other fields, such as
A stream that fails after it started ends with
https://kymaapi.com and it calls this path itself. Setup per SDK: Anthropic SDK guide.
Authentication
Send your key asx-api-key: kyma-... (what the Anthropic SDKs send) or as Authorization: Bearer kyma-.... Either works.
Request body
string
required
A Kyma model id or alias, for example
deepseek-v4-flash. Any chat model works; see GET /v1/models. This endpoint returns 400 naming the endpoint to use for an embedding model (POST /v1/embeddings), a reranking model (POST /v1/rerank), a decisions model (POST /v1/decisions), a model that does not produce text (for example image or speech) and a model that does not take text (transcription, audio understanding).array
required
The conversation, as
{role, content} objects with role "user" or "assistant". content is a string or an array of blocks:textimage, with abase64source (plusmedia_type) or aurlsource, on a model that accepts images (GET /v1/models?input_modalities=image). Other image sources, and images sent to a text-only model, return400.document, with atextsource only. PDF, url, file and custom-content documents return400: send the text instead.tool_use(assistant turns) andtool_result(user turns). Atool_resultmay hold a string ortext,documentandimageblocks.
string | array
The system prompt, as a string or an array of
text blocks. cache_control on a system block is kept. See Prompt caching.integer
default:"4096"
Maximum tokens to generate. Unlike Anthropic’s API, it is optional here: when omitted, Kyma sends
4096. If your balance cannot pay for all of them, Kyma lowers the value and says so in the x-kyma-max-tokens-clamped header.boolean
default:"false"
Stream the reply as Anthropic server-sent events.
number
Sampling temperature. When omitted, the model’s own default applies.
number
Nucleus sampling. When omitted, the model’s own default applies.
array
Strings that end generation.
array
Tool definitions:
name, description, input_schema (JSON Schema). On models with supports_tools: true. See Tool calling.object
{"type": "auto"}, {"type": "any"}, {"type": "none"} or {"type": "tool", "name": "..."}, with optional disable_parallel_tool_use: true. none and disable_parallel_tool_use are applied only when tools is also sent.top_k, thinking and metadata, are not forwarded to the model.
Response
{
"id": "msg_abc123",
"type": "message",
"role": "assistant",
"content": [
{ "type": "text", "text": "Hello! How can I help you today?" }
],
"model": "deepseek-v4-flash",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": { "input_tokens": 12, "output_tokens": 10 }
}
contentholds atextblock, then onetool_useblock (id,name,input) per tool call.stop_reasonisend_turn,max_tokensortool_use.stop_sequenceis alwaysnull.modelis the Kyma id your request resolved to.usagecarriesinput_tokensandoutput_tokensonly.
stream: true you get the Anthropic event sequence: message_start, content_block_start, content_block_delta (text_delta, or input_json_delta for tool input), content_block_stop, message_delta, message_stop. Kyma does not send an error event on this stream today.
Response headers
| Header | When |
|---|---|
x-kyma-model | Always. The model id your request resolved to |
x-kyma-alias | When you sent an alias; names it |
x-kyma-cost-usd | Non-streaming replies. What the call cost you, in USD. The Anthropic body has no field for a price, so it rides here |
x-kyma-fallback | true when a fallback route or model answered |
x-kyma-served-model | Only when a different model answered; names it |
x-kyma-max-tokens-clamped | When your balance could not pay for the full max_tokens; the value Kyma sent instead. x-kyma-credits-have carries your balance |
Errors
Every error on this endpoint uses Anthropic’s envelope, so an Anthropic SDK reads it as one:type: "error" on top, an Anthropic error type in error.type, and request_id at the top level. Kyma adds its own code next to the Anthropic type:
{
"type": "error",
"error": {
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "...",
"param": null,
"retryable": true,
"request_id": "req_…",
"doc_url": "https://docs.kymaapi.com/api-reference/errors#rate_limit_exceeded"
},
"request_id": "req_…"
}
| Status | error.type | error.code | What to do |
|---|---|---|---|
400 | invalid_request_error | invalid_json, missing_parameter, wrong_endpoint | Fix the request; wrong_endpoint names the endpoint that serves the model |
400 | invalid_request_error | unsupported_content | An image the model cannot take, an unsupported image source, or a document without a text source. Remove the block, or pick a model that accepts images |
400 413 422 | invalid_request_error | request_rejected | The model rejected the request; retrying the same body fails the same way |
401 | authentication_error | missing_api_key, invalid_api_key | Check x-api-key or Authorization |
402 | billing_error | insufficient_credits, model_requires_paid | Top up, or pick a model with free_tier: true. The body also carries balance, required, topup_url and details.hint |
403 | permission_error | route_refused | Every route for the model refused this content; send it to a model from error.suggested_models |
404 | not_found_error | model_not_found | Fix the model id; did_you_mean and suggested_models name close matches |
413 | request_too_large | request_too_large | Body over 25 MB: split the messages or downscale images |
429 | rate_limit_error | rate_limit_exceeded | Back off. Retry-After: 60, plus x-ratelimit-limit-requests, x-ratelimit-remaining-requests, x-ratelimit-reset-requests |
500 | api_error | internal_error | Retry once; if it repeats, send us the request_id |
502 | api_error | upstream_invalid_response | Retry |
503 | overloaded_error | provider_unavailable, model_unavailable | Retry after Retry-After: 5; on model_unavailable, pick another model |
event: error and error.code: "stream_interrupted" (overloaded_error). Retry the whole request.
curl https://kymaapi.com/v1/messages \
-H "x-api-key: kyma-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello!"}
]
}'
from anthropic import Anthropic
client = Anthropic(base_url="https://kymaapi.com", api_key="kyma-your-api-key")
message = client.messages.create(
model="deepseek-v4-flash",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)