Documentation

Frontière AI API reference

The Frontière AI API is an OpenAI-compatible gateway to a curated catalog of powerful open-source models hosted in Europe. Point your existing SDK or HTTP client at the base URL below, authenticate with an API key from your dashboard, and every live model is available through the same endpoint — each one labeled EU sovereign or fast access, so you always know which jurisdiction serves your data.

Overview

The API implements the OpenAI chat-completions contract. If your code already talks to OpenAI — through the official Python or JavaScript SDK, LangChain, or a plain HTTP client — you only change two things: the base URL and the key. One key unlocks the whole catalog.

Machine-readable OpenAPI spec: /openapi.json (OpenAPI 3.1).

Base URL
https://getfrontiereai.eu/api/v1

Two endpoints:

POST /chat/completionsRun a model (streaming supported)
GET /modelsList the catalog — public, no key required

Authentication

Every call to the chat endpoint carries your API key in the Authorization header. Keys are created in the dashboard under API keys — the full value (sk-front-…) is shown once at creation, then only its prefix. Create one key per environment or app; each can be revoked independently without touching the others.

Header
Authorization: Bearer sk-front-…

Keep keys server-side (environment variables, a secret manager) — never in client-side code or a public repository. If a key leaks, revoke it from the dashboard and create a new one; the old one stops working immediately.

Quickstart

The same call in three languages. The Python and JavaScript examples use the official OpenAI SDK (pip install openai / npm install openai) — no Frontière AI-specific library needed.

curl
curl https://getfrontiereai.eu/api/v1/chat/completions \
  -H "Authorization: Bearer $FRONTIERE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm-5.2",
    "messages": [{"role": "user", "content": "Bonjour"}]
  }'
Python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://getfrontiereai.eu/api/v1",
    api_key=os.environ["FRONTIERE_KEY"],
)

reply = client.chat.completions.create(
    model="glm-5.2",
    messages=[{"role": "user", "content": "Bonjour"}],
)
print(reply.choices[0].message.content)
JavaScript / TypeScript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://getfrontiereai.eu/api/v1",
  apiKey: process.env.FRONTIERE_KEY,
});

const reply = await client.chat.completions.create({
  model: "glm-5.2",
  messages: [{ role: "user", content: "Bonjour" }],
});
console.log(reply.choices[0].message.content);

Trying a model without writing code

Your dashboard includes a console: a chat window onto the same catalog, over the same EU routing, at the same per-token price. It is there to answer “which model should I use, with which system prompt and which parameters?” before you wire anything up — every reply shows the model, the token counts and the exact amount debited.

Once a prompt behaves the way you want, the console turns the current model, parameters and prompt into a ready-to-paste curl, Python or JavaScript call against this API. Conversations are held in your browser, not on our servers, unless you explicitly sync a thread to your account.

Open the console

Chat completions

POST
https://getfrontiereai.eu/api/v1/chat/completions

Send a conversation, get the model's reply. Request body fields:

FieldTypeDescription
modelstring — requiredA live model ID from the catalog, e.g. glm-5.2 (see Models below).
messagesarray — requiredThe conversation so far: a list of {role, content} objects with roles system, user and assistant, in OpenAI format.
streambooleantrue streams the reply as server-sent events (see Streaming).
max_tokensintegerCap on completion tokens. On reasoning models, thinking counts against it — omit it or allow at least ~1,000 (see Reasoning models).
temperature, top_p, stop, …variousStandard OpenAI sampling parameters, forwarded unchanged to the provider serving the model.

The request body is forwarded to the provider hosting the model, so the standard OpenAI parameters behave exactly as documented by OpenAI. Fields a given provider does not support are ignored by that provider.

The response is a standard chat.completion object. The usage block is what your balance is billed against — token-exact, including reasoning tokens on reasoning models:

200 — application/json
{
  "id": "chatcmpl-…",
  "object": "chat.completion",
  "model": "glm-5.2",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Bonjour ! Comment puis-je aider ?" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 9, "completion_tokens": 42, "total_tokens": 51 }
}

Streaming

Set "stream": true and the reply arrives as server-sent events — data: chunks with the incremental delta, terminated by data: [DONE]. This is the same wire format as OpenAI, so SDK streaming helpers work unchanged.

