Chatin valmistuminen
Luo chat-vastauksia yli 100 malliin yhdestä API:sta. Drop-in on yhteensopiva OpenAI Chat Completions, Anthropic Messages ja Anthropic Responses kanssa.
Airforce ymmärtää sekä OpenAI Chat Completions- että Anthropic Messages -wire-formaatit samalla mallijoukolla. Valitse SDK, jota jo käytät, ja muuta vain base URL — muut kuin Claude-mallit välitetään läpinäkyvästi kummankin rajapinnan takana.
Tämä sivu käsittelee autentikoinnin, molempien rajapintojen request- ja response-muodot, streamingin, tool callingin, visionin, päättelyn ja prompt cachingin. Uusi täällä? Aloita alla olevasta perusesimerkistä, saa yksi kutsu toimimaan ja lisää sitten streaming, toolit tai caching, kun se toimii.
Todennus
Jokainen pyyntö tarvitsee Bearer-tunnuksen (Airforce API -avaimesi). Anthropic x-api-key otsikko on myös hyväksytty /v1/messages SDK-yhteensopivuuden vuoksi.
Authorization: Bearer sk-air-YOUR_API_KEY
# alt for /v1/messages:
x-api-key: sk-air-YOUR_API_KEYPOST /v1/chat/completions
OpenAI-yhteensopivat Chat Completions. Toimii virallisen openai SDK ohittamalla base_url kohtaan https://api.airforce/v1.
https://api.airforce/v1/chat/completionsPyynnön runko
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Required | Mallin tunnus. Käytä GET /v1/models löytääksesi käytettävissä olevat tunnukset. |
| messages | array | Required | Keskusteluhistoria. Jokaisella merkinnällä on { role: "system" | "user" | "assistant" | "tool", content }. Sisältö on merkkijono tai taulukko sisältölohkoja (vision, katso alla). |
| max_tokens | integer | Optional | Luotavien tunnuksien enimmäismäärä. Rajattu mallin max_output_tokeniin. |
| temperature | float | Optional | Näytteenottolämpötila, 0–2. Alempi on deterministisempi. Oletusarvo riippuu ylävirran toimittajasta. |
| top_p | float | Optional | Ydinnäytteenotto. Käytä joko lämpötilaa tai top_p:tä, ei molempia. |
| stream | boolean | Optional | Kun tosi, vastaus on palvelimen lähettämien tapahtumien virta. Katso "Striimaus" alla. |
| models | array | Optional | Fallback models (max 3), e.g. ["deepseek-v3.2", "gpt-4o-mini"]. If every channel of the primary model fails, each candidate is tried in order. You are billed for — and response.model reports — the model that actually answered. Unknown or plan-gated candidates are skipped. With the OpenAI SDK pass it via extra_body. |
| transforms | array | Optional | Prompt transforms. Supported: ["middle-out"] — when the conversation overflows the model's context window, whole messages are dropped from the middle (system prompts, the first message and the most recent turns are kept), so long roleplay or agent histories keep working instead of erroring. Opt-in; off by default. |
| stream_options | object | Optional | { include_usage: boolean }. Käyttö sisältyy aina suoratoiston viimeiseen osaan; tämä kenttä hyväksytään OpenAI-yhteensopivuuden vuoksi, mutta sitä ei voi poistaa käytöstä. |
| stop | string | array | Optional | Jopa 4 pysäytysjaksoa. Sukupolvi pysähtyy heti, kun sellainen on valmistettu. |
| tools | array | Optional | Toimintojen määritelmät, joita malli voi kutsua. Katso "Työkalun kutsuminen" alla. |
| tool_choice | string | object | Optional | "auto" (oletus), "ei mikään" tai { type: "function", function: { name } } pakottaaksesi tietyn kutsun. |
| response_format | object | Optional | { type: "json_object" } pakottaa mallin lähettämään kelvollisen JSONin. Ohitetaan malleissa, jotka eivät tue sitä. |
| reasoning_effort | string | Optional | Reasoning depth: "low" | "medium" | "high" | "xhigh" | "max". Any model with supports_reasoning: true (Claude, OpenAI o/GPT-5, Gemini, Qwen, DeepSeek, …). See "Reasoning & thinking". |
| thinking | string | object | Optional | Cross-model thinking switch. "on" | "off" | "auto"; Anthropic-style { type: "enabled", budget_tokens: N }; hybrid { type: "enabled" | "disabled" }. See "Reasoning & thinking". |
| thinking_budget | integer | Optional | Token cap mallin päättelyjäljelle (kun toimittaja paljastaa sellaisen). |
| ignore_defaults | boolean | Optional | Ohita käyttäjän tallentamat mallikohtaiset oletusparametrit (määritetty kojelaudassa) tälle pyynnölle. |
| skill | string | Optional | ID of a single marketplace skill to apply to this request. The skill transforms your messages/parameters before the upstream call and overrides any installed-skill defaults. Consumed by Airforce, never forwarded upstream. See the Skills catalog at /docs/api/extend. |
| skills | array | Optional | Array of marketplace skill IDs applied in order, for stacking multiple skills on one request. |
Perusesimerkki
curl https://api.airforce/v1/chat/completions \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.1-chat",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"}
],
"max_tokens": 200,
"temperature": 0.7
}'Vastauksen muoto
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Optional | Vakaa valmistumistunnus, esim. "chatcmpl-abc123". |
| object | string | Optional | "chat.completion" ei-suoratoistolle, "chat.completion.chunk" suoratoistolle. |
| created | integer | Optional | Unix-aikaleima (sekuntia). |
| model | string | Optional | Kaiku pyydetystä mallitunnuksesta. |
| choices | array | Optional | Joukko valmistumisehdokkaita: [{ index, message: { role, content, tool_calls? }, lopetussyy }]. |
| choices[].finish_reason | string | Optional | "pysäytys" | "pituus" | "työkalukutsut" | "content_filter". |
| usage | object | Optional | { prompt_tokens, completion_tokens, total_tokens, completion_tokens_details?, prompt_tokens_details?, cache_creation_input_tokens?, cache_creation? }. completion_tokens_details.reasoning_tokens asetetaan kun malli tuotti päättelyjäljen. Välimuistikentät näkyvät kun upstream palautti prompt-välimuistitietoja: prompt_tokens_details.cached_tokens raportoi välimuistiluvut (OpenAI-standardi), cache_creation_input_tokens summaa kirjoitukset, ja cache_creation.ephemeral_5m_input_tokens / ephemeral_1h_input_tokens antavat TTL-jaon. |
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1710000000,
"model": "gpt-5.1-chat",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "The capital of France is Paris."
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 20,
"completion_tokens": 8,
"total_tokens": 28
}
}Pohdintaa & ajattelua
Reasoning/thinking is a cross-model feature for every model ID with supports_reasoning: true — Claude, OpenAI o-series/GPT-5, Gemini, Qwen, DeepSeek, and others. You send the same canonical parameters; Airforce maps them to each provider's native shape. This is not a DeepSeek-only API.
Truth source: check supports_reasoning: true mallissa sisään GET /v1/models (or GET /api/models/{id}/allowed-params). Prefer that flag over guessing from the model name.
Mallit päättelyn tuella
…· liveKanoniset parametrit
| Parameter | Type | Required | Description |
|---|---|---|---|
| reasoning_effort | string | Optional | "low" | "medium" | "high" | "xhigh" | "max". Accepted on every model with supports_reasoning: true. Some upstreams only honour a subset (e.g. high/max); others clamp unsupported levels to the nearest served value. |
| thinking | string | object | Optional | Three accepted shapes (we normalise): "on" | "off" | "auto"; Anthropic-style { type: "enabled", budget_tokens: N }; hybrid { type: "enabled" | "disabled" }. Mapped onto Claude extended thinking, OpenAI effort profiles, Gemini thinking_config, Qwen enable_thinking, DeepSeek hybrid, etc. |
| thinking_budget | integer | Optional | Maximum tokens the model may spend reasoning before emitting visible output. Mirrors budget_tokens when the upstream exposes a budget; takes precedence over reasoning_effort when both are sent and a budget is available. |
What differs by family (mapping only)
Parameters are the same everywhere. Only how we map them (and how hard "off" is) differs:
- Claude — Thinking on/off + budget; often also reasoning_effort via the gateway.
- OpenAI (o1/o3, GPT-5) — Mainly reasoning_effort. A full "thinking off" is often not available — you control how strongly the model reasons, not always whether it reasons at all.
- Gemini — thinking_config / budget mapped internally.
- Qwen / Xiaomi / Alibaba — thinking + enable_thinking-style controls.
- DeepSeek (generic) — Hybrid on/off is especially clear: thinking: { type: enabled|disabled } plus optional reasoning_effort.
- Resellers / other — Often generic passthrough of the same canonical fields.
Controlling where the trace appears
An optional reasoning object on the request decides what happens to the thinking trace. It is consumed by Airforce and never forwarded upstream.
| Parameter | Type | Required | Description |
|---|---|---|---|
| reasoning.format | string | Optional | "separate" (default) puts the trace in message.reasoning (and delta.reasoning while streaming). "inline" keeps the legacy inline <think>…</think> form inside content. |
| reasoning.exclude | boolean | Optional | When true, the reasoning trace is dropped entirely from the response. Reasoning tokens are still counted and billed if the model produced them. |
"reasoning": { "format": "separate", "exclude": false }Päättelytyö (OpenAI-tyyli)
Primary control for o-series and GPT-5: how much the model may reason. Same canonical field as on every other supports_reasoning model — OpenAI is included, but behaviour is not 1:1 with DeepSeek's hard on/off.
curl https://api.airforce/v1/chat/completions \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "o3-mini",
"messages": [{"role": "user", "content": "Prove the Pythagorean theorem."}],
"reasoning_effort": "high"
}'Laajennettu ajattelu (Anthropic-tyyli)
Budget-based thinking for Claude (and gateways that accept the Anthropic shape). You can still send reasoning_effort; we map when the channel supports it.
curl https://api.airforce/v1/chat/completions \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4.6",
"messages": [{"role": "user", "content": "Plan a 7-day Italy trip."}],
"thinking": {"type": "enabled", "budget_tokens": 4000}
}'Hybrid thinking (e.g. DeepSeek V3.2/V4)
Example of a hybrid model family with a clear Thinking / Non-Thinking switch — not a separate protocol. deepseek-v3.2, deepseek-v4-flash and deepseek-v4-pro accept the same canonical fields as every other supports_reasoning model. Toggle thinking and optionally set effort in one request:
curl https://api.airforce/v1/chat/completions \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro",
"messages": [{"role": "user", "content": "Solve this step by step: integrate x^2 * e^x."}],
"thinking": {"type": "enabled"},
"reasoning_effort": "high"
}'Turn thinking off (faster, cheaper when you only need the final answer) — this hard off is clearer on hybrid models than on many OpenAI o-series profiles:
"thinking": {"type": "disabled"}
// or simply: "thinking": "off"Native docs for this family often list effort levels such as "high" and "max". We accept the full low…max scale and map unsupported levels to the nearest value that reaches the model. Prefer the hybrid IDs above over retired deepseek-chat / deepseek-reasoner names when you need an explicit on/off switch.
Itse päättelyn jälki näkyy choices[0].message.reasoning (OpenAI-muoto) tai kuten thinking blokkaa sisään content (Anthropic-muoto). Perustelut laskutetaan ja raportoidaan usage.completion_tokens_details.reasoning_tokens.
Tämä completion_tokens_details.reasoning_tokens -erittely on mukana vain, kun upstream-palveluntarjoaja raportoi sen. Streamatussa vastauksessa jäljitys saapuu kentässä delta.reasoning_content per chunk.
Vision ja kuvan syöttö
Mallit, joissa supports_vision: true hyväksyä sisältölohkoiksi upotetut kuvat. Joko julkinen URL-osoite tai base64-tieto-URL toimii; kokorajoitukset riippuvat alkupään mallista.
Näkötuella varustetut mallit
…· livecurl https://api.airforce/v1/chat/completions \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.1-chat",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "What is in this image?"},
{"type": "image_url", "image_url": {"url": "https://example.com/cat.jpg"}}
]
}]
}'Työkalun kutsuminen
Mallit, joissa supports_tools: true voi kutsua määrittämiäsi toimintoja. Malli palauttaa a tool_calls joukko; soitat puhelun ja lähetät sitten tuloksen takaisin a tool viesti.
Mallit, joissa on työkalukutsutuki
…· livePyytää
curl https://api.airforce/v1/chat/completions \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.1-chat",
"messages": [{"role": "user", "content": "What is the weather in Paris?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"}
},
"required": ["location"]
}
}
}],
"tool_choice": "auto"
}'Vastaa työkalukutsulla
{
"id": "chatcmpl-abc123",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_1",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\":\"Paris\"}"
}
}]
},
"finish_reason": "tool_calls"
}]
}Seuranta työkalun tuloksella
{
"model": "gpt-5.1-chat",
"messages": [
{"role": "user", "content": "What is the weather in Paris?"},
{
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_1",
"type": "function",
"function": {"name": "get_weather", "arguments": "{\"location\":\"Paris\"}"}
}]
},
{"role": "tool", "tool_call_id": "call_1", "content": "{\"temp_c\": 14, \"sky\": \"cloudy\"}"}
]
}Assistant prefill
End your messages array with an assistant message that already contains some text, and the model continues from it instead of starting a fresh turn. This is a reliable way to force a response to begin a specific way — a leading "{" for JSON, a chosen language, or a fixed prefix. The same trick works on /v1/messages. Providers that reject native prefill are handled automatically: the gateway retries once with a compatible rewrite, so you do not have to special-case them.
{
"model": "claude-sonnet-4.6",
"messages": [
{"role": "user", "content": "List three primary colors as a JSON array."},
{"role": "assistant", "content": "["}
]
}Structured outputs
Set response_format to make the model return JSON. Two modes are supported:
{ "type": "json_object" }— the response is a single valid JSON value.{ "type": "json_schema", "json_schema": { "name", "schema", "strict" } }— the model is steered to produce JSON that matches your JSON Schema.
curl https://api.airforce/v1/chat/completions \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.1-chat",
"messages": [{"role": "user", "content": "Extract the city and country: I live in Paris, France."}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "location",
"schema": {
"type": "object",
"properties": { "city": {"type": "string"}, "country": {"type": "string"} },
"required": ["city", "country"]
}
}
}
}'Reliability: even when a model wraps its answer in prose or a markdown code fence, Airforce extracts the JSON payload so you always receive parseable content. If no valid JSON can be recovered, the original text is returned unchanged — so the guarantee never makes a response worse. This applies to non-streamed responses; streamed responses are passed through unchanged.
Suoratoisto
Sarja stream: true vastaanottaa osittaisia suorituksia palvelimen lähettäminä tapahtumina. Jokainen tapahtuma on yksi JSON-pala, jolla on sama muoto kuin suoratoistetulla vastauksella, paitsi message korvataan delta. Virta päättyy data: [DONE].
curl https://api.airforce/v1/chat/completions \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.1-chat",
"messages": [{"role": "user", "content": "Write a haiku about Berlin."}],
"stream": true,
"stream_options": {"include_usage": true}
}'Langallinen muoto
data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1710000000,"model":"gpt-5.1-chat","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1710000000,"model":"gpt-5.1-chat","choices":[{"index":0,"delta":{"content":"Cold "},"finish_reason":null}]}
data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1710000000,"model":"gpt-5.1-chat","choices":[{"index":0,"delta":{"content":"stone "},"finish_reason":null}]}
…
data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1710000000,"model":"gpt-5.1-chat","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":12,"completion_tokens":17,"total_tokens":29}}
data: [DONE]Reliability & smart routing
Every model ID resolves to a pool of upstream providers behind the scenes. If the first one errors or times out, the request is automatically retried against the next provider for the same model, in order, before any failure is returned — you do not configure or trigger this. The model field in the response always reports the variant that actually answered. This is independent of the optional models / fallbacks array, which adds your own cross-model candidates on top: first the primary model exhausts its own provider chain, then each fallback model exhausts its chain.
POST /v1/messages
Anthropic-yhteensopiva Messages API. Toimii virallisen @anthropic-ai/sdk asettamalla baseURL kohtaan https://api.airforce. Edelleenlähetys OpenAI/Google/etc. läpinäkyvästi muille kuin Claude-malleille.
https://api.airforce/v1/messagesPyynnön runko
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Required | Mallin tunnus (Anthropic-muoto tai reititetty alias). |
| messages | array | Required | Jokainen merkintä: { role: "user" | "assistant", content: string | array }. |
| max_tokens | integer | Required | Anthropicin vaatima. Token cap vastaukselle. |
| system | string | array | Optional | Järjestelmäkehote. Välitä taulukko { type: "text", text, cache_control? } lohkot merkitsevät välimuistissa olevat etuliitesegmentit. Katso "Kehote välimuistiin". |
| temperature | float | Optional | 0–1. |
| top_p | float | Optional | Ydinnäytteenotto. |
| top_k | integer | Optional | Rajoita näytteenottopooli top-K tokeneihin. |
| stop_sequences | array | Optional | Jopa 4 pysäytysjaksoa. |
| stream | boolean | Optional | Kun tosi, lähettää Anthropic-tyylisen SSE-tapahtumavirran (katso "Streaming"). |
| fallbacks | array | Optional | Fallback models (max 3) in Anthropic form: [{"model": "gpt-4o-mini"}]. If every channel of the primary model fails, each candidate is tried in order; you are billed for — and the response model field reports — the model that actually answered. A plain models string array is accepted too. |
| tools | array | Optional | Anthropicin työkalumääritelmät: { name, description, input_schema }. Vastaus voi sisältää tool_use-sisältölohkoja. |
| tool_choice | object | Optional | { type: "auto" | "any" | "tool", name? }. |
| thinking | object | Optional | Anthropicin laajennettu ajattelu: { type: "enabled", budget_tokens: N }. |
Esimerkki
curl https://api.airforce/v1/messages \
-H "x-api-key: sk-air-YOUR_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4.6",
"max_tokens": 256,
"system": "You are a helpful assistant.",
"messages": [
{"role": "user", "content": "Hello, Claude!"}
]
}'Vastauksen muoto
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Optional | Viestitunnus, esim. "msg_01ABCxyz". |
| type | string | Optional | Aina "viesti". |
| role | string | Optional | Aina "avustaja". |
| content | array | Optional | Sisältölohkojen taulukko: { type: "text" | "tool_use" | "thinking", … }. |
| model | string | Optional | Kaiku pyydetystä mallista. |
| stop_reason | string | Optional | "end_turn" | "max_tokens" | "stop_sequence" | "työkalun_käyttö". |
| usage | object | Optional | { input_tokens, output_tokens, cache_read_input_tokens?, cache_creation_input_tokens?, cache_creation? }. Välimuistikentät näkyvät kun prompt-välimuistia käytettiin. cache_creation.ephemeral_5m_input_tokens ja ephemeral_1h_input_tokens antavat kirjoitusjaon TTL-kohtaisesti. |
Streaming tapahtumia
Anthropic SSE käyttää nimettyjä tapahtumia kertaluonteisten JSON-palojen sijaan. Jokaisessa tapahtumassa on sekä event: nimi ja a data: JSON-hyötykuorma.
event: message_start
data: {"type":"message_start","message":{"id":"msg_01","role":"assistant","content":[],"model":"claude-sonnet-4.6","stop_reason":null,"usage":{"input_tokens":12,"output_tokens":1}}}
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"},"usage":{"output_tokens":17}}
event: message_stop
data: {"type":"message_stop"}POST /v1/messages/count_tokens
Anthropic-compatible token counting. Send the same system / messages / tools you would pass to /v1/messages and get an input-token estimate back without running the model — nothing is billed.
https://api.airforce/v1/messages/count_tokenscurl https://api.airforce/v1/messages/count_tokens \
-H "x-api-key: sk-air-YOUR_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4.6",
"system": "You are a helpful assistant.",
"messages": [{"role": "user", "content": "Hello, Claude!"}]
}'
# → {"input_tokens": 34}The count is a fast character-based estimate (about 4 characters per token) over system, messages and tools — close enough for context-budget checks, not an exact tokenizer run.
Nopea välimuisti
Päällä /v1/messages Claude-malleissa, merkitse etuliite välimuistiin siirtämällä system joukkona lohkoja, joissa välimuistissa oleva segmentti kuljettaa cache_control: { type: "ephemeral" }. Myöhemmät pyynnöt, jotka alkavat samalla etuliitteellä, veloittavat halvemman välimuistin lukuhinnan. Mallit, joissa supports_caching: true sisään /v1/models tukea tätä.
Mallit, joissa on nopea välimuisti
…· live{
"model": "claude-sonnet-4.6",
"max_tokens": 1024,
"system": [
{"type": "text", "text": "You are a senior staff engineer at Airforce."},
{
"type": "text",
"text": "<repository-snapshot>...</repository-snapshot>",
"cache_control": {"type": "ephemeral"}
}
],
"messages": [
{"role": "user", "content": "Where is rate limiting enforced?"}
]
}Miten välimuistilukemat raportoidaan vastauksessa
Välimuistitokenien lukemat välitetään kunkin muodon natiivimuodossa, joten SDK:t (openai, @anthropic-ai/sdk, @google/genai) lukevat ne ilman mukautettua koodia. Kentät jätetään pois kun arvo on nolla, pitäen ei-välimuistivastaukset kevyinä.
/v1/chat/completions (OpenAI-muoto)
"usage": {
"prompt_tokens": 2104,
"completion_tokens": 147,
"total_tokens": 2251,
"prompt_tokens_details": { "cached_tokens": 1980 },
"cache_creation_input_tokens": 124,
"cache_creation": {
"ephemeral_5m_input_tokens": 124,
"ephemeral_1h_input_tokens": 0
}
}/v1/messages (Anthropic-muoto)
"usage": {
"input_tokens": 2104,
"output_tokens": 147,
"cache_read_input_tokens": 1980,
"cache_creation_input_tokens": 124,
"cache_creation": {
"ephemeral_5m_input_tokens": 124,
"ephemeral_1h_input_tokens": 0
}
}/v1beta/.../generateContent (Gemini-muoto)
"usageMetadata": {
"promptTokenCount": 2104,
"candidatesTokenCount": 147,
"totalTokenCount": 2251,
"cachedContentTokenCount": 1980
}Missä välimuistitus pätee
Eksplisiittiset cache_control-merkinnät huomioidaan /v1/messages- ja /v1/chat/completions-rajapinnoissa Claude-malleille — laita ne system- tai message-sisältölohkoihin. Monet muut tarjoajat (OpenAI-perhe, DeepSeek, Gemini) välimuistittavat automaattisesti: et lähetä merkintöjä, ja näet vain cached_tokens vastauksessa, kun riittävän pitkää etuliitettä käytetään uudelleen.
Välimuistin kesto: 5 minuuttia tai 1 tunti
Välimuistitettu etuliite elää oletuksena 5 minuuttia, ja ajastin nollautuu joka osumalla. Pidempään elävää etuliitettä varten lisää ttl: "1h" merkintään. Vastaus raportoi kunkin TTL:n erikseen cache_creation-kohdassa.
"cache_control": { "type": "ephemeral", "ttl": "1h" }Esimerkki: ensin kirjoitus, sitten luku
Lähetä täsmälleen sama pyyntö kahdesti (yllä oleva välimuistiesimerkki). Ensimmäinen etuliitteen näkevä kutsu maksaa kertaluonteisen välimuistikirjoituksen; identtiset kutsut TTL:n sisällä maksavat paljon halvemman välimuistiluvun.
Ensimmäinen kutsu — välimuistikirjoitus (usage-ote):
"usage": {
"input_tokens": 2104,
"output_tokens": 12,
"cache_creation_input_tokens": 1980,
"cache_read_input_tokens": 0
}Toinen identtinen kutsu TTL:n sisällä — välimuistiluku:
"usage": {
"input_tokens": 2104,
"output_tokens": 12,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 1980
}Rajat ja kustannus
- Claude vaatii vähimmäisetuliitteen välimuistille (noin 1024 tokenia; joillekin malleille enemmän). Lyhyempiä etuliitteitä ei yksinkertaisesti välimuistiteta.
- Enintään 4 välimuistin katkaisukohtaa pyyntöä kohden, ja välimuistitetun etuliitteen on oltava tavulleen identtinen kutsujen välillä — yhdenkin merkin muutos ohittaa välimuistin.
- Välimuistikirjoitukset maksavat enemmän kuin tavallinen syöte (5m ≈ 1,25×, 1h ≈ 2×); luvut maksavat paljon vähemmän (≈ 0,1×). Katso kunkin mallin välimuistihinnat hinnoittelusivulta.
POST /v1/responses
OpenAI Responses-API tilallisille keskusteluille. Sama Bearer/x-api-key todennus. Välimuistilukemat näkyvät input_tokens_details.cached_tokens (luku) sekä litteä cache_creation_input_tokens + cache_creation.ephemeral_* (kirjoitukset) /v1/chat/completions pariteetilla.
https://api.airforce/v1/responsesPOST /v1beta/models/{model}:generateContent
Google Gemini-compatible endpoint. Works with the official @google/genai SDK and the Gemini CLI by pointing the base URL at https://api.airforce/v1beta. Any routed model works — requests are translated to and from the native Gemini shape, and the model is taken from the URL path (not the body).
https://api.airforce/v1beta/models/{model}:generateContentAuthentication
Pass your Airforce API key any of the three ways Google clients use:
# 1) query parameter (Google default)
?key=sk-air-YOUR_API_KEY
# 2) header
x-goog-api-key: sk-air-YOUR_API_KEY
# 3) bearer token
Authorization: Bearer sk-air-YOUR_API_KEYRequest body
| Parameter | Type | Required | Description |
|---|---|---|---|
| contents | array | Required | Conversation turns. Each: { role: "user" | "model", parts: [...] }. A part is { text }, { functionCall: { name, args } }, or { functionResponse: { name, response } }. "model" is Gemini's term for the assistant role. |
| systemInstruction | object | Optional | System prompt: { parts: [{ text }] }. |
| generationConfig | object | Optional | { temperature, maxOutputTokens, topP, stopSequences } — mapped to the canonical sampling parameters. |
| tools | array | Optional | Tool definitions: [{ functionDeclarations: [{ name, description, parameters }] }]. functionDeclarations are flattened across entries. |
| toolConfig | object | Optional | Tool-choice control: { functionCallingConfig: { mode: "AUTO" | "ANY" | "NONE" } }. ANY forces a call, NONE disables tools. |
Example
curl "https://api.airforce/v1beta/models/gemini-3.1-pro:generateContent" \
-H "x-goog-api-key: sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{"role": "user", "parts": [{"text": "What is the capital of France?"}]}
],
"systemInstruction": {"parts": [{"text": "You are a helpful assistant."}]},
"generationConfig": {"temperature": 0.7, "maxOutputTokens": 256}
}'Response shape
| Parameter | Type | Required | Description |
|---|---|---|---|
| candidates | array | Optional | Generated turns: [{ content: { role: "model", parts }, finishReason, index }]. Only the first candidate is populated. |
| candidates[].finishReason | string | Optional | "STOP" | "MAX_TOKENS" | "SAFETY" | "OTHER". |
| usageMetadata | object | Optional | { promptTokenCount, candidatesTokenCount, totalTokenCount, cachedContentTokenCount? }. cachedContentTokenCount appears when the upstream reported a cache read. |
| modelVersion | string | Optional | Echo of the requested model. |
{
"candidates": [{
"content": {
"role": "model",
"parts": [{"text": "The capital of France is Paris."}]
},
"finishReason": "STOP",
"index": 0
}],
"usageMetadata": {
"promptTokenCount": 16,
"candidatesTokenCount": 8,
"totalTokenCount": 24
},
"modelVersion": "gemini-3.1-pro"
}POST /v1beta/models/{model}:streamGenerateContent
Streaming uses the :streamGenerateContent action and returns Server-Sent Events. Each data: line is a full Gemini-shaped chunk (not a delta object); the final chunk carries usageMetadata.
data: {"candidates":[{"content":{"role":"model","parts":[{"text":"The capital"}]},"index":0}],"modelVersion":"gemini-3.1-pro"}
data: {"candidates":[{"content":{"role":"model","parts":[{"text":" is Paris."}]},"index":0}],"modelVersion":"gemini-3.1-pro"}
data: {"candidates":[{"content":{"role":"model","parts":[]},"finishReason":"STOP","index":0}],"usageMetadata":{"promptTokenCount":16,"candidatesTokenCount":8,"totalTokenCount":24}}List models
The catalog is also exposed in Gemini Model-resource shape so Google clients can enumerate models.
curl https://api.airforce/v1beta/modelsNotes: the base URL is https://api.airforce/v1beta (or /v1), not Google's host. The model name comes from the URL path, not the request body. Only the first candidate is returned, and a subset of Gemini fields is translated — safetySettings and cachedContent are currently ignored. Billing, rate limits and smart routing apply exactly as on /v1/chat/completions.
Virheet
Airforce palauttaa normaalit HTTP-tilakoodit ja yhtenäisen virheenkuoren molemmille päätepisteille.
| Parameter | Type | Required | Description |
|---|---|---|---|
| 400 | invalid_request_error | Optional | Väärin muotoiltu JSON, pakollinen kenttä puuttuu, malli tuntematon. |
| 401 | invalid_request_error / auth_required | Optional | Puuttuva tai virheellinen API-avain. |
| 402 | insufficient_quota | Optional | Malli vaatii aktiivisen tilauksen tai positiivisen Pay-as-you-Go-saldon. |
| 403 | model_access_denied / insufficient_scope | Optional | Suunnitelman tai avainkohtaiset käyttöoikeudet estävät tämän pyynnön. |
| 404 | model_not_found | Optional | Pyydettyä mallia ei ole olemassa tai sinulla ei ole siihen pääsyä. |
| 429 | rate_limit_error | Optional | Pyyntökorko tai päiväkohtainen token cap ylitetty. |
| 503 | api_error / moderation_unavailable | Optional | Kaikki pyydetyn palveluntarjoajan ylävirran avaimet epäonnistuivat. |
{
"error": {
"message": "The requested model does not exist or you do not have access to it.",
"type": "model_not_found",
"param": null,
"code": "404"
}
}Kuvaileva slug on kentässä type. code on HTTP-tila merkkijonona (esim. "404"), ja param on null paitsi parametrin arvoalueen validointivirheissä, joissa se nimeää virheellisen parametrin.
Tutustu malleihin
Katso täydellinen luettelo mallin tunnuksista ja niiden ominaisuuslipuista (näkemys, työkalut, päättely, välimuisti, kontekstin pituus jne.) osoitteessa /docs/api/models.
curl https://api.airforce/v1/models \
-H "Authorization: Bearer sk-air-YOUR_API_KEY"