# AxForge — the API, in full

AxForge is European AI infrastructure: an OpenAI-compatible inference API and whole GPUs by the hour, run in the EU. This page is generated from the live catalogue, price sheet and fleet — it is current, not a snapshot.

## The basics

| | |
|---|---|
| Base URL | `https://api.axforge.ai/v1` |
| Auth | `Authorization: Bearer $AXFORGE_API_KEY` |
| Compatibility | OpenAI API shape — the official SDKs work unchanged, only `base_url`, key and model id differ |
| Region | `eu-se-1` Stockholm (serverless), `eu-es-1` Málaga (dedicated GPUs) |
| Retention | Prompts and completions are processed in memory and never stored. Only counts, timestamps and status are kept, for billing |
| Keys | Created in the console: https://console.axforge.ai/keys |

```bash
curl -sS https://api.axforge.ai/v1/chat/completions \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gemma-4-26b-a4b-nvfp4","messages":[{"role":"user","content":"Hello"}]}'
```

## Models

Use the id in the `model` field. `Available` is hot now; `On request` boots on demand and the first call waits.

| Model | id | Type | Size · context | Price | Status |
|---|---|---|---|---|---|
| Gemma-4 26B | `gemma-4-26b-a4b-nvfp4` | Chat · text | 262k ctx | see /docs/models/ | On request |
| Mistral Small 3.2 | `mistral-small-3.2-24b-nvfp4` | Chat · text | 32k ctx | see /docs/models/ | On request |
| Qwen3 30B A3B | `qwen3-30b-a3b-nvfp4` | Chat · text | 65k ctx | see /docs/models/ | On request |
| Qwen3.6 35B A3B | `qwen3.6-35b-a3b-nvfp4` | Chat · text | 65k ctx | see /docs/models/ | On request |
| Qwen3.8 27B | `qwen3.8-27b-nvfp4` | Chat · text | — | €0.29 in · €1.77 out / 1M | Available |
| Qwen3 Embedding | `qwen3-embed` | Embeddings | 32k ctx | €0.02 in · €0.00 out / 1M | Available |
| ERNIE Image Turbo | `ernie-image-turbo` | Image generation | — | see /docs/models/ | Available |
| FLUX.2 Klein 4B | `qwen-image-edit` | Image generation | — | see /docs/models/ | Available |
| Qwen-Image | `qwen-image-dedicated` | Image generation | — | see /docs/models/ | On request |
| SDXL | `sdxl` | Image generation | — | see /docs/models/ | On request |
| MiniMax Music 3 | `planned-music-tbd` | Music | — | see /docs/models/ | Available |
| Piper (Text-to-Speech) | `piper-lessac` | Speech | — | see /docs/models/ | Available |
| Whisper (Speech-to-Text) | `whisper-base` | Speech | — | see /docs/models/ | Available |
| LTX-Video | `ltx-video` | Video generation | — | see /docs/models/ | Coming |
| MiniMax H3 | `minimax-h3` | Video generation | — | see /docs/models/ | Coming |
| Wan 2.2 5B | `wan2.2-ti2v-5b` | Video generation | — | see /docs/models/ | Coming |

## Endpoints

### `/v1/chat/completions`

Chat and tool use. `stream: true` gives server-sent events.

```json
{"model":"<id>","messages":[{"role":"user","content":"…"}],"stream":false}
```

### `/v1/embeddings`

Vectors for search and RAG.

```json
{"model":"qwen3-embed","input":"text to embed"}
```

### `/v1/images/generations`

Image generation.

```json
{"model":"<id>","prompt":"a red bicycle","size":"1024x1024"}
```

### `/v1/images/edits`

Image editing from an input image.

```json
multipart: model, image, prompt
```

### `/v1/audio/transcriptions`

Speech to text.

```json
multipart: model, file
```

### `/v1/audio/speech`

Text to speech.

```json
{"model":"piper-lessac","input":"hello"}
```

### `/v1/audio/music`

Music generation.

```json
{"model":"minimax-music3","prompt":"a calm piano piece"}
```

### `/v1/models`

What is served right now.

```json
GET
```

## Errors

Every error is JSON: `{"error":{"message":…,"type":…,"code":…}}`.

| Status | Means | Do |
|---|---|---|
| 400 | The request body is wrong | Read `error.message` — it names the field |
| 401 | No key, or a key that is gone | Check the Authorization header |
| 402 | Out of allowance or credit | Top up in the console; the message says which |
| 403 | The key may not use that model or endpoint | Check the key's scope in the console |
| 404 | Unknown model id or path | Call `/v1/models` for the live list |
| 413 | The body is too large | Split the input; embeddings take batches |
| 429 | Rate limited | Back off and retry with jitter; the headers say when |
| 502 | The model could not be reached | Retry once; if it persists the status page and the forum will say |
| 504 | The model took too long | Raise your client timeout for image and video models — minutes, not seconds |

## Dedicated GPUs

Whole machines by the hour with SSH, one tenant each. Prices no VAT configured.

| GPU | Memory | Status | Free now | From |
|---|---|---|---|---|
| NVIDIA DGX Spark (GB10) | 128 GB unified memory | Available | 0/1 | from €0.55/h |
| NVIDIA RTX 6000 Pro | 96 GB GDDR7 | Request capacity | — | from €1.06/h |
| NVIDIA RTX 5090 | 32 GB GDDR7 each | Request capacity | — | from €0.59/h |
| NVIDIA RTX 3090 | 24 GB GDDR6X | Request capacity | — | from €0.42/h |
| NVIDIA RTX 3060 | 12 GB each · 24 GB the pair | Available | 2/1 | from €0.16/h |
| NVIDIA H100 | 80 GB HBM3 | Request capacity | — | quoted |
| NVIDIA H200 | 141 GB HBM3e | Request capacity | — | quoted |
| NVIDIA B200 | 192 GB HBM3e | Request capacity | — | quoted |

Rent one: https://console.axforge.ai/gpus

## Where to read more