Python — stream
stream = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[{"role": "user", "content": "Bonjour"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

Frontière AI always enables stream_options.include_usage upstream: the final data chunk before [DONE] carries the usage object (and an empty choices array). That chunk is how streamed calls are billed exactly — don't be surprised by it if you parse the stream by hand.

Models

GET
https://getfrontiereai.eu/api/v1/models

The catalog is served live by GET /api/v1/models — public, no key required. It lists live models only, so anything you discover there is callable right now; add ?include=all to also get the coming-soon entries. Each entry carries the OpenAI fields (id, object, created, owned_by), context_length and pricing (client price in EUR per million tokens, input and output) when verified, plus four Frontière AI-specific ones: status ("live" or "coming-soon"), sovereign (boolean), tool_calling (boolean, present only where we measured it with a real call — filter on it before building an agent) and note (usage caveat, when one applies).

200 — application/json
{
  "object": "list",
  "data": [
    {
      "id": "glm-5.2",
      "object": "model",
      "created": 1786022547,
      "owned_by": "Zhipu / Z.ai",
      "label": "GLM-5.2 (Zhipu/Z.ai)",
      "provider": "scaleway",
      "status": "live",
      "sovereign": true,
      "tool_calling": true,
      "pricing": {
        "currency": "EUR",
        "input_per_million": 2.52,
        "output_per_million": 7.7
      },
      "note": "Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000."
    }
  ]
}

sovereign: true means the company operating the infrastructure has no non-EU capital or jurisdictional control (the SecNumCloud principle) — OVHcloud, Scaleway, or dedicated EU servers. Models served through US infrastructure (even in an EU region) are labeled fast access, never sovereign, so you can filter per call with full information.

Modelmodel IDHostingStatus
Qwen3 235B (instruct)qwen3-235bEU sovereignlive
Qwen3.5 397B (multimodal)qwen3.5-397bEU sovereignlive
GLM-5.2 (Zhipu/Z.ai)glm-5.2EU sovereignlive
DeepSeek V4 Flash 0731 (1M context)deepseek-v4-flash-0731EU sovereignlive
Llama 3.3 70Bllama-3.3-70bEU sovereignlive
Qwen3.6 27B (multimodal)qwen3.6-27bEU sovereignlive
Qwen3.5 9B (fast, budget)qwen3.5-9bEU sovereignlive
Qwen3 32Bqwen3-32bEU sovereignlive
Qwen3 Coder 30Bqwen3-coder-30bEU sovereignlive
Qwen2.5-VL 72B (vision)qwen2.5-vl-72bEU sovereignlive
GPT-OSS 120B (OpenAI)gpt-oss-120bEU sovereignlive
GPT-OSS 20B (OpenAI)gpt-oss-20bEU sovereignlive
Mistral Small 3.2 24Bmistral-small-3.2-24bEU sovereignlive
Kimi K3 (2.8T parameters, 1M context)kimi-k3Fast access (US)live
Kimi K3 — EU sovereign variantkimi-k3-souverainEU sovereignComing soon
Muse Spark 1.1 (1M context)muse-spark-1.1Fast access (US)live
Muse Spark 1.2 (1M context)muse-spark-1.2Fast access (US)live
GLM-5.3 Flash (Zhipu/Z.ai)glm-5.3-flashFast access (US)live
Qwen3.8 Max (2.4T, 1M context)qwen3.8-maxFast access (US)live
Qwen3.8 27B (multimodal)qwen3.8-27bEU sovereignlive
Qwen3.8 Flash (Qwen)qwen3.8-flashFast access (US)live
DeepSeek R1 (671B MoE)deepseek-r1Fast access (US)live
DeepSeek V4 Pro (345B MoE)deepseek-v4-proFast access (US)live
DeepSeek R1 (Distill Qwen 32B)deepseek-r1-distill-qwen-32bFast access (US)live
DeepSeek R1 (Distill Qwen 14B)deepseek-r1-distill-qwen-14bFast access (US)live
GLM-5.3 (Zhipu/Z.ai)glm-5.3Fast access (US)live
Gemma 3 27B (Google)gemma-3-27bFast access (US)live
DeepSeek V4.1 Flash (552B MoE, 1M context)deepseek-v4.1-flashFast access (US)live

Model notes

  • glm-5.2Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • deepseek-v4-flash-0731Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • qwen2.5-vl-72bVision model — its provider rejects tool calls with a 400, so it cannot back an agent. Use it for image understanding, not for function calling.
  • kimi-k3Reasoning model. First call after a quiet period can take a few minutes to warm up — then it responds in seconds.
  • muse-spark-1.1Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • muse-spark-1.2Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • glm-5.3-flashReasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • qwen3.8-27bReasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • deepseek-r1Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • deepseek-r1-distill-qwen-32bReasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • deepseek-r1-distill-qwen-14bReasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • glm-5.3Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.
  • deepseek-v4.1-flashMultimodal reasoning model (text + images). First call after a quiet period can take a while to warm up. Omit max_tokens or allow plenty of headroom for the chain of thought.

Per-token prices for every live model are listed on the model catalog. Calling a coming-soon model returns HTTP 409 — and records your interest: asking for a model is the best way to vote for its priority. Unknown model IDs return 404 with a pointer back to the catalog.

Errors

Errors are JSON, OpenAI-style — an error object with a human-readable message and a stable type you can branch on:

402 — application/json
{
  "error": {
    "message": "Insufficient credit balance. Top up your account from the dashboard.",
    "type": "insufficient_credit"
  }
}
StatustypeMeaning
400invalid_requestThe body is not valid JSON or the model field is missing.
401invalid_api_keyMissing, malformed or revoked API key in the Authorization header.
402insufficient_creditYour prepaid balance is at zero. Top up from the dashboard to resume.
404model_not_foundThe model ID is not in the catalog — list valid IDs via GET /api/v1/models.
409model_not_liveThe model exists but is still coming soon. Pick a live model.
502upstream_errorThe provider returned an unreadable response. Retry; report it if it persists.
503provider_not_configuredNo provider credentials for this model on this instance.

Provider-side errors (rate limits, overloaded model, invalid parameter for that provider) are relayed as-is with their upstream status code and body — what you would get calling the provider directly.

Credit & billing

Frontière AI is prepaid: you top up a balance (from €10, via Stripe, in the dashboard) and every successful call draws it down. No subscription, no card on file, no invoice at the end of the month — when the balance reaches zero, calls return 402 and nothing else happens.

Billing is token-exact, computed from the usage object the provider reports for your call: prompt tokens at the model's input rate, completion tokens (including reasoning tokens) at the output rate. When a provider serves part of your prompt from its cache and reports it (usage.prompt_tokens_details.cached_tokens), those tokens are billed at the model's cheaper cache rate.

Your dashboard shows the balance, a per-call billing history (tokens in/out and price per call), and top-up history. The price of each call is charged at the moment the provider returns its usage — streamed calls included, via the final usage chunk.

Reasoning models

glm-5.2 and kimi-k3 think before they answer: the thinking consumes completion tokens (billed as output) before any visible text is produced. With a small max_tokens the entire budget can go to reasoning — the reply then comes back with content: null and finish_reason "length", which looks like an empty answer. Omit max_tokens or allow at least ~1,000.

kimi-k3 additionally scales to zero between uses: the first call after a quiet period can take a few minutes to warm up, then it answers in seconds. It is served through US infrastructure and labeled fast access — check the sovereign field if jurisdiction matters for your workload.

Reasoning also takes wall-clock time: on a substantial prompt, glm-5.2 can think for several minutes before the full reply is ready. Set your HTTP client's timeout generously (many tools default to well under a minute — Make.com's HTTP module, for instance, cuts at 40 seconds unless you raise it), or better, use streaming: the first chunk arrives in under a second and the connection stays active throughout.

Embeddings

POST /api/v1/embeddings turns text into vectors, same authentication and same prepaid billing as chat. The request body follows OpenAI's: model, and input as a string or an array of strings. The response is an object of type list whose data carries one embedding per input, in the order you sent them.

curl
curl https://getfrontiereai.eu/api/v1/embeddings \
  -H "Authorization: Bearer $FRONTIERE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bge-m3",
    "input": ["Premier document", "Second document"]
  }'

