Skip to content
Heimdallm
Marketplace/Documentation
Documentation · API reference

Messages

POST https://api-staging.impossiblecarrot.cc/api/v1/messages

Send an Anthropic Messages request to a marketplace model and receive a message object or an Anthropic event stream. Requires bearer authentication: send Authorization: Bearer or x-api-key carrying a Heimdallm API key — the header the Anthropic SDKs and the Claude Code CLI send when configured with ANTHROPIC_API_KEY. Sending both headers with different values is refused. Choose a model id from the catalogue; the API dialect does not select Claude or guarantee a particular model's capabilities.

Request body

FieldTypeNotes
modelstringRequired marketplace model id; routing suffixes :free, :nitro and :floor are accepted.
messagesobject[]Required, at least one user, assistant or system turn. content is a string or an array of blocks.
max_tokenspositive integerRequired ceiling on generated tokens.
systemstring or object[]System prompt, or an array of text blocks.
toolsobject[]Function definitions with name, optional description and input_schema. Hosted web search is refused.
tool_choiceobject{"type":"auto"}, {"type":"any"}, {"type":"none"} or {"type":"tool","name":"get_weather"}. any requires a tool call.
stop_sequencesstring[]Up to eight stop sequences.
temperature, top_p, top_knumberRespectively 0–2, 0–1 and a nonnegative integer; support depends on the endpoint.
streambooleanSet to true for server-sent events.
metadata, thinkingobjectAccepted without effect. thinking does not control the routed model's reasoning.

A system turn placed among the messages is accepted, and its text joins the top-level system text in the one leading system message sent upstream: a chat template takes a system turn only as the opening message, so a briefing sent mid-conversation reaches the model as part of the system prompt.

Text blocks use {"type":"text","text":"Hello."}. User image blocks accept a source with type: "base64", media_type and data, or type: "url" and url; choose a model that reads images. User document blocks accept the same base64 and url sources for a PDF, or a text source that joins the turn as text; choose a model that reads files. An image or document block may instead carry source { "type": "file", "file_id": "…" }, naming a file stored with the Files API; see Documents & files. An assistant tool call is a tool_use block with id, name and input. Return its result in the next user turn as a tool_result block with the matching tool_use_id and content. content may hold text, image and document blocks. A returned image or PDF reaches the model as an image or file part in the user turn after the results, labelled with its tool_use_id, so the request is routed only to an endpoint that reads that input, and a model with none answers HTTP 503 naming it. A plain-text document stays in the result's text; a block of any other type is named there and its payload left out. Your client executes the function; the marketplace does not execute it.

Example

Replace the example model with one listed in the catalogue. Token counts and ids in the reply are illustrative.

curl https://api-staging.impossiblecarrot.cc/api/v1/messages \
-H "Authorization: Bearer $HEIMDALL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "model": "deepseek/deepseek-v4-flash-0731-abliterated",
  "max_tokens": 64,
  "messages": [{ "role": "user", "content": "Say hello." }]
}'
{
  "id": "msg_gen-example",
  "type": "message",
  "role": "assistant",
  "model": "deepseek/deepseek-v4-flash-0731-abliterated",
  "content": [{ "type": "text", "text": "Hello." }],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": { "input_tokens": 9, "output_tokens": 3 }
}

A picture the model generates is an image block beside the text, with a base64 source carrying the bytes and their media_type, or a url source where the endpoint answered with a URL of its own. Generated audio has no block on this wire: a reply carrying it is refused with HTTP 422 naming the limit, and the same model's speech is served on POST /chat/completions, whose reply carries it in message.audio.

content holds text and/or tool_use blocks. stop_reason is end_turn, max_tokens or tool_use; the translator returns stop_sequence: null, including when a stop sequence was requested. usage carries input and output token counts, without usage.cost or cache breakdowns.

This dialect's usage object is required and states both counts, and a client parsing it rejects an object with a member missing, so a count the endpoint serving the reply never reported has no member to leave out. It is sent as 0 and named in usage.heimdall.unreported, a marketplace extension listing every count whose zero nothing measured:

"usage": { "input_tokens": 0, "output_tokens": 3, "heimdall": { "unreported": ["input_tokens"] } }

A count not named there is the endpoint's own figure, so a zero without the marker is a measured zero. The marker is absent from a reply whose counts were both reported, and a reply the endpoint sent no usage document for names both. Clients that do not know the extension read the object as before.

