Anthropic-compatible API
Base URL https://modelportal.ai, authenticated with x-api-key: YOUR_API_KEY or Authorization: Bearer YOUR_API_KEY, plus an anthropic-version header (such as 2023-06-01). Requests and responses follow the Anthropic Messages API. The old /anthropic/* addresses return 410 request.endpoint_moved.
POST /v1/messages
| Field | Type | Required | Notes |
|---|---|---|---|
model |
string | Yes | Model ID or alias; any text model in the catalog |
max_tokens |
integer | Yes | Maximum output |
messages |
array | Yes | Messages with text, images, tool_use, tool_result and thinking blocks |
system |
string or array | No | System prompt; content blocks may carry cache_control |
stream |
boolean | No | true returns SSE with the official events, ending in message_stop |
thinking |
object | No | See Reasoning |
tools, tool_choice |
— | No | Tool use |
temperature, top_p, top_k |
number | No | Sampling parameters |
metadata.user_id |
string | No | Used as the session identifier for affinity, removed before forwarding |
Pass routing preferences in the X-ModelPortal-Provider-Preferences header. The anthropic-beta header is forwarded upstream.
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"model": "MODEL_ID",
"content": [{"type": "text", "text": "Hello!"}],
"stop_reason": "end_turn",
"usage": {"input_tokens": 9, "output_tokens": 4, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0, "cost": 0.000013},
"provider": "PROVIDER_ID",
"attempts": [{"provider": "PROVIDER_ID", "endpoint": "ENDPOINT_ID", "status": 200, "cost": 0.000013}]
}
usage is the billed usage: input_tokens excludes the cache, cache writes and reads are listed separately, and output_tokens includes reasoning. usage.cost is the charge for this call (USD); provider and attempts name the provider that served it and each attempt. When streaming, these three are in the message_delta event. Response headers are in the API overview.
POST /v1/messages/count_tokens
Counts input tokens without charging or holding balance. Fields as in /v1/messages; only model and messages are needed.
GET /v1/models
With the anthropic-version header, returns the models this key may call in the Anthropic format.
Errors
Error bodies are {"type": "error", "error": {"type", "message"}}, with no machine-readable code:
| HTTP | error.type |
Platform codes |
|---|---|---|
| 400 | invalid_request_error |
invalid_request, unsupported_parameter |
| 401 | authentication_error |
invalid_api_key, key_inactive |
| 402 | billing_error |
insufficient_balance, budget_exceeded |
| 403 | permission_error |
key_restricted, request_blocked, region_restricted, verification_required |
| 404 / 410 | not_found_error |
model_not_found, model_retired, request.endpoint_moved |
| 422 | invalid_request_error |
no_eligible_endpoint, with exclusion reasons in error.excluded |
| 429 | rate_limit_error |
rate_limited, capacity_exhausted |
| 502 | api_error |
upstream_failed |
When the x-should-retry response header is true (429 and 5xx), retry with backoff. All codes are in Common errors.