Api.Airforce
API REFERENCE

Chat-Completions

Generiere Chat-Antworten über 100+ Modelle aus einer API. Direkt kompatibel mit OpenAI Chat Completions, Anthropic Messages und Anthropic Responses.

Authentifizierung

Jede Anfrage benötigt einen Bearer-Token (deinen Airforce API-Key). Der Anthropic x-api-key Header wird auch an /v1/messages akzeptiert für SDK-Kompatibilität.

Authorization: Bearer sk-air-YOUR_API_KEY
# alt for /v1/messages:
x-api-key: sk-air-YOUR_API_KEY

POST /v1/chat/completions

OpenAI-kompatible Chat Completions. Funktioniert mit dem offiziellen openai SDK indem du base_url auf https://api.airforce/v1.

POSThttps://api.airforce/v1/chat/completions

Request-Body

ParameterTypeRequiredDescription
modelstringRequiredModel-ID. Nutze GET /v1/models um verfügbare IDs zu finden.
messagesarrayRequiredKonversationsverlauf. Jeder Eintrag hat { role: "system" | "user" | "assistant" | "tool", content }. Content ist ein String oder ein Array von Content-Blöcken (Vision, siehe unten).
max_tokensintegerOptionalMaximale Anzahl zu generierender Tokens. Begrenzt durch max_output_tokens des Modells.
temperaturefloatOptionalSampling-Temperatur, 0–2. Niedriger ist deterministischer. Default hängt vom Upstream-Provider ab.
top_pfloatOptionalNucleus-Sampling. Nutze entweder temperature oder top_p, nicht beides.
streambooleanOptionalWenn true, ist die Response ein Stream von Server-Sent Events. Siehe "Streaming" unten.
stream_optionsobjectOptional{ include_usage: boolean }. Wenn include_usage true ist, trägt der finale SSE-Chunk den Usage-Block.
stopstring | arrayOptionalBis zu 4 Stopp-Sequenzen. Generierung stoppt sobald eine produziert wird.
toolsarrayOptionalFunktionsdefinitionen die das Modell aufrufen darf. Siehe "Tool-Calling" unten.
tool_choicestring | objectOptional"auto" (default), "none", oder { type: "function", function: { name } } um einen spezifischen Call zu erzwingen.
response_formatobjectOptional{ type: "json_object" } zwingt das Modell, valides JSON auszugeben. Wird ignoriert für Modelle die das nicht unterstützen.
reasoning_effortstringOptionalOpenAI o1/o3-Stil Reasoning-Tiefe: "low" | "medium" | "high". Siehe "Reasoning & Thinking".
thinkingstring | objectOptionalProvider-übergreifender Thinking-Switch. "on" | "off" | "auto", oder Anthropic-Form { type: "enabled", budget_tokens: N }. Siehe "Reasoning & Thinking".
thinking_budgetintegerOptionalToken-Limit für den Reasoning-Trace des Modells (sofern der Provider eines exponiert).
ignore_defaultsbooleanOptionalÜberspringt die im Dashboard gespeicherten Per-Modell-Default-Parameter für diese Anfrage.

Einfaches Beispiel

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
  }'

Response-Format

ParameterTypeRequiredDescription
idstringOptionalStabile Completion-ID, z.B. "chatcmpl-abc123".
objectstringOptional"chat.completion" für Non-Streamed, "chat.completion.chunk" für Streamed.
createdintegerOptionalUnix-Timestamp (Sekunden).
modelstringOptionalEcho der angefragten Model-ID.
choicesarrayOptionalArray von Completion-Kandidaten: [{ index, message: { role, content, tool_calls? }, finish_reason }].
choices[].finish_reasonstringOptional"stop" | "length" | "tool_calls" | "content_filter".
usageobjectOptional{ prompt_tokens, completion_tokens, total_tokens, completion_tokens_details?, prompt_tokens_details?, cache_creation_input_tokens?, cache_creation? }. completion_tokens_details.reasoning_tokens wird gesetzt wenn das Modell eine Reasoning-Spur erzeugt hat. Cache-Felder erscheinen wenn der Upstream Prompt-Caching-Infos zurückgab: prompt_tokens_details.cached_tokens berichtet Cache-Reads (OpenAI-Standard), cache_creation_input_tokens aggregiert Writes, und cache_creation.ephemeral_5m_input_tokens / ephemeral_1h_input_tokens geben die TTL-Aufteilung.
{
  "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
  }
}

Reasoning & Thinking

Modelle die erweitertes Reasoning unterstützen, geben einen Thinking-Trace neben dem regulären Output zurück. Airforce normalisiert drei verschiedene Upstream-Konventionen zu einem einheitlichen Set kanonischer Parameter, die überall funktionieren.

Prüfe supports_reasoning: true auf einem Modell in GET /v1/models um zu sehen welche IDs diese Parameter akzeptieren.

Modelle mit Reasoning-Support

· live

Kanonische Parameter