Streaming

Add "stream": true to the same body and use curl -N. The response is text/event-stream. Events have both an event: name and a JSON type. A text answer follows this sequence (the example shows the content and closing events after message_start and ping):

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello."}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":9,"output_tokens":3}}

event: message_stop
data: {"type":"message_stop"}

A generated picture opens as a content_block_start whose content_block is the whole image block, followed at once by its content_block_stop; there is no image delta. A stream that produces audio ends with the same refusal as an error event, because the status is already sent.

message_start contains an empty message whose token counts are both zero and both named in usage.heimdall.unreported, because nothing is measured when the stream opens. Read through the final message_delta for usage; those initial zeros are not measurements. Tool blocks open with content_block_start and type: "tool_use"; their arguments arrive as input_json_delta with partial_json fragments. Accumulate the fragments before parsing them. ping events and SSE comments can occur between content events. Success ends with message_stop, without [DONE].

Authentication and body validation failures use the HTTP error envelope. The stream commits on its first event, or after one keep-alive period when the model is slower than that to start, so a rejection before then (an unknown model, no eligible endpoint, an engine refusing a request member) is an HTTP error status with {"type":"error","error":{"type":"invalid_request_error","message":"…","metadata":{…}}}. Once streaming begins, a failure arrives as event: error in the same shape (the error type varies), and the connection closes. A 503 the request did not cause, a marketplace restart among them, is overloaded_error: the type Anthropic clients retry. metadata is the public error envelope's and carries the engine's own diagnostic as provider_message when one came back. A partial answer without message_stop is not a completed message.

The marketplace runs no web search. Anthropic's hosted search is declared in tools by a dated type (web_search_20250305 and later) and run by Anthropic's own API, which reports it as server_tool_use and web_search_tool_result blocks and counts it in usage.server_tool_use.web_search_requests. A request that declares one is refused with HTTP 400 before inference, naming the entry (tools[0]) and its version, because a model offered a search nothing can run answers as though it had searched.

A reply never carries those blocks, a citations member on a text block or a usage.server_tool_use member, so a client counting from them reads none, which is the number the marketplace ran. Claude Code's built-in WebSearch tool declares the hosted search and fails with this refusal; search through an MCP server or another tool your client runs.

To search, declare a function of your own, such as web_search with an input_schema taking a query, and run it in your client. Each call the model makes is one tool_use block; several in one turn arrive as several blocks with their own id, and the next user turn answers each with a tool_result whose is_error is true where that search failed. A search that found nothing is a result, not an error. Hosted-search blocks from an earlier Anthropic reply are not forwarded; the model reads the conversation's text.

Heimdallm differences

The request runs through the same model routing as chat completions, session affinity included: send X-Session-Id to keep a conversation on the endpoint that served it. The Anthropic wire carries no conversation id of its own, so this dialect has no other way to take part. X-Generation-Id identifies the generation; a successful non-streaming reply also carries X-Provider-Name. Read the generation's recorded cost through GET /generation using that header. These dialect replies contain neither a provider field nor a usage.cost field.

The translation handles text, images and function tools. Other content blocks and block hints such as cache_control are not forwarded; accepting them does not enable Anthropic-specific features. models, provider and route carry the shared routing controls; other extra request members are not forwarded. Key routing defaults apply below explicit request preferences. Tools require an eligible endpoint that supports them.

For a context estimate, use Count message tokens. For harness integration, see Switching to Heimdallm.

DiscoverFind your next modelModel libraryAll models, versions, prices and capabilitiesBenchmarksMeasured quality, cost and time by serving configurationShowcaseImages, video and 3D made on the marketplaceProvidersCompare independent inference providersActivityMarketplace traffic and usageNetwork statusAvailability, latency and endpoint healthChatConversations, model settings and filesImage, video & 3DGenerate images, video and 3D assetsScene studioStage a shot in 3D, direct it and render it as a videoCoding playgroundBuild software with an AI agent on a machine of your ownOverview & routingIdentity, workspaces and routing preferencesCredits & billingBalance, deposits, ledger and reserved fundsAPI keysKeys scoped to workspaces, limits and expirationOrganizationsTeams, members and shared workspacesRequest historyRequests, receipts, sandbox sessions and account historyReferralsInvitations and referral earningsPrivacyData settings, exports and deletionDocumentationQuickstart, SDKs, pricing and guidesAPI referenceInteractive endpoint reference