Embedding models live in their own catalog — a chat model sent here answers 404, and an embedding model sent to /chat/completions does too. GET /api/v1/models?kind=embedding returns only the valid ones; every entry in the catalog also carries a kind field ("chat" or "embedding") so a single call can tell them apart.

ModelDimensionsContext
bge-m310248192
bge-multilingual-gemma235848192
qwen3-embedding-8b409640960

Pick by dimensions before you index anything: the vector length is part of your storage schema, and changing model later means recomputing every vector you hold. Billing counts input tokens only — an embedding produces no output tokens, so there is no output rate.

MCP server

Frontière AI exposes a Model Context Protocol (MCP) endpoint that gives AI agents (Claude Code, Codex, Cursor, Roo Code, Continue, etc.) full programmatic access to the Frontière AI API. Any MCP-compatible client connects with a single URL and can browse the catalog, run inference, create embeddings, and check account balance — all over standardized JSON-RPC 2.0.

Connect your agent's MCP client to the endpoint URL below. The endpoint uses stateless HTTP: each POST request is a self-contained JSON-RPC 2.0 call with a synchronous response — no SSE streams, no session state. Authentication is done by sending your API key as an Authorization header on each request (e.g. Authorization: Bearer sk-front-...). Read-only tools (catalog queries) work without a key; inference and balance tools require one.