ParameterTypeRequiredDescription
reasoning_effortstringOptional"low" | "medium" | "high". OpenAI o1/o3, GPT-5 Reasoning-Modelle und alle Router die darauf abbilden.
thinkingstring | objectOptional"on" | "off" | "auto" für einen Schnell-Toggle, oder { type: "enabled", budget_tokens: N } im Anthropic-nativen Format. Wird auf Claude Extended Thinking, Gemini Thinking und DeepSeek Reasoning abgebildet.
thinking_budgetintegerOptionalMaximale Tokens die das Modell für Reasoning aufwenden darf, bevor sichtbarer Output beginnt. Spiegelt budget_tokens.

Reasoning Effort (OpenAI-Stil)

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"
  }'

Extended Thinking (Anthropic-Stil)

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}
  }'

Der Reasoning-Trace selbst erscheint in choices[0].message.reasoning_content (OpenAI-Format) oder als thinking Blöcke in content (Anthropic-Format). Reasoning-Tokens werden abgerechnet und in usage.completion_tokens_details.reasoning_tokens.


Vision & Bild-Input

Modelle mit supports_vision: true akzeptieren Bilder als eingebettete Content-Blöcke. Entweder eine öffentliche URL oder eine base64-Data-URL — Größenlimits hängen vom Upstream-Modell ab.

Modelle mit Vision-Support

· live
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": [
        {"type": "text", "text": "What is in this image?"},
        {"type": "image_url", "image_url": {"url": "https://example.com/cat.jpg"}}
      ]
    }]
  }'

Tool-Calling

Modelle mit supports_tools: true können Funktionen aufrufen die du definierst. Das Modell gibt ein tool_calls Array zurück; du führst den Call aus und schickst das Ergebnis dann in einer tool Message zurück.

Modelle mit Tool-Calling-Support

· live

Anfrage

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"
  }'

Response mit Tool-Call

{
  "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"
  }]
}

Folge-Anfrage mit Tool-Ergebnis

{
  "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\"}"}
  ]
}

Streaming

Setze stream: true um partielle Completions als Server-Sent Events zu erhalten. Jedes Event ist ein JSON-Chunk mit der gleichen Form wie die Non-Streamed-Response, außer dass message ersetzt wird durch delta. Der Stream endet mit 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}
  }'

Wire-Format

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]

POST /v1/messages

Anthropic-kompatible Messages-API. Funktioniert mit dem offiziellen @anthropic-ai/sdk indem du baseURL auf https://api.airforce. setzt. Leitet für Non-Claude-Modelle transparent an OpenAI/Google/etc. weiter.

POSThttps://api.airforce/v1/messages

Request-Body

ParameterTypeRequiredDescription
modelstringRequiredModel-ID (Anthropic-Format oder geroutetes Alias).
messagesarrayRequiredJeder Eintrag: { role: "user" | "assistant", content: string | array }.
max_tokensintegerRequiredAnthropic-Pflichtfeld. Token-Limit für die Response.
systemstring | arrayOptionalSystem-Prompt. Übergib ein Array aus { type: "text", text, cache_control? } Blöcken um Cache-Prefix-Segmente zu markieren. Siehe "Prompt-Caching".
temperaturefloatOptional0–1.
top_pfloatOptionalNucleus-Sampling.
top_kintegerOptionalBegrenzt den Sampling-Pool auf die Top-K Tokens.
stop_sequencesarrayOptionalBis zu 4 Stopp-Sequenzen.
streambooleanOptionalWenn true, sendet einen Anthropic-Stil SSE-Event-Stream (siehe "Streaming").
toolsarrayOptionalAnthropic-Tool-Definitionen: { name, description, input_schema }. Die Response kann tool_use Content-Blöcke enthalten.
tool_choiceobjectOptional{ type: "auto" | "any" | "tool", name? }.
thinkingobjectOptionalAnthropic Extended Thinking: { type: "enabled", budget_tokens: N }.

Beispiel

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!"}
    ]
  }'

Response-Format

ParameterTypeRequiredDescription
idstringOptionalMessage-ID, z.B. "msg_01ABCxyz".
typestringOptionalImmer "message".
rolestringOptionalImmer "assistant".
contentarrayOptionalArray von Content-Blöcken: { type: "text" | "tool_use" | "thinking", … }.
modelstringOptionalEcho des angefragten Modells.
stop_reasonstringOptional"end_turn" | "max_tokens" | "stop_sequence" | "tool_use".
usageobjectOptional{ input_tokens, output_tokens, cache_read_input_tokens?, cache_creation_input_tokens?, cache_creation? }. Cache-Felder erscheinen wenn Prompt-Caching genutzt wurde. cache_creation.ephemeral_5m_input_tokens und ephemeral_1h_input_tokens geben die Write-Aufteilung pro TTL.

Streaming-Events

Anthropic SSE nutzt benannte Events statt einzelner JSON-Chunks. Jedes Event hat sowohl einen event: Namen als auch ein data: JSON-Payload.

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"}