- [Overview](https://dev.axforge.ai/docs/) — What the platform is, and the shape of the API.
- [Quickstart](https://dev.axforge.ai/docs/quickstart/) — Key, first call, the real response — in one page.
- [Glossary](https://dev.axforge.ai/docs/glossary/) — The words we use, defined once.
- [Chatbox starter](https://dev.axforge.ai/docs/starters/) — A streaming chatbox in plain JavaScript — paste your key and it runs.
- [Test a call](https://dev.axforge.ai/docs/test-a-call/) — Run a real call and see how it lands, and why if it does not.
- [Models & pricing](https://dev.axforge.ai/docs/models/) — Every served model, its id and what it costs.
- [Chat completions](https://dev.axforge.ai/docs/chat/) — /v1/chat/completions — streaming, tools, JSON mode.
- [Embeddings](https://dev.axforge.ai/docs/embeddings/) — /v1/embeddings — 1024-dim vectors, batching, limits.
- [Images](https://dev.axforge.ai/docs/images/) — /v1/images — generate and edit; sizes and formats.
- [Speech & music](https://dev.axforge.ai/docs/audio/) — Transcription, text-to-speech and music.
- [Errors & limits](https://dev.axforge.ai/docs/errors-limits/) — Every status code, what causes it, what to do.
- [Use it from your stack](https://dev.axforge.ai/docs/connect/) — The SDKs, the editors and the CLIs, each with its real config.
- [OpenAI SDK](https://dev.axforge.ai/docs/connect/openai-sdk/) — The official SDK, base URL changed.
- [Vercel AI SDK](https://dev.axforge.ai/docs/connect/vercel-ai-sdk/) — Edge and node, streaming.
- [aider](https://dev.axforge.ai/docs/connect/aider/) — Pair programming in the terminal.
- [Continue](https://dev.axforge.ai/docs/connect/continue/) — The VS Code and JetBrains extension.
- [Cline](https://dev.axforge.ai/docs/connect/cline/) — The autonomous coding extension.
- [Codex CLI & Claude Code](https://dev.axforge.ai/docs/connect/codex-claude-code/) — Both agents against our endpoint.
- [Kimi Code CLI](https://dev.axforge.ai/docs/connect/kimi/) — The CLI, pointed here.
- [LiteLLM](https://dev.axforge.ai/docs/connect/litellm/) — A proxy in front of many providers.
- [Open WebUI](https://dev.axforge.ai/docs/connect/open-webui/) — A chat UI you host yourself.
- [LibreChat](https://dev.axforge.ai/docs/connect/librechat/) — The multi-model chat front end.
- [llm (Datasette CLI)](https://dev.axforge.ai/docs/connect/llm/) — Simon Willison's llm, configured.
- [How GPU rentals work](https://dev.axforge.ai/docs/gpu-rentals/) — On-demand and scheduled machines, SSH, the clock.
- [Regions & data handling](https://dev.axforge.ai/docs/regions-data/) — eu-se-1, eu-es-1, zero retention, what is logged.
- [Rules & responsibilities](https://dev.axforge.ai/docs/responsibilities/) — What you may run, and what we do.

- [The forum](https://dev.axforge.ai/) — questions and answers, one thread per model, GPU and docs page
- [The catalogue](https://axforge.ai/models/) — every open model we track, with the ones we run marked
- [axforge.ai](https://axforge.ai/) — the product pages

## If you are an agent acting for someone

Use their own key, never a shared one. Prefer a hot model for interactive work. Image, video and music calls can take minutes — set the client timeout accordingly rather than retrying, which doubles the work. If something is wrong here, the page it belongs to has a thread and a human reads it.


---

# The documentation, in full



## Overview (/docs/)


# AxForge documentation

Everything speaks the OpenAI API shape. Point the SDK you already use at
    our base URL, swap the key and the model name, and chat, embeddings, images,
    speech and music all work behind the same key — served in the EU, with zero
    prompt retention.

## The API in four lines

        | Base URL | https://api.axforge.ai/v1 |  |

        | Auth | `Authorization: Bearer YOUR_AXFORGE_KEY` — your key is created with your account; copy it from the console |  |

        | Region | eu-se-1 · Stockholm — pinned on your key; all inference runs in-region |  |

        | Retention | Zero. Prompts and completions are never written to disk, logged, or trained on — the commitment |  |

## One request, end to end

```
$ curl https://api.axforge.ai/v1/chat/completions \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen3.8-27b-nvfp4",
       "messages": [{"role": "user", "content": "Hello from Stockholm"}]}'
```

That is the whole integration. The quickstart
    does the same with the OpenAI Python SDK in three steps.

## Every endpoint behind one key

        | Capability | Endpoint | Model | Price |  |

        Chat, tools, vision | /v1/chat/completions | qwen3.8-27b-nvfp4 | €0.29 / €1.77 per 1M |  |

        Embeddings (1024-dim) | /v1/embeddings | qwen3-embed | €0.015 / 1M |  |

        Image generation | /v1/images/generations | ernie-image-turbo | €0.05 / image |  |

        Image editing | /v1/images/edits | flux2-klein-4b | €0.06 / edit |  |

        Speech to text | /v1/audio/transcriptions | whisper | €0.005 / minute |  |

        Text to speech | /v1/audio/speech | piper | €2.95 / 1M characters |  |

        Music generation | /v1/audio/music | minimax-music3 | €0.04 / 10 seconds |  |

    Chat prices are launch pricing, per 1M input / output tokens.
    Full details on Models & pricing.

## Start

        | Quickstart | Create an account, copy your key from the console, send your first request. |  |

        | Serverless Models | The product page — what is served, where it runs, what it costs. |  |

        | Glossary | Every term you meet — tokens, embeddings, regions, the trust vocabulary — in plain language. |  |

        | Models & pricing | Every served model, its API name and price, plus models deployable on dedicated hardware. |  |

## Use AxForge with your stack

Because everything speaks the OpenAI shape, your existing tools work by
    changing the base URL to `api.axforge.ai/v1`. Step-by-step guides:

        | All tools | The one pattern, plus a card for each guide below. |  |

        | OpenAI SDK · Vercel AI SDK | Python, Node, TypeScript — change the base URL, keep your code. |  |

        | aider · Continue · Cline · Kimi | Coding assistants that drop straight in. |  |

        | Codex & Claude Code | Point them straight at us — Responses & Messages are served natively. |  |

        | LiteLLM | Optional gateway — front AxForge for budgets, fan-out, or many providers. |  |

## API reference

        | Chat completions | Request shape, streaming, tool calls, reasoning output, image input. |  |

        | Embeddings | 1024-dimension vectors, batching, curl and Python. |  |

        | Image generation & editing | PNG generation with ERNIE, instruction edits with FLUX — and when to use which. |  |

        | Speech & music | Transcription, text to speech, and full music tracks with lyrics. |  |

## Platform

        | How GPU rentals work | The first-come, first-served queue, offers and payment, on-demand billing (4 h min · 48 h hard cap · no refunds), the off switch, and the no-data-kept rule. |  |

        | Regions & data handling | Stockholm (eu-se-1) for serverless inference, Málaga (eu-es-1) for dedicated GPUs, region pinning, what we keep and what we never keep. |  |

        | Dedicated DGX Spark (GB10) | Rent the hardware behind the API with full SSH access — from €0.55/hour by the hour, week, month or year. |  |

        | Errors & limits | Error shapes, the 503 retry pattern, and the honest concurrency picture. |  |

        | Rules & responsibilities | What you can build and must not, the controller/processor split, and examples by use case. |  |

## What these docs promise

Every number here is real: prices are the prices, and limits are the limits we serve
    today. Where a model is available as a managed deployment rather than on the
    serverless API, the page says so.
    If you find a gap between these docs and the API's behavior, that is a bug —
    tell an engineer.

      Quickstart &rarr;



## Quickstart (/docs/quickstart/)


# Quickstart

Everything on AxForge speaks the OpenAI API shape. If you have used the
    OpenAI SDK, you already know this API — the only changes are the base URL,
    your key, and the model name. Three steps to your first streamed token.

## 1. Create an AxForge account

Create an account. Your API key
    is created with it. Every new account currently includes 5M serverless tokens/month at launch.

## 2. Copy your API key from the console

Your key is on the API keys page
    of the console. It is pinned to eu-se-1 · Stockholm,
    and all inference for the key runs in that region.

## 3. Send your first request

Point the SDK you already use at `https://api.axforge.ai/v1`:

    Python

```
# pip install openai — the official SDK, unchanged
from openai import OpenAI

client = OpenAI(
    base_url="https://api.axforge.ai/v1",
    api_key="YOUR_AXFORGE_KEY",
)
```

```
$ curl https://api.axforge.ai/v1/chat/completions \
    -H "Authorization: Bearer $AXFORGE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"model":"qwen3.8-27b-nvfp4","max_tokens":60,
         "messages":[{"role":"user","content":"Say hello from Stockholm in one sentence."}]}'
```

```
# Windows PowerShell cannot pass inline JSON to curl.exe — not with single quotes,
# not escaped, not from a variable. This is its own client, and it has no such problem.
PS> $key = "YOUR_AXFORGE_KEY"
PS> $body = @{ model = 'qwen3.8-27b-nvfp4'; max_tokens = 60; messages = @(@{ role = 'user'; content = 'Say hello from Stockholm in one sentence.' }) } | ConvertTo-Json -Depth 5
PS> $r = Invoke-RestMethod -Uri https://api.axforge.ai/v1/chat/completions -Method Post -Headers @{ Authorization = "Bearer $key" } -ContentType 'application/json' -Body $body
PS> $r.choices[0].message.content
```

```
REM cmd does not strip single quotes, so the inner ones are escaped instead.
C:\> curl -s https://api.axforge.ai/v1/chat/completions -H "Authorization: Bearer %AXFORGE_API_KEY%" -H "Content-Type: application/json" -d "{\"model\":\"qwen3.8-27b-nvfp4\",\"max_tokens\":60,\"messages\":[{\"role\":\"user\",\"content\":\"Say hello from Stockholm in one sentence.\"}]}"
```

Every one of these was run on the system it names before it was printed here.
In **PowerShell 7** (`pwsh`) the bash line works too; in Windows
PowerShell 5.1 — the one that opens by default — it cannot. `$PSVersionTable.PSVersion`
tells you which you are in.

What comes back — the standard shape, with the tokens you were billed for in `usage` (this is a real answer, recorded 2026-09-18; the ids and the wording will differ):

```
{
  "id": "chatcmpl-a76c352750b8914a",
  "object": "chat.completion",
  "model": "qwen3.8-27b-nvfp4",
  "choices": [{ "index": 0, "finish_reason": "stop",
                "message": { "role": "assistant", "content": "Hello from Stockholm!" } }],
  "usage": { "prompt_tokens": 20, "completion_tokens": 5, "total_tokens": 25 }
}
```

No answer? Run the self-test — one click in the console tells you which step failed and how to fix it — and the errors & limits page lists every status the API returns.

### Stream a completion

```
r = client.chat.completions.create(
    model="qwen3.8-27b-nvfp4",
    stream=True,
    messages=[{"role": "user", "content": "Hello from Stockholm"}],
)
for chunk in r:
    print(chunk.choices[0].delta.content or "", end="")
```

Streaming sends one `chat.completion.chunk` per token as server-sent events — the first two look like this, and the last one carries `usage`:

```
data: {"object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant","content":""}}]}
data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"Hello"}}]}
```

    The model is Qwen3.8 27B at €0.29 / 1M input tokens and €1.77 / 1M output tokens (launch pricing), with a 262,144-token context. Streaming responses include usage.

## Everything else behind the same key

        | Capability | Endpoint | Model name |  |

        | Chat, tools, vision | /v1/chat/completions | qwen3.8-27b-nvfp4 |  |

        | Embeddings (1024-dim) | /v1/embeddings | qwen3-embed |  |

        | Image generation | /v1/images/generations | ernie-image-turbo |  |

        | Image editing | /v1/images/edits | flux2-klein-4b |  |

        | Speech to text | /v1/audio/transcriptions | whisper |  |

        | Text to speech | /v1/audio/speech | piper |  |

        | Music generation | /v1/audio/music | minimax-music3 |  |

Each has its own page in these docs with request and response shapes and
    practical guidance — and a product page on Serverless Models.

## Zero retention, verifiable

Prompts and completions are processed in memory in the EU — never written
    to disk, logged, retained, or used for training. Only request metadata
    (token counts, timestamps, status) is kept for billing. The commitment in
    full: axforge.ai/privacy; the data-residency
    evidence is in the Trust Centre.

      &larr; Overview
      Glossary &rarr;



## Glossary (/docs/glossary/)


# Glossary

    The words you meet building on AxForge, in plain language and
    explained the way AxForge uses them. If a term means something specific here
    — like _region pinning_ or _zero retention_ — this is where it
    is pinned down, with links to the page that goes deeper.

      API basics
      Capabilities
      Compatibility & tooling
      Regions & metering
      Trust & compliance

## API basics

The request you send, the key that authorises it, and the units you are
    billed in. Everything speaks the OpenAI shape — see the
    Quickstart.

      API key #
      A secret token (prefixed `orx_live_`) that authenticates your
      requests. Send it as `Authorization: Bearer <key>` (or
      `x-api-key`). A key is created with your account and shown in the
      console; it belongs to one tenant, is pinned to one EU
      region, and can be revoked at any time. Treat it like a password — never ship
      it in client-side code.
      See also: Quickstart · Errors & limits

      Base URL #
      The address your SDK or tool points at instead of OpenAI:
      `https://api.axforge.ai/v1`. Because the API is OpenAI-compatible,
      pointing an existing client at this base URL — plus your key and a model name —
      is usually the entire integration.
      See also: Use with your stack

      Endpoint #
      A path under the base URL that does one job:
      `/chat/completions`, `/embeddings`,
      `/images/generations`, `/audio/speech`, and so on. Every
      endpoint takes and returns the same JSON shapes the OpenAI endpoints do.
      See also: Chat completions

      Model #
      The open-weight system that produces the answer. You choose one per request
      with the `model` field. Models can be named by a stable role
      (`chat`, `agentic` for tool-heavy work, `vision`,
      `embeddings`) or by their exact version (`qwen3.8-27b-nvfp4`)
      — both resolve to the same served model. Call `GET /v1/models` for the
      live list.
      See also: Models & pricing · Model catalogue

      Token #
      The unit a model reads and writes in — roughly ¾ of a word of English.
      Prompts are counted as _input_ tokens and answers as _output_
      tokens; pricing and your usage balance are both in tokens. Every response
      carries a `usage` object with the exact counts.
      See also: Pricing · Usage

      Context window #
      The maximum number of tokens a model can consider at once — prompt plus
      answer. Exceed it and the oldest content is dropped or the request is rejected.
      Each model lists its window on the models page.
      See also: Models & pricing

      Streaming (SSE) #
      Set `stream: true` and the answer arrives token by token as
      server-sent events, ending with `data: [DONE]` — so a UI can show
      text as it is generated. AxForge streams include a final `usage`
      chunk so streamed answers are metered too.
      See also: Chat completions

      System / user / assistant message #
      The `messages` array carries the conversation. A
      _system_ message sets behaviour and rules, _user_ messages are
      the human's turns, and _assistant_ messages are the model's prior
      replies. Send the whole history each turn — the API is stateless.
      See also: Chat completions

      Temperature #
      A 0–2 dial on randomness. Low (0–0.3) is focused and repeatable — good for
      extraction and code; high (0.8+) is more varied — good for brainstorming. It
      does not change what the model knows, only how it samples.
      See also: Chat completions

      Usage #
      The token counts returned with every completion
      (`prompt_tokens`, `completion_tokens`,
      `total_tokens`). AxForge records these against your tenant's balance;
      prompts and answers themselves are never stored.
      See also: Metering · Regions & data

      Rate limit #
      The ceiling on requests per minute for a key. Cross it and you get an
      HTTP `429` with a `Retry-After` header — back off and
      retry. Limits protect shared capacity and can be raised for production traffic.
      See also: Errors & limits

## Capabilities

What the one key unlocks — text, vectors, images, and audio — each on an
    OpenAI-shaped endpoint.

      Chat completion #
      The core text endpoint: send a list of messages, get a reply. Handles
      instructions, Q&A, extraction, code, and multi-turn conversation, with
      optional tools and image inputs.
      See also: Chat completions

      Tool calling (function calling) #
      You describe functions the model may call; when useful it returns a
      structured `tool_calls` request instead of prose, your code runs the
      function and feeds the result back. This is the mechanism agents and
      MCP tools are built on.
      See also: Chat completions · MCP

      Vision #
      Passing an image alongside text in a chat request so the model can read,
      describe, or reason about it — screenshots, documents, diagrams, photos.
      See also: Chat completions

      Embedding #
      A vector of numbers that captures the meaning of a piece of text, so that
      similar meanings sit close together. The building block of search,
      recommendation, and retrieval-augmented generation. AxForge returns 1024-dim
      vectors.
      See also: Embeddings · Semantic search

      Vector / semantic search #
      Finding results by meaning rather than exact keywords: embed your documents
      and the query, then compare vectors. The retrieval half of RAG (retrieval-
      augmented generation), where you fetch relevant text and pass it to the model
      as context.
      See also: Embeddings

      Reranking #
      A second pass that scores a shortlist of candidate documents against a query
      and reorders them by true relevance — sharper than vector similarity alone, and
      a common step between search and the model.
      See also: Embeddings

      Image generation #
      Creating a picture from a text prompt via
      `/v1/images/generations`. The response carries the image as
      base64 PNG in `data[].b64_json`.
      See also: Image generation & editing

      Image editing #
      Changing an existing image from an instruction — pass the source image plus
      a prompt to `/v1/images/edits` and get an edited PNG back.
      See also: Image generation & editing

      Transcription (speech to text) #
      Turning an uploaded audio file into text via
      `/v1/audio/transcriptions` — a multipart file upload, OpenAI Whisper
      shape.
      See also: Speech & music

      Speech synthesis (text to speech) #
      Turning text into spoken audio via `/v1/audio/speech`.
      See also: Speech & music

      Music generation #
      Composing an audio track from a prompt (and optional lyrics) via
      `/v1/audio/music`.
      See also: Speech & music

## Compatibility & tooling

Why your existing tools work, and the few places the ecosystem has more than
    one API shape. The practical guides live in
    Use with your stack.

      OpenAI-compatible #
      AxForge implements the same HTTP endpoints, request bodies, and response
      shapes as OpenAI's API. Any client that can target a custom base URL — SDK,
      CLI, gateway, or app — works against AxForge by changing three things: the base
      URL, the key, and the model name.
      See also: OpenAI alternative in Europe · Use with your stack

      Chat Completions API #
      The widely-supported `/v1/chat/completions` surface — messages in,
      a choice out. The one nearly every tool speaks; AxForge serves it (alongside the
      Responses and Messages surfaces).
      See also: Chat completions

      Responses API #
      A newer OpenAI surface (`/v1/responses`) that some tools — notably
      OpenAI's Codex CLI and the default path of a few SDKs — now prefer. AxForge serves
      it natively at `api.axforge.ai/v1/responses`, alongside Chat Completions,
      so Responses-only clients point straight at us.
      See also: Codex & Claude Code

      Messages API (Anthropic) #
      Anthropic's `/v1/messages` surface, which Claude Code speaks. It is
      a different shape from OpenAI's, and AxForge serves it natively at
      `api.axforge.ai/v1/messages` — so a Claude-native tool points straight
      at us, no shim required.
      See also: Codex & Claude Code

      SDK #
      A library that wraps the HTTP API for a language — the official OpenAI
      SDKs (Python, Node) and the Vercel AI SDK are the common ones. All of them take
      a base-URL option, which is where you point them at AxForge.
      See also: OpenAI SDK · Vercel AI SDK

      Gateway #
      A service that sits in front of one or more model providers behind a single
      OpenAI-compatible endpoint — for routing, fallback, budgets, or key management.
      AxForge is a provider you can put behind a gateway; a gateway is not a
      substitute for a provider.
      See also: LiteLLM

      MCP (Model Context Protocol) #
      An open protocol that lets an AI app (the _host_, e.g. an IDE agent)
      connect to external tools and data through _MCP servers_. It is a
      client-side protocol, separate from how inference is served: MCP tools are
      driven by the model's tool calling in ordinary chat
      requests, so AxForge powers MCP-based agents without needing to "speak MCP"
      itself.
      See also: Use with your stack

      LiteLLM #
      An open-source proxy that fronts an OpenAI-compatible upstream like AxForge
      and re-exposes it on the Chat Completions, Anthropic Messages, and Responses
      surfaces at once. AxForge serves all three natively, so LiteLLM is optional —
      reach for it when you want a gateway (budgets, fan-out, many providers).
      See also: LiteLLM

## Regions & metering

Where inference runs, how you keep it there, and what is kept afterwards.

      Region #
      A physical location where your workload runs: `eu-se-1`
      (Stockholm, Sweden) for serverless inference and `eu-es-1` (Málaga,
      Spain) for dedicated GPU rental. The console shows the region and machine
      your key runs on, and every response carries the model identity.
      See also: Regions & data · Data residency

      Data residency #
      The guarantee that your requests are processed and any metadata is kept
      within a chosen jurisdiction — for AxForge, the EU. The basis for GDPR and
      sovereignty commitments.
      See also: Data residency · GDPR

      EU-hosted / sovereign AI #
      Inference on infrastructure located and operated in the EU, on open-weight
      models, with no dependency on a non-EU cloud in the request path — so data does
      not leave the jurisdiction to be processed.
      See also: Sovereign AI cloud · EU AI API

      Region pinning #
      Binding a key to one region so inference only ever runs there. Every API
      key is pinned to `eu-se-1` (Stockholm); the console shows the region
      and machine, and every response carries the model identity.
      See also: Regions & data

      Zero retention #
      Prompts and completions are processed and discarded — never written to disk,
      logged, retained, or used for training. Only request metadata (token counts,
      timestamps, status) is kept, and only for billing.
      See also: Retention · Privacy

      In-memory processing #
      Handling a request entirely in RAM for the moment it is served, with nothing
      about its content persisted afterwards — how zero retention is achieved in
      practice.
      See also: Retention

      Tenant #
      Your isolated account boundary. Keys, usage, and any stored configuration
      belong to a tenant, and one tenant can never see another's data. Signing up
      creates your own tenant.
      See also: Regions & data

      Workspace #
      A named project inside a tenant — a place to group an agent or deployment,
      its knowledge, and its settings in the console. Optional for raw API use.
      See also: Console

      Deployment #
      A configured, addressable instance of an agent or endpoint you have published
      — with its own public slug and access controls — as opposed to a raw model call.
      See also: Console

      Usage record / metering #
      The billing event AxForge writes after a token-priced call, recording the
      model and token counts against your tenant's balance. It captures counts and
      metadata only — never the prompt or the answer.
      See also: Usage · Pricing

## Trust & compliance

The vocabulary that shows up in procurement, DPAs, and audits — defined as
    they apply to AxForge. This is orientation, not legal advice.

      GDPR #
      The EU General Data Protection Regulation, governing how personal data is
      processed. EU-hosted, zero-retention inference is what makes AxForge
      straightforward to use under it.
      See also: GDPR & AI · Trust centre

      DPA (Data Processing Agreement) #
      The contract that sets out how a processor handles personal data on a
      controller's behalf. AxForge offers one for customers who send personal data
      through the API.
      See also: DPA

      Sub-processor #
      A third party a processor uses to help deliver the service. AxForge's
      EU-hosted design keeps this list short and in-jurisdiction; it is published for
      transparency.
      See also: Trust centre · DPA

      Data controller / processor #
      Under GDPR, the _controller_ decides why and how personal data is
      processed (you), and the _processor_ acts on the controller's
      instructions (AxForge, for the data you send).
      See also: DPA

      EU AI Act #
      EU regulation classifying AI systems by risk and setting obligations
      accordingly. Your obligations depend on what you build; AxForge provides the
      transparency inputs (model provenance, region, retention) you need to document
      it.
      See also: EU AI API · Model transparency

      Model transparency #
      Publishing which open-weight models serve each capability, and where, so you
      can record provenance for your own compliance. AxForge's models are open-weight
      and named per capability.
      See also: Model transparency · Models & pricing

      No-training commitment #
      AxForge does not train on customer prompts or completions. Combined with
      zero retention, your content is used to serve your request and nothing else.
      See also: Retention · Privacy

      PII (personal data) #
      Information that identifies a person. You remain the controller for any PII
      you send; AxForge's zero-retention processing means it is not persisted, but
      handling it responsibly — minimising and having a lawful basis — is your call.
      See also: Rules & responsibilities · GDPR

      &larr; Quickstart
      Models & pricing &rarr;



## Chatbox starter (/docs/starters/)


# A chatbox you can run in one minute

A tiny streaming chatbox in plain HTML, CSS and JavaScript. No framework, no build step,
    no dependencies. Paste your API key and it talks to AxForge — replies stream in as they are
    generated. The API speaks the OpenAI shape, so the same code runs against any
    OpenAI-compatible endpoint by changing two lines.

Open the live demo
    Download the ZIP

Need a key? Create one — new accounts include
    free serverless tokens each month.

## Three fields, and it works

The only AxForge-specific parts are the base URL, your key and the model name. Everything
    else is the standard OpenAI request shape.

```
const res = await fetch("https://api.axforge.ai/v1/chat/completions", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + YOUR_KEY,
  },
  body: JSON.stringify({
    model: "qwen3.8-27b",
    messages: [{ role: "user", content: "Hello!" }],
    stream: true,
  }),
});
```

The download reads the streamed reply token by token and prints it. That loop is the other
    interesting part of `app.js` — about a dozen lines, commented.

## Four files, nothing hidden

Read it, change it, keep it. There is no toolchain to learn.

      | File | What it does |  |

      | `index.html` | The page: a settings panel for your key and model, a message log, and the composer. Open it in a browser. |  |

      | `app.js` | The logic: send the conversation, read the SSE stream, render each token. About 120 lines — start here. |  |

      | `styles.css` | Self-contained styling, no framework, safe to replace with your own. |  |

      | `README.md` | How to run it two ways, how to get a key, and the note on keys in the browser. |  |

## Keys in the browser are for trying it out

This starter calls the API straight from the browser, so your key is in the page and stored
    only in your browser. That is fine for experimenting on your own machine. For anything public,
    keep the key on a small server and have the browser talk to that server instead — never ship a
    real key in front-end code. The chat reference shows the server-side
    shape, and the quickstart gets you a key and a first call.



## Test a call (/docs/test-a-call/)


# Run a test call, see exactly how it lands

Make a real call from your side and watch how it goes through on ours — whether it
    connected, whether your key and quota passed, which model answered, how long it took, and, if
    it did not go through, why and how to fix it. It runs the real path, so it tells you whether
    your setup just works. The report comes from an endpoint built to gather only safe facts —
    never your key, your account name, or anything about our machines.

Test it in the console

## Every stage, and how long it took

A worked example of a call that went through. Each line is a stage of the real path, timed
    as it happens — not a value read from a stored log.

      | Stage | Result |  |

      | Connected | OK · reached eu-se-1 · Stockholm |  |

      | Key accepted | OK · valid, active |  |

      | Allowed | OK · within your quota and limits |  |

      | Answer generated | OK · Qwen3.8 27B · finished `stop` |  |

      | Total time | 9.8 s |  |

      | Throughput | ~12 tok/s |  |

      | Tokens | prompt 26 · output 118 · total 144 |  |

If a stage fails, the report stops there and tells you which one and why, in plain words,
    with the fix — so you can tell a wrong key from an exhausted quota from a request that was too
    large.

```
# bash · macOS · Linux
$ curl -X POST https://api.axforge.ai/v1/diagnostics \
    -H "Authorization: Bearer $AXFORGE_KEY"
# Windows PowerShell — ContentType and Body are both needed here
PS> Invoke-RestMethod https://api.axforge.ai/v1/diagnostics -Method Post `
    -Headers @{ Authorization = "Bearer $env:AXFORGE_KEY" } `
    -ContentType 'application/json' -Body '{}'
# → a small JSON report: ok, stages[], timings, usage, and on failure a safe reason + fix
```

## Why, in plain words, with the fix

      | What you see | What it means and the fix |  |

      | **Key not accepted** · 401 | The key is wrong, revoked or from another account. Create or copy one in the console. |  |

      | **Out of allowance** · 402 | Your token allowance for the period is used up. Top up in billing, then retry. |  |

      | **Not allowed for this key** · 403 | The key exists but may not use this model or endpoint. Check its scope under API keys. |  |

      | **Request too large** · 413 | The input is over the model's context. Shorten it — see errors & limits. |  |

      | **Too many at once** · 429 | Your key's rate limit or the model's concurrency was hit. Wait a moment and retry; spread bursts out. |  |

      | **Model answered badly** · 502 | The model returned something the API could not use. Retry once; if it repeats, the model page shows its status. |  |

      | **Busy right now** · 503 | The model was saturated for a moment. Retry with a short backoff. |  |

      | **Timed out** · 504 | No answer within the limit — a long generation on a busy model. Retry, or ask for fewer tokens. |  |

## What the report shows, and what it never does

**Shown:** which stages passed and how long each took, total time, throughput, token
    counts, the model and region, how the answer finished, and — when it fails — a plain reason and
    the fix.

**Never shown:** your prompt and the model's reply, your API key, your account or user
    name, anything about other customers, and our internals — machine names, addresses, GPU layout,
    upstream URLs, stack traces. None of it is a field the endpoint can emit. Inference has
    zero prompt retention, so the text of your call is
    not stored at all.



## Models & pricing (/docs/models/)


# Models & pricing

One key serves every model below, from Stockholm, Sweden (eu-se-1). Pass the API model name in the
    `model` field of the matching endpoint. Prices are per-use, in
    EUR, excluding VAT. Every new account currently includes 5M serverless tokens/month at launch.

## Available on the serverless API

        | Model | Endpoint | API model name | Context | Price |  |

        Qwen3.8 27B | /v1/chat/completions | qwen3.8-27b-nvfp4 | 262,144 | €0.29 / 1M in · €1.77 / 1M out |  |

        Qwen3 Embedding | /v1/embeddings | qwen3-embed | 32,768 | €0.015 / 1M |  |

        ERNIE Image Turbo | /v1/images/generations | ernie-image-turbo | — | €0.05 / image |  |

        FLUX.2 Klein 4B | /v1/images/edits | flux2-klein-4b | — | €0.06 / edit |  |

        Whisper | /v1/audio/transcriptions | whisper | — | €0.005 / minute |  |

        Piper | /v1/audio/speech | piper | — | €2.95 / 1M characters |  |

        MiniMax Music 3 | /v1/audio/music | minimax-music3 | — | €0.04 / 10 seconds |  |

Chat prices are launch pricing. Each linked page carries the model's
    specs, benchmarks and data-handling details; the API pages in
    these docs (chat,
    embeddings,
    images, audio) carry
    the request and response shapes.

## How we price

Every model has one published price, in euros and excluding VAT, billed by
    use — no subscription and no minimum. The table above is the current list.

    Committed volume:
    talk to an engineer.

## Available as managed deployment

These models are validated on AxForge hardware and deployed on a dedicated
    NVIDIA DGX Spark for your traffic only — an OpenAI-compatible endpoint on your
    own machine, operated by AxForge. Hardware from €0.55/hour;
    managed service quoted per deployment.

        | Model | Type | Context |  |

        | Qwen3.6 35B A3B | LLM (MoE, 3B active) | 65,536 |  |

        | Qwen3 30B A3B | LLM (MoE) | 65,536 |  |

        | Gemma-4 26B | LLM, vision-capable | 262,144 |  |

        | Mistral Small 3.2 | LLM | 32,768 |  |

        | SDXL | Image generation | — |  |

        | Qwen-Image | Image generation & editing | — |  |

Want one of these, or a different open model on dedicated hardware?
    Request deployment — or rent the
    DGX Spark yourself with full SSH access.

      &larr; Glossary
      Chat completions &rarr;



## Chat completions (/docs/chat/)


# Chat completions

`POST /v1/chat/completions` — the OpenAI chat shape, served by
    Qwen3.8 27B as
    `qwen3.8-27b-nvfp4`. 262,144-token context. €0.29 / 1M input tokens, €1.77 / 1M output tokens (launch pricing). Streaming, tool calls,
    reasoning output and image input all work on this one endpoint.

## Request & response

```
$ curl https://api.axforge.ai/v1/chat/completions \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.8-27b-nvfp4",
    "messages": [
      {"role": "system", "content": "You answer in one sentence."},
      {"role": "user", "content": "What is an embedding?"}
    ],
    "max_tokens": 2048
  }'
```

```
PS> $body = @{
    model    = 'qwen3.8-27b-nvfp4'
    messages = @(
      @{ role = 'system'; content = 'You answer in one sentence.' },
      @{ role = 'user';   content = 'What is an embedding?' }
    )
    max_tokens = 2048
  } | ConvertTo-Json -Depth 5
PS> $r = Invoke-RestMethod https://api.axforge.ai/v1/chat/completions -Method Post `
    -Headers @{ Authorization = "Bearer $env:AXFORGE_API_KEY" } `
    -ContentType 'application/json' -Body $body
PS> $r.choices[0].message.content
```

```
REM cmd keeps single quotes, so the inner quotes are escaped instead.
C:\> curl -s https://api.axforge.ai/v1/chat/completions -H "Authorization: Bearer %AXFORGE_API_KEY%" -H "Content-Type: application/json" -d "{\"model\":\"qwen3.8-27b-nvfp4\",\"messages\":[{\"role\":\"system\",\"content\":\"You answer in one sentence.\"},{\"role\":\"user\",\"content\":\"What is an embedding?\"}],\"max_tokens\":2048}"
```

    Python

```
from openai import OpenAI

client = OpenAI(
    base_url="https://api.axforge.ai/v1",
    api_key="YOUR_AXFORGE_KEY",
)
r = client.chat.completions.create(
    model="qwen3.8-27b-nvfp4",
    messages=[{"role": "user", "content": "What is an embedding?"}],
)
print(r.choices[0].message.content)
```

The response is the standard OpenAI shape. Note
    `reasoning_content` — the model's thinking, separate from the
    answer (details below).

```
{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "model": "qwen3.8-27b-nvfp4",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "An embedding is a vector that encodes meaning...",
      "reasoning_content": "The user wants a one-line definition..."
    },
    "finish_reason": "stop"
  }],
  "usage": {"prompt_tokens": 21, "completion_tokens": 96, "total_tokens": 117}
}
```

## Streaming

Set `"stream": true` and the response arrives as server-sent
    events, one JSON chunk per `data:` line. Usage is included in
    streaming mode too — the final chunk before `[DONE]` carries it.

```
$ curl -N https://api.axforge.ai/v1/chat/completions \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen3.8-27b-nvfp4", "stream": true,
       "messages": [{"role": "user", "content": "Count to three."}]}'

# the wire format:
data: {"choices":[{"delta":{"content":"One"}}]}
data: {"choices":[{"delta":{"content":", two"}}]}
data: [DONE]
```

```
# Streaming is the one place Windows PowerShell needs more than a different quote.
# Invoke-RestMethod waits for the whole body, and plain Invoke-WebRequest throws on an
# SSE response in 5.1 ("Object reference not set to an instance of an object").
# -UseBasicParsing gets you the full text once it is finished:
PS> $body = '{"model":"qwen3.8-27b-nvfp4","stream":true,"messages":[{"role":"user","content":"Count to three."}]}'
PS> (Invoke-WebRequest https://api.axforge.ai/v1/chat/completions -Method Post `
      -Headers @{ Authorization = "Bearer $env:AXFORGE_API_KEY" } `
      -ContentType 'application/json' -Body $body -UseBasicParsing).Content

# For tokens as they arrive, read the stream yourself:
PS> $req = [System.Net.HttpWebRequest]::Create("https://api.axforge.ai/v1/chat/completions")
PS> $req.Method = "POST"; $req.ContentType = "application/json"
PS> $req.Headers.Add("Authorization", "Bearer $env:AXFORGE_API_KEY")
PS> $bytes = [Text.Encoding]::UTF8.GetBytes($body); $req.ContentLength = $bytes.Length
PS> $s = $req.GetRequestStream(); $s.Write($bytes,0,$bytes.Length); $s.Close()
PS> $rd = New-Object IO.StreamReader($req.GetResponse().GetResponseStream())
PS> while (-not $rd.EndOfStream) { $l = $rd.ReadLine(); if ($l -like "data: *") { $l } }
```

```
C:\> curl -N -s https://api.axforge.ai/v1/chat/completions -H "Authorization: Bearer %AXFORGE_API_KEY%" -H "Content-Type: application/json" -d "{\"model\":\"qwen3.8-27b-nvfp4\",\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"Count to three.\"}]}"
```

The wire format, whichever shell you used:

```
# the wire format:
data: {"choices":[{"delta":{"content":"One"}}]}
data: {"choices":[{"delta":{"content":", two"}}]}
data: {"choices":[{"delta":{},"finish_reason":"stop"}]}
data: {"choices":[],"usage":{"prompt_tokens":13,"completion_tokens":9,"total_tokens":22}}
data: [DONE]
```

    Python

```
r = client.chat.completions.create(
    model="qwen3.8-27b-nvfp4",
    stream=True,
    messages=[{"role": "user", "content": "Count to three."}],
)
for chunk in r:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="")
    if chunk.usage:
        print("\ntokens:", chunk.usage.total_tokens)
```

## Tool calls

The endpoint accepts the OpenAI `tools` schema. Declare
    functions, let the model decide when to call one, run it yourself, and send
    the result back as a `tool` message. One complete round trip:

    Python

```
import json

tools = [{
    "type": "function",
    "function": {
        "name": "get_invoice",
        "description": "Look up an invoice by its number",
        "parameters": {
            "type": "object",
            "properties": {"number": {"type": "string"}},
            "required": ["number"],
        },
    },
}]

messages = [{"role": "user", "content": "What is the total on invoice 2041?"}]
r = client.chat.completions.create(
    model="qwen3.8-27b-nvfp4", messages=messages, tools=tools,
)

# the model asked for the tool instead of answering
call = r.choices[0].message.tool_calls[0]
args = json.loads(call.function.arguments)   # {"number": "2041"}

# run it yourself, then send the result back
messages.append(r.choices[0].message)
messages.append({
    "role": "tool",
    "tool_call_id": call.id,
    "content": json.dumps({"number": "2041", "total_eur": 1240.0}),
})
r = client.chat.completions.create(
    model="qwen3.8-27b-nvfp4", messages=messages, tools=tools,
)
print(r.choices[0].message.content)   # "Invoice 2041 totals EUR 1,240.00."
```

On the wire, the model's tool request looks like this — pass the same
    `tools` array in a curl body to get it:

```
"message": {
  "role": "assistant",
  "content": null,
  "tool_calls": [{
    "id": "call_...",
    "type": "function",
    "function": {"name": "get_invoice", "arguments": "{\"number\": \"2041\"}"}
  }]
},
"finish_reason": "tool_calls"
```

## Reasoning output

The model thinks before it answers. The thinking arrives in
    `reasoning_content` on the message (and in the delta when
    streaming); `content` holds only the answer. Reasoning tokens are
    output tokens and are billed as such.

To disable thinking, pass `chat_template_kwargs`:

    curl

```
$ curl https://api.axforge.ai/v1/chat/completions \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.8-27b-nvfp4",
    "messages": [{"role": "user", "content": "Classify: \"refund please\""}],
    "chat_template_kwargs": {"enable_thinking": false}
  }'
```

    Python

```
r = client.chat.completions.create(
    model="qwen3.8-27b-nvfp4",
    messages=[{"role": "user", "content": "Classify: \"refund please\""}],
    extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
```

    **Tip — give thinking room.** With thinking enabled, the
    model spends output tokens on `reasoning_content` before it
    writes the answer, so a small `max_tokens` can be used up by
    reasoning and return an empty `content`. Raise
    `max_tokens`, or disable thinking for short structured outputs.

## Image input (vision)

Qwen3.8 27B reads images. Make `content` an array that mixes
    `text` and `image_url` parts. An image is either an
    `https://` URL we can fetch, or a base64 `data:` URL you
    build from the file. You can send **several images in one message** &mdash; up
    to **8** per request &mdash; and the model reads them in the order you list them.

**Send them the best way:**

      - **Resize big scans.** Cost scales with pixels: a phone photo is about
      500&ndash;1,500 tokens, a full A4 300-DPI page (2480&times;3508) about 8,500. Downscale
      documents to roughly 1,500&ndash;2,000 px on the long side unless the fine print
      matters &mdash; it is faster and cheaper, and just as accurate for invoices and forms.

      - **Use JPEG** for photos and scans (a fraction of a PNG's size). Keep PNG only for
      screenshots and line art.

      - **One document per image.** For a multi-page file, send one image per page, in
      order, and say so in the text.

      - **Put the images first, then your question** &mdash; the model answers what the
      text asks about the images above it.

    curl &middot; two images

```
$ curl https://api.axforge.ai/v1/chat/completions \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.8-27b-nvfp4",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "These are two invoice pages. What is the grand total?"},
        {"type": "image_url", "image_url": {"url": "https://example.com/page-1.jpg"}},
        {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."}}
      ]
    }]
  }'
```

The Python helper below resizes each file, encodes it as a JPEG data URL, and sends
    any number of images in one call.

    Python &middot; several files, resized

```
import base64, io
from openai import OpenAI
from PIL import Image  # pip install pillow openai

client = OpenAI(base_url="https://api.axforge.ai/v1", api_key="YOUR_AXFORGE_KEY")

def image_part(path, max_side=2000):
    # open, shrink the long side to max_side, re-encode as JPEG, return a data-URL part
    im = Image.open(path).convert("RGB")
    scale = min(1.0, max_side / max(im.size))
    if scale < 1.0:
        im = im.resize((round(im.width * scale), round(im.height * scale)))
    buf = io.BytesIO()
    im.save(buf, "JPEG", quality=85)
    b64 = base64.b64encode(buf.getvalue()).decode()
    return {"type": "image_url",
            "image_url": {"url": f"data:image/jpeg;base64,{b64}"}}

files = ["page-1.jpg", "page-2.jpg", "page-3.png"]  # up to 8
parts = [{"type": "text",
          "text": "These are the pages of one invoice, in order. "
                  "Return supplier, invoice number, date and total as JSON."}]
parts += [image_part(f) for f in files]

r = client.chat.completions.create(
    model="qwen3.8-27b-nvfp4",
    messages=[{"role": "user", "content": parts}],
)
print(r.choices[0].message.content)
```

## Context & pricing

        | Context window | 262,144 tokens |  |

        Input | €0.29 / 1M tokens (launch pricing) |  |

        Output | €1.77 / 1M tokens (launch pricing) |  |

        | Image input | ~500–9,000 prompt tokens per image by size (a full A4 scan ~8,500), billed as input |  |

        | Reasoning | Billed as output tokens |  |

More on how prices are set: Models &
    pricing and the pricing page. Concurrency and
    error behavior: Errors & limits.

      &larr; Models & pricing
      Embeddings &rarr;



## Embeddings (/docs/embeddings/)


# Embeddings

`POST /v1/embeddings` — the OpenAI embeddings shape, served by
    Qwen3 Embedding as
    `qwen3-embed`. 1024-dimension vectors, €0.015 / 1M tokens.

## Request & response

    curl

```
$ curl https://api.axforge.ai/v1/embeddings \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen3-embed", "input": "The invoice is due on Friday"}'
```

```
PS> $body = @{ model = 'qwen3-embed'; input = 'The invoice is due on Friday' } | ConvertTo-Json
PS> $r = Invoke-RestMethod https://api.axforge.ai/v1/embeddings -Method Post `
    -Headers @{ Authorization = "Bearer $env:AXFORGE_API_KEY" } `
    -ContentType 'application/json' -Body $body
PS> $r.data[0].embedding.Count     # 1024
```

```
C:\> curl -s https://api.axforge.ai/v1/embeddings -H "Authorization: Bearer %AXFORGE_API_KEY%" -H "Content-Type: application/json" -d "{\"model\":\"qwen3-embed\",\"input\":\"The invoice is due on Friday\"}"
```

```
{
  "object": "list",
  "model": "qwen3-embed",
  "data": [{
    "object": "embedding",
    "index": 0,
    "embedding": [0.0132, -0.0417, ...]   // 1024 floats
  }],
  "usage": {"prompt_tokens": 7, "total_tokens": 7}
}
```

## Batching

Pass `input` as an array of strings to embed many texts in one
    request. You get one vector per item; `index` matches the input
    position.

    Python

```
from openai import OpenAI

client = OpenAI(
    base_url="https://api.axforge.ai/v1",
    api_key="YOUR_AXFORGE_KEY",
)
r = client.embeddings.create(
    model="qwen3-embed",
    input=[
        "The invoice is due on Friday",
        "Payment terms are net 30",
        "The meeting moved to Tuesday",
    ],
)
vectors = [d.embedding for d in r.data]   # three lists of 1024 floats
```

## Specs

        | Model | qwen3-embed |  |

        | Dimensions | 1024 |  |

        | Context | 32,768 tokens |  |

        Price | €0.015 / 1M tokens |  |

Store the vectors in any vector database; cosine similarity is the usual
    distance. All input is processed with
    zero retention, like every endpoint here.

      &larr; Chat completions
      Image generation & editing &rarr;



## Images (/docs/images/)


# Image generation & editing

Two endpoints, two models.
    ERNIE Image Turbo generates new images —
    including dense, accurate in-image text.
    FLUX.2 Klein edits an existing
    image from an instruction. Both return base64 PNG in the OpenAI images
    shape.

## Generation

`POST /v1/images/generations` — model
    `ernie-image-turbo`, €0.05 / image.

        | Parameter | Meaning |  |

        | prompt | What to draw. ERNIE follows text-in-image instructions well — quote the exact wording you want rendered. |  |

        | size | `"WxH"`, e.g. `"1024x1024"` — up to 2048 per side |  |

        | seed | Optional. Same seed + same prompt reproduces the image. |  |

        | n | Optional. Number of images, up to 4. |  |

    curl

```
$ curl https://api.axforge.ai/v1/images/generations \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ernie-image-turbo",
    "prompt": "Poster reading GRAND OPENING in bold red serif on cream paper",
    "size": "1024x1024",
    "seed": 7,
    "n": 1
  }' | jq -r '.data[0].b64_json' | base64 -d > poster.png
```

The response carries the PNG in `data[].b64_json`:

```
{
  "data": [
    {"b64_json": "iVBORw0KGgoAAAANSUhEUg..."}
  ]
}
```

Generation is not instant — expect tens of seconds per image. Set your
    client timeout accordingly.

## Editing

`POST /v1/images/edits` — model `flux2-klein-4b`.
    Send the source image plus an instruction; get the edited image back as
    base64 PNG. €0.06 per edit (launch pricing).

        | Parameter | Meaning |  |

        | prompt | The edit instruction, e.g. "make the sky overcast" |  |

        | image | The source image, as base64 or a data URL. Use `images` for several sources. |  |

        | n | Optional. Number of variants. |  |

    curl

```
$ IMG=$(base64 -w0 photo.png)
$ curl https://api.axforge.ai/v1/images/edits \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"model\": \"flux2-klein-4b\",
    \"prompt\": \"Make the sky overcast\",
    \"image\": \"data:image/png;base64,$IMG\"
  }" | jq -r '.data[0].b64_json' | base64 -d > edited.png
```

Edits are faster than full generations — seconds-scale rather than
    tens of seconds.

## Changing text inside an image

    **Regenerate, don't edit.** To change words inside an
    image, re-run `/v1/images/generations` with
    `ernie-image-turbo` and the new wording — reuse your
    `seed` to keep the composition close. ERNIE renders dense
    in-image text accurately; instruction editors like FLUX mangle
    letterforms.

      &larr; Embeddings
      Speech & music &rarr;



## Speech & music (/docs/audio/)


# Speech & music

Three audio endpoints:
    Whisper for transcription,
    Piper for text to speech, and
    MiniMax Music 3 for full music tracks. Launch pricing: transcription
    €0.005 / minute, speech €2.95 / 1M characters, music €0.04 / 10 seconds.

## Speech to text

`POST /v1/audio/transcriptions` — model `whisper`.
    A multipart file upload, not JSON:

    curl

```
$ curl https://api.axforge.ai/v1/audio/transcriptions \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -F file=@meeting.wav \
  -F model=whisper
```

```
{"text": "Let's move the review to Tuesday morning."}
```

## Text to speech

`POST /v1/audio/speech` — model `piper`. Send the
    text, receive the spoken audio as the response body:

    curl

```
$ curl https://api.axforge.ai/v1/audio/speech \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "piper", "input": "Your order has shipped."}' \
  --output speech.wav
```

## Music generation

`POST /v1/audio/music` — MiniMax Music 3, model name
    `minimax-music3`. Describe the music in `prompt`;
    optionally structure lyrics with `[verse]` and
    `[chorus]` tags, or omit `lyrics` entirely for an
    instrumental track.

        | Parameter | Meaning |  |

        | prompt | A musical description: genre, mood, tempo, instrumentation |  |

        | lyrics | Optional. Lyrics with `[verse]` / `[chorus]` tags. Omit for instrumental. |  |

        | duration_s | Track length in seconds, up to 300 |  |

        | seed | Optional. Same seed + same inputs reproduces the track. |  |

    curl

```
$ curl --max-time 300 https://api.axforge.ai/v1/audio/music \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-music3",
    "prompt": "Warm acoustic folk, fingerpicked guitar, 90 bpm, hopeful",
    "lyrics": "[verse]\nMorning light on the harbor line\n[chorus]\nWe sail at dawn",
    "duration_s": 60,
    "seed": 11
  }' | jq -r '.data[0].b64_json' | base64 -d > track.wav
```

The response carries the track in `data[].b64_json` — a WAV
    file, 32 kHz stereo, base64-encoded.

    **Generation takes ~2–3 minutes per track.** Use generous
    client timeouts (the `--max-time 300` above) and async patterns —
    fire the request from a background job, not a user-facing request handler.

Publishing the track? Label it as AI-generated — it was made by
    MiniMax Music 3 — and check your jurisdiction's disclosure rules for
    generated media.

      &larr; Image generation & editing
      Regions & data handling &rarr;



## Errors & limits (/docs/errors-limits/)


# Errors & limits

Errors use the standard OpenAI JSON shape, so existing SDK error handling
    works unchanged. This page lists what the API actually returns and what the
    serverless API serves today.

## The error shape

```
{
  "error": {
    "message": "a human-readable description",
    "type": "...",
    "param": null,
    "code": "..."
  }
}
```

## Status codes

        | Status | Meaning | What to do |  |

        | 400 | Validation error — malformed JSON, unknown field, or a bad parameter value | Fix the request; `error.message` names the problem |  |

        | 401 | Unauthorized — missing or invalid key | Check the `Authorization: Bearer` header and your key |  |

        | 402 | `insufficient_quota` — the account's token allowance and balance are used up | Top up in Usage & Billing, then retry the same request |  |

        | 403 | `scope_denied` — the key exists but is not allowed this model or endpoint | Check the key's scope under API keys, or create one for this use |  |

        | 413 | `context_length_exceeded` — the input is larger than the model's context | Shorten the prompt or the history; the limit is in the table below |  |

        | 429 | `rate_limited` / `too_busy` — your key's rate or the model's concurrency was hit | Wait briefly and retry; spread bursts out over time |  |

        | 503 | `model_not_hot` — the model is not loaded right now | Retry with backoff |  |

## 503 model_not_hot

The model is not loaded right now — retry with backoff. The condition is
    temporary; your request itself is fine.

```
HTTP/2 503
{
  "error": {
    "message": "The model for this role is not loaded. Retry with backoff.",
    "code": "model_not_hot"
  }
}
```

    Python

```
import time

for wait in (1, 2, 4, 8, 16):
    try:
        r = client.chat.completions.create(model="qwen3.8-27b-nvfp4", messages=messages)
        break
    except openai.InternalServerError as e:   # SDK surfaces 503 here
        time.sleep(wait)
```

## Limits

The serverless API serves:

        | Context window | 262,144 tokens (chat model) |  |

        | Concurrency | Up to 4 concurrent sequences on the chat model |  |

Under concurrent load requests queue; latency grows before anything fails.
    There are no hidden quotas — this table is the whole list.

If you need committed throughput — reserved concurrency, your own
    dedicated system, a specific model held hot — rent a
    dedicated DGX Spark from €0.55/hour,
    or Request deployment for a system AxForge operates for you.

      &larr; Regions & data handling
      Rules & responsibilities &rarr;



## Use it from your stack (/docs/connect/)


# Use AxForge with your stack

    AxForge speaks the OpenAI API shape, so the tools you already
    use work here. In almost every case the whole integration is three changes:
    the base URL, your
    key, and a
    model name.

## The one pattern behind every guide

Whatever the tool, you are telling it to send OpenAI-style requests to us
    instead of OpenAI:

        | Set this | To |  |

        | Base URL | https://api.axforge.ai/v1 |  |

        | API key | your AxForge key (orx_live_…) — from the console |  |

        | Model | chat · embeddings · or an exact version |  |

The fastest check that it is wired correctly, from any shell:

```
$ curl https://api.axforge.ai/v1/chat/completions \
    -H "Authorization: Bearer $AXFORGE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"model":"chat","messages":[{"role":"user","content":"ping"}]}'
```

A JSON reply with a `choices` array means you are connected. From
    there, pick your tool.

## SDKs

        **OpenAI SDK**Python & Node. Change `base_url`, keep the rest of your code.drop-in

        **Vercel AI SDK**The standard TypeScript AI toolkit, via its OpenAI-compatible provider.drop-in

## Coding assistants

        **aider**Terminal pair-programmer. One env var and a model prefix.drop-in

        **Continue**VS Code & JetBrains. An `openai` provider in `config.yaml`.drop-in

        **Cline**VS Code agent. The "OpenAI Compatible" provider.drop-in

        **Kimi Code CLI**Moonshot's terminal agent, pointed at an `openai` provider.drop-in

        **Codex & Claude Code**Speak the Responses / Messages APIs — both served natively, point straight at us.direct

## Chat UIs & terminals

        **Open WebUI**Self-hosted chat UI. One OpenAI connection; models auto-list.drop-in

        **LibreChat**Multi-model chat app. A custom endpoint in `librechat.yaml`.drop-in

        **llm (Datasette CLI)**Simon Willison's terminal LLM CLI. One YAML entry.drop-in

## Gateways & proxies

        **LiteLLM**Put AxForge behind one endpoint; re-expose Chat, Messages & Responses.proxy

    **A note on API shapes.** Nearly everything speaks the
    Chat Completions API, which
    AxForge serves. Two popular tools speak a different shape — OpenAI's
    **Codex CLI** uses the
    Responses API and
    **Claude Code** the Anthropic
    Messages API — and AxForge serves both
    of those natively too (`/v1/responses`, `/v1/messages`), so
    they point straight at us. See the Codex
    & Claude Code guide.

## Anything else

If a tool can point at a custom OpenAI base URL — another CLI, a workflow node, a
    no-code builder, a gateway such as the Vercel
    AI Gateway — it works the same way: base URL, key, model. When in doubt, use the
    `curl` check above with your tool's base-URL and key fields, then
    fill them into the tool. Stuck? Talk to an
    engineer.

      &larr; Glossary
      OpenAI SDK &rarr;



## OpenAI SDK (/docs/connect/openai-sdk/)


    Connect → OpenAI SDK

# Use AxForge with the OpenAI SDK

    The official OpenAI SDKs take a base-URL option. Set it to
    `https://api.axforge.ai/v1`, use your AxForge key, and the rest of
    your code is unchanged — chat, streaming, tools, vision and embeddings all work
    against the same client.

## Python

    Python

```
# pip install openai — the official SDK, unchanged
from openai import OpenAI

client = OpenAI(
    base_url="https://api.axforge.ai/v1",   # or set OPENAI_BASE_URL
    api_key="YOUR_AXFORGE_KEY",             # or set OPENAI_API_KEY
)

resp = client.chat.completions.create(
    model="chat",
    messages=[{"role": "user", "content": "Hello from Stockholm"}],
)
print(resp.choices[0].message.content)
print(resp.usage)   # token counts, for your own accounting
```

### Streaming

```
stream = client.chat.completions.create(
    model="chat", stream=True,
    messages=[{"role": "user", "content": "Count to five"}],
)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")
```

### Embeddings

```
e = client.embeddings.create(model="embeddings", input="a sentence to embed")
print(len(e.data[0].embedding))   # 1024
```

## Node / TypeScript

    Node

```
// npm i openai
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.axforge.ai/v1",   // or OPENAI_BASE_URL
  apiKey: process.env.AXFORGE_API_KEY,       // or OPENAI_API_KEY
});

const resp = await client.chat.completions.create({
  model: "chat",
  messages: [{ role: "user", content: "Hello" }],
});
console.log(resp.choices[0].message.content);
```

    **Tip — use `chat.completions`.** This SDK's
    `client.chat.completions.create` hits the widely-supported
    Chat Completions API and is the
    path shown here. AxForge _also_ serves the newer
    Responses API
    (`client.responses.create` → `/v1/responses`) natively, so
    either works — see Codex & Claude
    Code.

## Model names

Use a stable role name like `chat` or `embeddings`, or
    an exact version like `qwen3.8-27b-nvfp4` — both resolve to the same
    served model. Call `client.models.list()`
    (`GET /v1/models`) for the live catalogue, or see
    Models & pricing.

## Keep your data in the EU

Every key is pinned to an EU region, and
    you can force one per request with a default header:

```
client = OpenAI(
    base_url="https://api.axforge.ai/v1", api_key="YOUR_AXFORGE_KEY",
)  # the region is pinned on the key — nothing to set per request
```

Prompts and completions are processed in memory and never retained — see
    Regions & data handling.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - The response object carries a `usage` block with token counts. That is the API answering, not a stub.
- `response.model` is an AxForge model id, which tells you the base URL took effect.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | `AuthenticationError` | the key is wrong or from the other environment | confirm it with the self-test before blaming the SDK |  |

        | `NotFoundError` / 404 | the base URL is missing `/v1`, or the model id is not one we serve | ids are on Models & pricing |  |

        | It reaches OpenAI instead | `base_url` was not applied to the client you actually used | set it on the client you call, not a second one |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; Use with your stack
      Vercel AI SDK &rarr;



## Vercel AI SDK (/docs/connect/vercel-ai-sdk/)


    Connect → Vercel AI SDK

# Use AxForge with the Vercel AI SDK

    The Vercel AI SDK
    (npm `ai`, Apache-2.0) is the de-facto standard TypeScript toolkit for
    building with models. Point it at AxForge with its OpenAI-compatible provider and
    the rest of your app — `generateText`, `streamText`, tools,
    UI hooks — is unchanged.

## Install & configure

```
$ npm i ai @ai-sdk/openai-compatible
```

```
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { generateText } from "ai";

const axforge = createOpenAICompatible({
  name: "axforge",
  baseURL: "https://api.axforge.ai/v1",
  apiKey: process.env.AXFORGE_API_KEY,
});

const { text } = await generateText({
  model: axforge("chat"),
  prompt: "Hello from Stockholm",
});
```

### Streaming

```
import { streamText } from "ai";
const result = streamText({ model: axforge("chat"), prompt: "Count to five" });
for await (const delta of result.textStream) process.stdout.write(delta);
```

### Embeddings

```
import { embed } from "ai";
const { embedding } = await embed({
  model: axforge.textEmbeddingModel("embeddings"),
  value: "a sentence to embed",
});   // 1024-dim
```

    **Prefer the OpenAI-compatible provider.**
    `@ai-sdk/openai-compatible` always calls
    Chat Completions — the simplest,
    most portable path. If you use `@ai-sdk/openai` instead, its default
    `openai('id')` targets the
    Responses API
    (`/v1/responses`) — AxForge serves that too, but for the chat path call
    `openai.chat('id')`.

## Model names

Pass `chat` / `embeddings` (stable role names) or an exact
    version like `qwen3.8-27b-nvfp4` — see
    Models & pricing. Everything runs in the EU with
    zero retention.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - `generateText` returns text, and `result.usage` has token counts.
- `streamText` yields chunks progressively rather than one final blob.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | `401` | the key is not reaching the provider | environment variables in Next.js are not automatically available server-side at runtime — check where you read it |  |

        | `404` | `baseURL` without `/v1` | it must end `/v1` |  |

        | Types complain about the provider | the OpenAI-compatible provider is a separate import from the OpenAI one | use the compatible provider as shown above |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; OpenAI SDK
      aider &rarr;



## aider (/docs/connect/aider/)


    Connect → aider

# Use AxForge with aider

    aider is an AI pair-
    programmer that edits code in your terminal. It routes model calls through LiteLLM,
    so you point it at AxForge with the OpenAI environment variables and an
    `openai/` model prefix.

## Get aider

aider is a terminal program, installed from PyPI:

```
$ python -m pip install aider-chat
```

Then run `aider` inside a git repository — it works on the repo you are
    standing in. Full options:
    aider.chat.

## Configure

```
$ export OPENAI_API_BASE=https://api.axforge.ai/v1
$ export OPENAI_API_KEY=your-axforge-key
$ aider --model openai/qwen3.8-27b-nvfp4
```

Or pass them as flags instead of env vars:

```
$ aider --openai-api-base https://api.axforge.ai/v1 \
      --openai-api-key your-axforge-key \
      --model openai/qwen3.8-27b-nvfp4
```

    **The `openai/` prefix is required.** It tells
    aider's LiteLLM layer to treat the model as a generic
    OpenAI-compatible endpoint. Without
    it, aider tries to match the bare name against known hosted providers and fails.

## Notes

      - For a model aider does not recognise, set its context window in a
      `.aider.model.settings.yml` so aider sizes the conversation
      correctly.

      - Use a coding-strong model — the `agentic` role (which maps to
      `qwen3.8-27b-nvfp4`) is a good default; see Models.

## Where to put this

The two exports above only last for the terminal you typed them in. For something
    permanent, pick one:

      | Where | Good for |  |

        | Your shell profile — `~/.bashrc`, `~/.zshrc`, or on
        Windows `$PROFILE` | Every project, every new terminal |  |

        | `.env` beside the repo | One project. aider reads it, and
        it keeps the key out of your shell history |  |

        | `~/.aider.conf.yml` | aider's own settings file, when you
        also want to pin the model and other options |  |

    On Windows, `export` is not a command —
    `$env:OPENAI_API_BASE = "https://api.axforge.ai/v1"` in PowerShell, or
    `set OPENAI_API_BASE=https://api.axforge.ai/v1` in cmd.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - aider prints the model on the line it starts with — you should see `openai/chat`, not a Moonshot or OpenAI default.
- Ask it something small (`what files are in this repo?`) and the answer arrives rather than an error.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | `Model not found` or aider offers a picker | the `openai/` prefix is missing, so aider looked up a model that is not ours | the model must be written `openai/chat`, prefix included |  |

        | `401` | the key | check `OPENAI_API_KEY` is exported in the shell you actually ran aider in — a new terminal does not have it |  |

        | It answers but edits nothing | that is aider working normally; it asks before writing | not a connection problem |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; Vercel AI SDK
      Continue &rarr;



## Continue (/docs/connect/continue/)


    Connect → Continue

# Use AxForge with Continue

    Continue is an
    open-source coding assistant that runs inside VS Code and JetBrains. It has no model
    of its own — you point it at one, which is what makes it useful here: the same editor
    assistance as a hosted product, running against AxForge.

## Is this the one you want?

Three of the tools on this page live in VS Code, and they are not interchangeable:

      | Tool | Best when you want |  |

        | **Continue** | Chat and inline edits driven by a **config file** you keep in version control, in **VS Code or JetBrains**. Indexes your repo for `@codebase` questions. |  |

        | Cline | An **agent** that plans and edits across files by itself. Configured in the UI, no file to edit. |  |

        | Codex / Claude Code | A **terminal** agent rather than an editor panel. |  |

## 1. Install Continue

It is an extension, not something built into your editor:

      - **VS Code** — Extensions (Ctrl/Cmd+Shift+X),
      search **Continue**, install the one by Continue Dev. Or
      from the marketplace.

      - **JetBrains** — Settings → Plugins → Marketplace → **Continue**.

A Continue icon appears in the sidebar once it is installed.

## 2. Find the config file

Continue keeps one config file per machine, outside your project:

      | System | Path |  |

        | macOS & Linux | `~/.continue/config.yaml` |  |

        | Windows | `%USERPROFILE%\.continue\config.yaml` |  |

Easiest route: open the Continue sidebar and use its settings (gear) to open the
    config — that way you are certainly editing the file it reads.

## 3. Add AxForge

```
name: AxForge
version: 0.0.1
schema: v1
models:
  - name: AxForge Chat
    provider: openai
    model: chat
    apiBase: https://api.axforge.ai/v1
    apiKey: your-axforge-key
    roles: [chat, edit, apply]
  - name: AxForge Embed        # optional, for @codebase indexing
    provider: openai
    model: embeddings
    apiBase: https://api.axforge.ai/v1
    apiKey: your-axforge-key
    roles: [embed]
```

    **Use `config.yaml` (schema `v1`).** The
    older `config.json` still loads but is legacy. `apiBase` must
    include the `/v1`; `provider: openai` calls
    Chat Completions by default.

## 4. Check that it worked

Save the file, then open the Continue sidebar. You should see:

      - **AxForge Chat** in the model picker at the top of the panel. If it is not
      there, Continue did not load the file — see below.

      - A reply that **streams in word by word** when you send "hello". Streaming is
      the sign it is really talking to the API rather than returning an error object.

      - A matching call in the console at
      Billing & usage within a minute or
      two. That is the end-to-end proof: your editor reached our API on your key.

## When it does not work

Three things break, and they look different:

      | What you see | What it means | Fix |  |

        |
          **AxForge Chat is missing** from the picker |
          Continue never read your file, or the YAML is invalid |
          Check you edited the path above, and that indentation is spaces not tabs. Continue shows config errors in its own panel. |
         |

        |
          **401** or "invalid API key" |
          The key is wrong, revoked, or has a stray space |
          Make a new key and paste it whole. Confirm it independently with the self-test. |
         |

        |
          **404**, or a reply that never arrives |
          `apiBase` is missing the `/v1`, or the model name is not one we serve |
          It must end `/v1`. Model ids are on Models & pricing. |
         |

    Still stuck? Run the self-test — it
    tells you in one click whether the problem is your key, your quota or us, so you know
    whether to keep debugging Continue at all.

## Notes

The `embed` role powers Continue's `@codebase` retrieval;
    point it at the `embeddings` model as above. Model names come from
    Models & pricing.

      &larr; aider
      Cline &rarr;



## Cline (/docs/connect/cline/)


    Connect → Cline

# Use AxForge with Cline

    Cline is an
    autonomous coding agent for VS Code. It has a built-in **OpenAI
    Compatible** provider — configure it in the model picker, no file needed.

## Get Cline

Cline is a VS Code extension, not something built in:

      - Extensions (Ctrl/Cmd+Shift+X),
      search **Cline**, install it.

      - A Cline icon appears in the activity bar; its settings are in that panel.

    Cline keeps its configuration **in the UI** — there is no file to
    edit, which is the main practical difference from
    Continue.

## In the Cline model settings

        | Field | Value |  |

        | API Provider | OpenAI Compatible |  |

        | Base URL | https://api.axforge.ai/v1 |  |

        | API Key | your AxForge key |  |

        | Model ID | chat  (or qwen3.8-27b-nvfp4) |  |

    **Set the model limits yourself.** For an OpenAI-Compatible
    provider Cline cannot auto-detect model metadata, so open the advanced model
    settings and set **Context Window** (e.g. 262144),
    **Max Output Tokens**, and **Image Support**. Leave them
    at the defaults and Cline may truncate context early or error on long sessions.

## Notes

Cline is agentic and multi-step — prefer the `agentic` role (or the
    exact `qwen3.8-27b-nvfp4`) for tool-heavy work. See
    Models & pricing.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - **AxForge** is selectable in the Cline model picker.
- A task you give it produces a reply that **streams** in. An error object arrives all at once; a real answer arrives progressively.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | "No provider" or the model will not select | the provider is not set to **OpenAI Compatible** | it is a separate entry from "OpenAI" in the provider list |  |

        | `401` | the key | paste it again whole — a trailing space is enough to break it |  |

        | `404` | the Base URL is missing `/v1` | it must end `/v1` |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; Continue
      Kimi Code CLI &rarr;



## Codex CLI & Claude Code (/docs/connect/codex-claude-code/)


    Connect → Codex & Claude Code

# Use AxForge with Codex CLI & Claude Code

    OpenAI's **Codex CLI** speaks the
    Responses API and Anthropic's
    **Claude Code** speaks the
    Messages API — not Chat Completions. So
    AxForge serves both natively: `api.axforge.ai/v1/responses` and
    `api.axforge.ai/v1/messages` translate to the same models behind your
    key, with tool calling and streaming. Point each tool straight at us — no proxy.

## Get the CLIs

Both are terminal tools installed from npm, and each is maintained by its own
    vendor — take the current command from their own pages
    (Codex CLI,
    Claude Code)
    rather than from us, so it does not go stale here. What matters for AxForge is the
    endpoint each one talks to, below.

## Codex CLI

In your user-level `~/.codex/config.toml`, add an AxForge provider that
    uses the Responses wire API:

```
model = "chat"                    # or agentic, or qwen3.8-27b-nvfp4
model_provider = "axforge"

[model_providers.axforge]
name = "AxForge"
base_url = "https://api.axforge.ai/v1"
env_key = "AXFORGE_API_KEY"       # env var holding your AxForge key
wire_api = "responses"
```

Export the key (`export AXFORGE_API_KEY=your-axforge-key`) and run
    `codex`.

    **Two things.** `wire_api` must be
    `"responses"` — Codex removed the chat wire API in early 2026. Use a
    _new_ `model_provider` id (don't override the built-in
    `openai` one), in the user-level file, not a project-local one.

## Claude Code

Point Claude Code at AxForge's Anthropic-format endpoint with two env vars:

```
$ export ANTHROPIC_BASE_URL=https://api.axforge.ai
$ export ANTHROPIC_AUTH_TOKEN=your-axforge-key
$ claude                                  # runs on AxForge's /v1/messages
```

    **Always set the token.** `ANTHROPIC_AUTH_TOKEN`
    is sent as `Authorization: Bearer`; without a credential Claude Code falls
    back to a saved claude.ai login instead of AxForge. (`ANTHROPIC_API_KEY`,
    sent as `x-api-key`, works too.)

## Prefer a gateway?

You don't need one, but if you already run LiteLLM
    for budgets, fan-out, or multiple providers, it can front AxForge and expose the same
    Responses and Messages surfaces — point Codex/Claude Code at the proxy instead. Either
    way works.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - The CLI starts without a provider error and answers a prompt.
- The reply streams rather than arriving in one piece.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | `404` on `/chat/completions` | the tool is speaking the wrong API for its endpoint | Codex wants `/v1/responses`, Claude Code wants `/v1/messages` — not `/v1/chat/completions` |  |

        | `401` | the key, or it is in the wrong variable | each CLI reads its own environment variable — check which one |  |

        | It reaches the vendor instead | the base URL was not picked up | some CLIs only read it at start — restart after changing it |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; LiteLLM
      Back to all tools &rarr;



## Kimi Code CLI (/docs/connect/kimi/)


    Connect → Kimi Code CLI

# Use AxForge with Kimi Code CLI

    Kimi
    Code CLI is Moonshot's terminal coding agent. Although it ships pointed at
    Moonshot, its provider model lets you target any
    OpenAI-compatible endpoint — so it
    runs on AxForge.

## Get Kimi Code CLI

Kimi Code CLI is Moonshot's own tool — install it from
    their instructions, which
    stay current with their releases. Everything below applies once `kimi`
    runs and you can reach its config file.

## ~/.kimi-code/config.toml

```
[providers."axforge"]
type     = "openai"                       # OpenAI-compatible wire protocol
api_key  = "your-axforge-key"
base_url = "https://api.axforge.ai/v1"

[models."axforge-chat"]
provider         = "axforge"
model            = "chat"                    # or qwen3.8-27b-nvfp4
max_context_size = 262144
capabilities     = ["tool_use"]
```

    **Credentials live in the TOML only.** Kimi Code CLI does
    not read the API key from shell environment variables — put `api_key` in
    the config file as above.

## Notes

The provider `type` selects the wire protocol; `"openai"`
    is the one to use for AxForge. Model names come from
    Models & pricing, or
    `GET /v1/models`.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - Kimi starts against the AxForge provider rather than Moonshot — it names the provider it is using.
- A prompt gets an answer rather than a provider error.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | It still calls Moonshot | the config file was not read, or another provider is still the default | check the path above, and that AxForge is the selected provider |  |

        | `401` | the key | the key in the TOML is an AxForge key, not a Moonshot one |  |

        | `404` | the base URL is missing `/v1` | it must end `/v1` |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; Cline
      LiteLLM &rarr;



## LiteLLM (/docs/connect/litellm/)


    Connect → LiteLLM

# Use AxForge with LiteLLM

    LiteLLM is an
    open-source proxy. Put AxForge behind it to get one endpoint for many models, with
    budgets, keys and fallback — and to reach AxForge from tools that speak a different
    API shape.

## config.yaml

```
model_list:
  - model_name: axforge-chat
    litellm_params:
      model: openai/chat                 # openai/ prefix = OpenAI-compatible upstream
      api_base: https://api.axforge.ai/v1  # MUST include /v1
      api_key: os.environ/AXFORGE_API_KEY
  - model_name: axforge-embed
    litellm_params:
      model: openai/embeddings
      api_base: https://api.axforge.ai/v1
      api_key: os.environ/AXFORGE_API_KEY
```

```
$ litellm --config config.yaml     # proxy on http://localhost:4000
```

    **Two easy mistakes.** `api_base` must end in
    `/v1` (omit it and you get a Not Found), and you should never append
    `/chat/completions` yourself — LiteLLM's OpenAI handler adds the path.

## Three surfaces from one upstream

The proxy can re-expose AxForge on all three of the API shapes tools expect:

        | Surface | Reaches | Note |  |

        | /v1/chat/completions | OpenAI clients | native, no extra config |  |

        | /v1/messages | Anthropic / Claude Code | translated automatically |  |

        | /v1/responses | Codex / Responses clients | add `use_chat_completions_api: true` |  |

For the Responses bridge, add that flag to the model's
    `litellm_params` and use LiteLLM ≥ 1.63.8. You don't need this to reach
    AxForge from Codex or Claude Code —
    both are served natively — but it's handy if you already front everything with a
    gateway.

    **Pin a clean LiteLLM release.** Avoid the PyPI builds
    `1.82.7` / `1.82.8`, which were flagged upstream — install a
    known-good version.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - `curl http://localhost:4000/v1/models` lists your AxForge model names.
- A chat call through the proxy returns an answer with `usage`.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | The proxy starts but the model 404s | the `model` value is missing the `openai/` prefix | LiteLLM needs the provider prefix to know the wire protocol |  |

        | `401` from the proxy | your LiteLLM key | different from your AxForge key — both must be right |  |

        | `401` from upstream | the AxForge key in `api_key` | confirm it with the self-test |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; Kimi Code CLI
      Codex & Claude Code &rarr;



## Open WebUI (/docs/connect/open-webui/)


    Connect → Open WebUI

# Use AxForge with Open WebUI

    Open WebUI is a
    self-hosted chat interface. Add AxForge as an OpenAI connection and its models show
    up in the model picker.

## Run it pointed at AxForge

```
$ docker run -d -p 3000:8080 \
    -e ENABLE_OPENAI_API=True \
    -e OPENAI_API_BASE_URL=https://api.axforge.ai/v1 \
    -e OPENAI_API_KEY=your-axforge-key \
    -v open-webui:/app/backend/data \
    --name open-webui ghcr.io/open-webui/open-webui:main
```

Open WebUI calls `GET /v1/models` when the connection is saved and
    auto-populates the model list. To add several backends, use the plural,
    `;`-separated forms — keys pair to URLs by position:

```
-e OPENAI_API_BASE_URLS="https://api.axforge.ai/v1;http://other:11434/v1"
-e OPENAI_API_KEYS="axforge-key;other-key"
```

    **These env vars are read once.** Open WebUI stores them in
    its database on first launch (they are "PersistentConfig"), so changing the env var
    on a later restart of an existing volume has no effect — edit the connection under
    **Admin Settings → Connections** instead. The base URL must include
    `/v1`.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - AxForge models appear in the model picker at the top of a new chat. Open WebUI lists them by asking our `/v1/models`, so if they are there, the connection works.
- A message gets a streamed reply.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | The model list is empty | Open WebUI could not reach the API, or the key was refused | Settings → Connections shows the connection state; a container cannot reach `localhost` on your host |  |

        | `401` | the key | re-enter it in Settings → Connections |  |

        | Models list but replies fail | the connection is fine and the model id is not | pick from the list rather than typing an id |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; Use with your stack
      LibreChat &rarr;



## LibreChat (/docs/connect/librechat/)


    Connect → LibreChat

# Use AxForge with LibreChat

    LibreChat is a
    self-hosted, multi-model chat app. Add AxForge as a custom endpoint in
    `librechat.yaml`.

## Get LibreChat

LibreChat is a server you host, not an extension. The usual route is Docker
    Compose from the project's repository — follow
    their install guide, then
    come back here for the endpoint. You need a running LibreChat and access to its
    `librechat.yaml` and `.env` before the step below.

## librechat.yaml

```
endpoints:
  custom:
    - name: "AxForge"
      apiKey: "${AXFORGE_API_KEY}"       # from your .env
      baseURL: "https://api.axforge.ai/v1"
      models:
        default: ["chat"]           # initial pick (required)
        fetch: true               # pull the full list from GET /v1/models
      titleConvo: true
      titleModel: "chat"
      modelDisplayLabel: "AxForge"
```

Put `AXFORGE_API_KEY=your-axforge-key` in your `.env`.

    **Three things to get right.** `apiKey` is
    mandatory — it cannot be blank (use `"user_provided"` to have each user
    supply their own). `baseURL` must include `/v1` (LibreChat
    appends `/chat/completions`). Always populate `default` — if
    `fetch` can't reach `/v1/models` it falls back to that list.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - **AxForge** is in the endpoint dropdown when you start a conversation.
- Its models load in the model list beside it, and a message gets a streamed reply.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | AxForge missing from the dropdown | `librechat.yaml` was not loaded, or the YAML is invalid | LibreChat logs a config error at startup — read the first lines of its log |  |

        | Endpoint appears, models empty | it reached the file but not the API | check `baseURL` ends `/v1` and the key resolved from `.env` |  |

        | `401` | the key did not resolve | `${AXFORGE_API_KEY}` must exist in the environment LibreChat runs in |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; Open WebUI
      llm &rarr;



## llm (Datasette CLI) (/docs/connect/llm/)


    Connect → llm

# Use AxForge with llm

    llm (Simon
    Willison's CLI) talks to models from the terminal. Register AxForge as an
    OpenAI-compatible model with one config file.

## Get llm

A terminal tool, installed from PyPI:

```
$ python -m pip install llm
```

Or, if you use uv,
    `uv tool install llm`. Documentation:
    llm.datasette.io.

## 1. Add the model

Create `extra-openai-models.yaml` in llm's config dir — find it with
    `dirname "$(llm logs path)"`:

```
# extra-openai-models.yaml
- model_id: axforge            # the name you'll pass to -m
  model_name: chat            # the model id the API expects
  api_base: "https://api.axforge.ai/v1"
  api_key_name: axforge       # the NAME of a stored key (below)
```

## 2. Store the key & call it

```
$ llm keys set axforge        # paste your AxForge key at the prompt
$ llm -m axforge "Say hello in one line"
$ llm models                   # axforge should appear in the list
```

    **Include `/v1`, and mind `api_key_name`.**
    llm's OpenAI client appends `/chat/completions`, so `api_base`
    must be `https://api.axforge.ai/v1` (some local-server examples omit it —
    don't copy that here). `api_key_name` is the _name_ of the key you
    set with `llm keys set`, not the key value.

## Check that it worked

Two things, and the second is the one that proves it end to end:

      - `llm models` lists `axforge` among the models. If it does not, the YAML is in the wrong directory.
- `llm -m axforge 'hello'` answers.

      - The call appears in the console at
      Billing & usage within a minute or
      two. Nothing else confirms that _your_ key reached _our_ API — a reply
      alone could be a cache or another provider.

## When it does not work

      | What you see | What it means | Fix |  |

        | `axforge` not in `llm models` | the file is not in llm's config directory | find it with `dirname "$(llm logs path)"` — it is not your project folder |  |

        | `401` | the key | `llm keys set axforge`, or the key in the YAML |  |

        | `Unknown model` | a typo in `model_id` | the id you call must match the one in the file |  |

    Run the self-test first when you are
    unsure — it says in one click whether the problem is your key, your quota or us, so you
    know whether the tool is worth debugging at all.

      &larr; LibreChat
      Back to all tools &rarr;



## How GPU rentals work (/docs/gpu-rentals/)


# How GPU rentals work

Rent a dedicated GPU by the hour, week, month or year, with full SSH
    access to the machine. Here's the whole flow — request, offer, pay, run,
    stop — in plain bullets.

## 1. The queue

      - Send a request from the console. You join a **queue** for that GPU type.

      - 🔴! It's **first-come, first-served**: everyone in line is offered the machine, and the **first to complete payment gets it**.

      - You get **1 offer email**, then **about one an hour** so you don't miss it. The window is a **few hours**.

      - Miss it, or someone pays first? Your request stays in line for the next machine — you're never dropped.

## 2. Paying

      - Pay by **card (Stripe)** or from your **AxForge balance** — the offer email and your console both open secure checkout.

      - The exact price is in the offer email. Dedicated DGX Spark (GB10) is from €0.55/hour, billed by the hour, week, month or year.

      - Access opens the moment payment is confirmed. Then you add your SSH key on the machine page.

      - 🔴 No refunds once you've paid — not for stopping early, not for unused hours. The one exception: you paid and the machine never worked (if you could log in and start it, it worked).

      - ⚠️ Never connect? A rental nobody connected to ends when its paid hours end — nothing more is charged, nothing is refunded.

## 3. On demand — 4 h minimum, 48 h hard cap

      - On demand keeps the machine running — and keeps billing — while you have balance.

      - ⚠️ On demand: 4 h minimum · 48 h hard cap — it ends 48 h after it starts, whatever your balance.

      - 🔴 No refunds once paid — only exception: a machine that never worked.

## 4. The off switch

      - Stop it any time from your console.

      - 🔴! Stopping is the only thing that stops billing on demand — before the 48 h cap ends it for you.

    **On-demand rentals keep running — and keep billing — until you press Stop or your AxForge balance runs out. Disconnecting SSH, closing the browser, or logging out does NOT stop it.**

## 5. Nothing is saved

      - ⚠️ **Nothing is saved.** Per the rental agreement we keep no data or work.

      - When a rental ends, the machine and everything on it (including `/workspace`) are deleted and cannot be recovered.

      - Back up anything you want to keep **before** you stop.

    ⚠️ Encrypted backup service isn't available yet (in progress). Until then, copying your work out yourself is the only backup.

      &larr; Overview
      GPU Rental &rarr;



## Regions & data handling (/docs/regions-data/)


# Regions & data handling

Your requests run in the EU, on hardware we own, and nothing you send is
    kept. This page states exactly where, on what, and what little metadata
    remains.

## Regions

        | Region | Location | Service | Status |  |

        | eu-se-1 | Stockholm | Serverless inference — the API at api.axforge.ai/v1 | live |  |

        | eu-es-1 | Málaga | Dedicated GPU rental — NVIDIA DGX Spark (GB10) with full SSH access | live |  |

## Region pinning

Every API key is pinned to eu-se-1 · Stockholm, and all inference for that key runs in
    that region. There is no cross-region fallback — a request either runs in
    your region or fails.

```
$ curl -sS https://api.axforge.ai/v1/chat/completions \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen3.8-27b-nvfp4",
       "messages": [{"role": "user", "content": "ping"}]}'
```

## Transport

TLS 1.3, terminated in the EU.

## Zero retention

Prompts and completions are processed in memory in the EU — not written
    to disk, not logged, not retained, and never used to train. This applies to
    every endpoint: chat, embeddings, images, audio. The commitment in full:
    axforge.ai/privacy.

## What metadata is kept

Request metadata only — token counts, timestamps, and status — retained
    for billing and operations. Never the content.

        | Data | Kept? |  |

        | Prompts, completions, images, audio | **No** — processed in memory only |  |

        | Token counts | Yes — billing |  |

        | Timestamps | Yes — billing and operations |  |

        | Request status | Yes — operations |  |

## The hardware, by name

Inference runs on NVIDIA DGX Spark (GB10) systems that AxForge owns —
    not resold hyperscaler capacity. The same machine is rentable with full SSH
    access from €0.55/hour:
    DGX Spark rental and the GB10 technical page.

## Subprocessors

EU-hosted infrastructure; the register is in the Trust Centre. Inference itself
    runs on our own hardware.

## Compliance posture

Infrastructure designed for EU data-residency and GDPR-sensitive
    workloads. Everything your assessment needs is stated plainly on this
    page: EU regions, zero retention, named hardware, EU-hosted infrastructure.
    More:
    data residency in the Trust Centre,
    GDPR compliance and
    the sovereignty page.

      &larr; Speech & music
      Errors & limits &rarr;



## Rules & responsibilities (/docs/responsibilities/)


# Rules & responsibilities

    What you can build on AxForge, what you must not, and who is
    responsible for what. This is a plain-language orientation for developers — the
    binding documents are the Acceptable Use Policy,
    the Terms, and the DPA. It is not
    legal advice.

## Who is responsible for what

AxForge provides EU-hosted inference and keeps your content private; you decide
    what to send and what to build. In GDPR terms you are the
    controller and AxForge is a
    processor for the data you send.

        AxForge is responsible for

          - Running inference in the EU on open-weight models, in the
          region your key is pinned to.

          - Zero retention: not storing,
          logging, or training on your prompts or completions.

          - Securing the platform and isolating each
          tenant.

          - Publishing which models serve each capability
          (model transparency).

        You are responsible for

          - Having a lawful basis for any personal data you send, and minimising it.

          - What your application does with model output, and any human oversight it
          needs.

          - Disclosing to your end users that they are interacting with AI where the
          EU AI Act requires it.

          - Keeping your keys secret and
          rotating them if exposed.

## Do / don't

The Acceptable Use Policy is the full list; these
    are the essentials.

        Do

          - Build assistants, search, extraction, coding tools, and content
          generation for legitimate purposes.

          - Send the minimum data a task needs; prefer
          pseudonymised inputs.

          - Keep a human in the loop for decisions that affect people materially.

          - Handle errors and rate limits with
          backoff and retries.

        Don't

          - Generate content that is illegal, that harms or targets people, or that
          facilitates fraud, malware, or abuse.

          - Use output to make consequential decisions about people without human
          review (credit, employment, legal, medical).

          - Send data you have no right to process, or special-category data without
          a proper basis and safeguards.

          - Embed a raw key in a browser, mobile app, or public repo — proxy through
          your own backend.

## Examples by use case

How the split plays out in the things people actually build.

### Support / chat assistant

      - **Fine:** answer product questions, write replies, summarise a ticket. Tell
      users it's an AI assistant.

      - **Watch:** don't let it promise refunds or make binding commitments without
      a human check; don't feed it a customer's full account record when the question
      needs one order.

### RAG over internal documents

      - **Fine:** embed your docs, retrieve the
      relevant passages, and pass them as context. Content is processed in memory and
      not retained.

      - **Watch:** you control your vector store — apply your own access controls so
      a user can't retrieve documents they shouldn't see. Redact secrets you don't need
      the model to read.

### Coding assistant

      - **Fine:** point aider,
      Continue or
      Cline at AxForge and let it read and edit your
      repo.

      - **Watch:** review generated code before shipping; don't paste live
      credentials or customer data into prompts.

### Images, speech & music

      - **Fine:** generate and edit assets, transcribe audio, synthesise speech for
      your own product.

      - **Watch:** don't impersonate a real person's likeness or voice, or produce
      deceptive media; respect the rights in any source material you upload.

### Personal data (PII)

      - **Fine:** process personal data you have a lawful basis for — it stays in
      the EU and is never retained or trained on.

      - **Watch:** you're the controller. Sign the DPA,
      minimise what you send, and honour your users' rights. See
      GDPR & AI.

## If something needs a review

Building something novel, high-risk, or at scale and want a second opinion on the
    boundaries? Talk to an engineer — we would rather
    help you get it right than find out later.

      &larr; Errors & limits
      Acceptable Use Policy &rarr;