The MCP server exposes eight tools: three for catalog discovery (list_models, get_model, search_models — no auth required) and five for authenticated operations (chat_completion forwards a chat request to the gateway with full token billing, create_embedding generates vectors from text, check_balance returns your current credit balance, and web_search / web_fetch give the agent live web access through an EU search provider). A dedicated page covers setup and per-tool detail.

MCP endpoint
https://getfrontiereai.eu/api/mcp

Transport: POST with application/json — JSON-RPC 2.0, stateless (no SSE, no sessions).

Available tools

ToolDescription
list_modelsList all models with optional filters: filter (live/coming-soon/sovereign), provider, kind (chat/embedding), includeComingSoon
get_modelGet detailed info for a single model by slug: pricing, vendor, license, parameters, sovereignty, compliance data
search_modelsSearch models by keyword across slug, name, vendor, provider, and modality
chat_completionRun inference on any live model. Supports temperature, max_tokens, tool calling. Usage billed per token (same pricing as the REST API)
create_embeddingGenerate text embeddings for RAG/semantic search. Supports string or array input. Usage billed per token
check_balanceCheck current prepaid credit balance in EUR (no parameters needed)
web_searchLive web search (Linkup, EU) returning up to 8 results with the full page text of each — covered by our search quota, not billed against your balance
web_fetchRead one web page as clean markdown (Linkup, EU) — follow up on a search result URL

Integrations

Anything that speaks the OpenAI protocol works by changing the base URL and the key — SDKs, LangChain, agent frameworks, no-code tools. Some platforms need a few specific steps, and agents in particular need tool calling, which we measured model by model:

Integrations: agent platforms, tool-calling matrix, known gaps

FAQ

Can I try a model without writing any code?

Yes — the dashboard includes a web console that talks to the same catalog over the same EU routing, at the same per-token price as the API. Use it to settle on a model, a system prompt and parameters, then have it generate the equivalent curl, Python or JavaScript call. Conversations stay in your browser unless you explicitly sync a thread to your account.

Can I use the official OpenAI SDK?

Yes. The API implements the OpenAI chat-completions contract: point base_url at the Frontière AI API and pass your key as api_key — the official Python and JavaScript SDKs, and tools built on them, work unchanged.

What happens when my credit reaches zero?

Calls return HTTP 402 (insufficient_credit) and stop being served. Nothing else happens — no overdraft, no automatic charge. Top up from the dashboard to resume.

How do I know whether a model is EU sovereign?

Every model carries a sovereign boolean in GET /api/v1/models and a badge on the catalog. sovereign: true means no non-EU capital or jurisdictional control over the operator (SecNumCloud principle); models served through US infrastructure are always labeled fast access, never sovereign.

Why did my reply come back empty?

You most likely called a reasoning model (glm-5.2, kimi-k3) with a small max_tokens: the whole budget went to thinking and content came back null with finish_reason "length". Omit max_tokens or allow at least ~1,000.

Ready to make your first call?

Create an account, top up from €10, paste two lines — the whole catalog behind one key.

Create an account
Create an account