Prompt-Caching

Auf /v1/messages mit Claude-Modellen markierst du ein Prefix als gecacht, indem du system als Array von Blöcken übergibst, wo das gecachte Segment cache_control: { type: "ephemeral" }. trägt. Folgeanfragen mit demselben Prefix zahlen den günstigeren Cache-Read-Tarif. Modelle mit supports_caching: true in /v1/models unterstützen das.

Modelle mit Prompt-Caching

· 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?"}
  ]
}

Wie Cache-Counts in der Response erscheinen

Cache-Token-Counts werden im jeweils nativen Format zurückgegeben, sodass SDKs (openai, @anthropic-ai/sdk, @google/genai) sie ohne Custom-Code lesen. Felder mit Wert 0 werden weggelassen, damit Non-Cache-Responses schlank bleiben.

/v1/chat/completions (OpenAI-Format)

"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-Format)

"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-Format)

"usageMetadata": {
  "promptTokenCount": 2104,
  "candidatesTokenCount": 147,
  "totalTokenCount": 2251,
  "cachedContentTokenCount": 1980
}

Wo Caching greift

Explizite cache_control-Marker werden auf /v1/messages und /v1/chat/completions für Claude-Modelle honoriert — setze sie auf system- oder message-content-Blöcke. Viele andere Anbieter (OpenAI-Familie, DeepSeek, Gemini) cachen automatisch: du sendest keine Marker und siehst einfach cached_tokens in der Antwort, sobald ein ausreichend langer Prefix wiederverwendet wird.

Cache-Dauer: 5 Minuten oder 1 Stunde

Ein gecachter Prefix lebt standardmäßig 5 Minuten, und der Timer wird bei jedem Treffer erneuert. Für einen länger lebenden Prefix füge ttl: "1h" zum Marker hinzu. Die Antwort meldet jede TTL separat unter cache_creation.

"cache_control": { "type": "ephemeral", "ttl": "1h" }

Beispiel: erst Write, dann Read

Sende denselben Request zweimal (das Caching-Beispiel oben). Der erste Aufruf, der den Prefix sieht, zahlt einen einmaligen Cache-Write; identische Aufrufe innerhalb der TTL zahlen den viel günstigeren Cache-Read.

Erster Aufruf — Cache-Write (usage-Auszug):

"usage": {
  "input_tokens": 2104,
  "output_tokens": 12,
  "cache_creation_input_tokens": 1980,
  "cache_read_input_tokens": 0
}

Zweiter identischer Aufruf innerhalb der TTL — Cache-Read:

"usage": {
  "input_tokens": 2104,
  "output_tokens": 12,
  "cache_creation_input_tokens": 0,
  "cache_read_input_tokens": 1980
}

Limits & Kosten

  • Claude erfordert einen Mindest-Prefix (ca. 1024 Tokens; bei manchen Modellen mehr). Kürzere Prefixe werden schlicht nicht gecacht.
  • Bis zu 4 Cache-Breakpoints pro Request, und der gecachte Prefix muss über Aufrufe hinweg byte-identisch sein — schon eine Änderung um ein Zeichen verfehlt den Cache.
  • Cache-Writes kosten mehr als normaler Input (5m ≈ 1,25×, 1h ≈ 2×); Cache-Reads kosten viel weniger (≈ 0,1×). Die Cache-Preise je Modell stehen auf der Preisseite.

POST /v1/responses

OpenAI Responses-API für stateful Konversationen. Gleiche Bearer/x-api-key Auth. Cache-Counts erscheinen als input_tokens_details.cached_tokens (Read) plus cache_creation_input_tokens + cache_creation.ephemeral_* (Writes) — analog zu /v1/chat/completions.

POSThttps://api.airforce/v1/responses

Fehler

Airforce gibt Standard-HTTP-Statuscodes und einen einheitlichen Fehler-Envelope für beide Endpoints zurück.

ParameterTypeRequiredDescription
400invalid_requestOptionalFehlerhaftes JSON, fehlendes Pflichtfeld, unbekanntes Modell.
401authentication_errorOptionalAPI-Key fehlt oder ist ungültig.
403permission_errorOptionalPlan- oder Per-Key-Permissions verweigern diese Anfrage.
429rate_limitOptionalRequest-Rate oder tägliches Token-Limit überschritten.
503upstream_errorOptionalAlle Upstream-Keys für den angefragten Provider sind ausgefallen.
{
  "error": {
    "message": "Model 'gpt-99' not found.",
    "type": "invalid_request",
    "param": "model",
    "code": "model_not_found"
  }
}

Modelle entdecken

Siehe die vollständige Liste aller Model-IDs und ihrer Capability-Flags (Vision, Tools, Reasoning, Caching, Context-Length, …) auf /docs/api/models.

curl https://api.airforce/v1/models \
  -H "Authorization: Bearer sk-air-YOUR_API_KEY"