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. 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. 18 of the 25 live models are EU sovereign, run by EU-controlled providers; the others are fast access, run by US companies — each one is labeled, 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).
https://getfrontiereai.eu/api/v1Endpoints:
POST /chat/completions | Run a chat model (streaming supported) |
POST /embeddings | Turn text into vectors |
POST /images/generations | Generate images from text |
POST /images/edits | Generate portraits from reference face photos |
GET /models | List the catalog — public, no key required |
GET /models/{id} | Retrieve one model by ID — public, no key required |
Authentication
Every call to the chat and embeddings endpoints 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.
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 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"}]
}'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)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, with the same default routing and 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, never on our servers.
Agent mode
The console also has an Agent switch. With it on, the model you picked does more than reply: it works through a task step by step — searching the web, writing files, creating documents and images — until it is done. It does not run code. Like the rest of the console, it is a test bench for this API, not an alternative to it — the same catalog, the same per-token price, a spend limit you set for each turn, and the exact cost of the turn shown when it ends. The conversation and the agent's files stay in your browser.
What the agent can do:
- Search the web. It can search and read web pages, up to 40 lookups per turn and 300 per day. Each search costs €0.00756 and each page read €0.001512 (VAT included), counted in the turn's spend limit, plus the tokens of what the model reads.
- Write and edit files. Text files of any kind — Markdown, CSV, JSON, HTML… — in the conversation's workspace, where they stay for the next turns of the same conversation.
- Create documents. Word (.docx) and PDF documents from Markdown, and Excel (.xlsx) workbooks. They are generated in our servers' memory and never kept there.
- Generate images. With FLUX.1 [schnell], one at a time and up to 12 per turn, square, landscape or portrait. Each image becomes a JPEG file of the conversation, shown as a thumbnail and downloadable like any other file. An image is billed per second of generation, like the image API — about €0.02 for a square image.
- Hand you its files. Every file the agent writes can be downloaded from the conversation, one at a time. Files are kept in your browser, with the conversation.
Limits:
- Models. Only models that support tool calling can run an agent turn; the Integrations page shows which ones. Choose the model yourself: agent mode is not available with Auto.
- One turn at a time. Per account. A turn takes 40 steps at most and starts no new step after 10 minutes; Continue carries on in a new turn.
- No code. The agent cannot run code, install software or reach your computer: it works only through the tools above.
- Attachments. As in the chat: the text of the documents you attach is extracted in your browser and added to your message, and up to 4 images can be attached for models that accept them. A whole request, files of the conversation included, is limited to 4 MB.
- Files. A conversation's workspace holds up to 200 files. A text file holds up to 1,000,000 characters, a document or an image up to 5 MB, and a turn can produce up to 25 MB of files.
- Spend limit. Per turn: €0.50, €1, €2, €5, or €10. The default is €2, and a limit is never higher than your balance.
How the spend limit works. Before each model call — and each image — the most that call could cost is set aside against the turn's limit and your balance, and released once the real cost is billed: a call that would not fit is refused, which ends the turn. You can send another message, with a new limit, to carry on. You are billed the real cost, never the amount set aside, so a turn stays within its limit; the one exception is a provider that reports more output than the cap we set on the call. Stopping a turn does not cancel what was already sent: the model call in progress is completed and billed, and so is an image being generated, even if the turn ends before it reaches your browser.
Where your data goes. Each model call follows the rule of the model you chose: an EU sovereign model is only run by its EU providers, a fast-access model by a US company, and the cost line under each agent answer names the providers behind it. What the agent sends to that provider includes the content of the files it reads and the results of its tools. When it generates an image, the description it writes goes to Infomaniak, a Swiss company, in its own data centers in Switzerland — outside the EU, under an EU adequacy decision — and the cost line shows it with a Swiss flag. The agent itself runs in our application on Vercel, a US company, in its Paris region: your messages and the conversation's files pass through it for the length of a turn and are never stored there. The privacy policy has the details.
Agent mode exists only in the web console. The API (/api/v1) has no agent mode: it relays your request to the model, and never chains steps or tools for you or applies a per-turn spend limit. The MCP server has none either.
Chat completions
https://getfrontiereai.eu/api/v1/chat/completionsSend a conversation, get the model's reply. Request body fields:
| Field | Type | Description |
|---|---|---|
model | string — required | A live model ID from the catalog, e.g. glm-5.2 (see Models below). |
messages | array — required | The conversation so far: a list of {role, content} objects with roles system, user and assistant, in OpenAI format. |
stream | boolean | true streams the reply as server-sent events (see Streaming). |
max_tokens | integer | Cap 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, … | various | Standard 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:
{
"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.
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
https://getfrontiereai.eu/api/v1/modelsThe 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 paused and coming-soon entries, and ?kind=chat or ?kind=embedding to get a single family. Each entry carries the OpenAI fields (id, object, created, owned_by) plus Frontière AI-specific ones: kind ("chat" or "embedding"), label, provider (the route tried first by default — the one x-routed-provider names on a normal call), status ("live", "paused" or "coming-soon"), pause (since, reason and reason_fr — present only on a paused model), sovereign (boolean), providers (the routing chain in priority order, present only when a model has more than one route; a route flagged requires_opt_in: true is used only if you allow every provider — see Data routing), compliance (license, AI Act status, EU data residency, and data_retention: zero_prompt_retention when every default route documents zero prompt retention (OVHcloud), no_storage_except_errors on Scaleway (no prompt stored except requests that cause errors or abuse, kept up to two weeks), provider_policy when a fast-access provider's own retention policy applies — Frontière AI itself stores no prompt or completion), verified (the six Frontière Verified checks — true once a check has been run, recorded and passed, false otherwise (not run yet, or run without passing); absent when no check has started), tool_calling (present only where we measured it with a real call — filter on it before building an agent), context_length and pricing (client price in EUR per million tokens; vat_included: true — VAT is always included) when verified, and note (usage caveat, when one applies).
{
"object": "list",
"data": [
{
"id": "glm-5.2",
"object": "model",
"kind": "chat",
"created": 1786022547,
"owned_by": "Zhipu / Z.ai",
"label": "GLM-5.2 (Zhipu/Z.ai)",
"label_fr": "GLM-5.2 (Zhipu/Z.ai)",
"provider": "scaleway",
"status": "live",
"sovereign": true,
"compliance": {
"open_weights": true,
"license": "MIT",
"license_restricted": false,
"gpai_status": "gpai",
"systemic_risk": null,
"model_card_url": "https://huggingface.co/zai-org/GLM-5.2",
"training_docs_url": "https://arxiv.org/abs/2602.15763",
"data_retention": "no_storage_except_errors",
"eu_data_residency": true
},
"verified": {
"license": true,
"provenance": true,
"security": false,
"gdpr": true,
"benchmarks": false,
"api": true
},
"tool_calling": true,
"context_length": 256000,
"pricing": {
"currency": "EUR",
"vat_included": true,
"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.",
"note_fr": "Modèle de raisonnement — réfléchit avant de répondre. Omettez max_tokens ou prévoyez au moins ~1 000."
}
]
}GET /api/v1/models/{id} returns a single entry in the same shape — the call behind models.retrieve() in the OpenAI SDKs. An unknown ID returns 404 model_not_found.
sovereign: true means the company operating the infrastructure has no non-EU capital or jurisdictional control (the SecNumCloud principle) — today AKI.IO, Infomaniak, Mistral AI, OVHcloud, or Scaleway. Models run by US companies (Modal and OpenRouter) are labeled fast access, never sovereign, even when served from an EU region, so you can filter per call with full information. Dedicated EU deployments for a given workload are available on request. The first model planned on a dedicated EU server operated by Frontière AI — kimi-k3-souverain — is listed as coming soon; no live model runs there yet.
| Model | model ID | Hosting | Status |
|---|---|---|---|
| Qwen3 235B (instruct) | qwen3-235b | EU sovereign | live |
| Qwen3.5 397B (multimodal) | qwen3.5-397b | EU sovereign | live |
| GLM-5.2 (Zhipu/Z.ai) | glm-5.2 | EU sovereign | live |
| DeepSeek V4 Flash 0731 | deepseek-v4-flash-0731 | EU sovereign | live |
| Llama 3.3 70B | llama-3.3-70b | EU sovereign | live |
| Qwen3.6 27B (multimodal) | qwen3.6-27b | EU sovereign | paused |
| Qwen3.6 35B A3B (multimodal) | qwen3.6-35b | EU sovereign | live |
| Qwen3.5 9B (fast, budget) | qwen3.5-9b | EU sovereign | paused |
| Qwen3 Coder 30B | qwen3-coder-30b | EU sovereign | live |
| Qwen2.5-VL 72B (vision) | qwen2.5-vl-72b | EU sovereign | paused |
| Pixtral 12B (vision) | pixtral-12b | EU sovereign | live |
| GPT-OSS 120B (OpenAI) | gpt-oss-120b | EU sovereign | live |
| GPT-OSS 20B (OpenAI) | gpt-oss-20b | EU sovereign | paused |
| Mistral Small 3.2 24B | mistral-small-3.2-24b | EU sovereign | live |
| Mistral Large 4 (preview, 512K context) | mistral-large-4 | EU sovereign | live |
| Apertus v1.5 70B (Swiss open model) | apertus-v1.5-70b | EU sovereign | live |
| Kimi K3 (2.8T parameters, 1M context) | kimi-k3 | Fast access (US) | live |
| Kimi K3 — EU sovereign variant | kimi-k3-souverain | EU sovereign | Coming soon |
| Muse Spark 1.1 (1M context) | muse-spark-1.1 | Fast access (US) | live |
| Muse Spark 1.2 (1M context) | muse-spark-1.2 | Fast access (US) | live |
| GLM-5.3 Flash (Zhipu/Z.ai) | glm-5.3-flash | Fast access (US) | live |
| Qwen3.8 Max (2.4T, 1M context) | qwen3.8-max | Fast access (US) | paused |
| Qwen3.8 27B (multimodal) | qwen3.8-27b | EU sovereign | live |
| Qwen3.8 Flash (Qwen) | qwen3.8-flash | Fast access (US) | live |
| DeepSeek V4 Pro (1.6T MoE) | deepseek-v4-pro | Fast access (US) | live |
| GLM-5.3 (Zhipu/Z.ai) | glm-5.3 | EU sovereign | live |
| Gemma 3 27B (Google) | gemma-3-27b | Fast access (US) | live |
| DeepSeek V4.1 Flash (552B MoE, 1M context) | deepseek-v4.1-flash | EU sovereign | live |
| Gemma 4 26B (A4B MoE) | gemma-4-26b | EU sovereign | live |
| Kolibri 1 (Aleph Alpha) | kolibri-1 | EU sovereign | live |
| Mistral Small 4 119B | mistral-small-4-119b | EU sovereign | live |
Model notes
glm-5.2— Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.deepseek-v4-flash-0731— Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.mistral-large-4— Public preview from Mistral: open weights announced for late October 2026. Answers directly by default; send reasoning_effort (any value but "none") to turn on thinking, returned in reasoning_content and billed as output. As a preview model, it falls under § 4.3 of Mistral's commercial terms: Mistral may use the data and outputs to train its models, and opt-outs, zero data retention included, do not apply.apertus-v1.5-70b— Served by Infomaniak in Switzerland (outside the EU, under an EU adequacy decision). Context window of 100K tokens, prompt and completion combined. With tool_choice "auto" it often answers without calling the tool: send "required" or a named function. Listed as beta by the host.kimi-k3— Reasoning model. First call after a quiet period can take a few minutes to warm up — then it responds in seconds.muse-spark-1.1— Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.muse-spark-1.2— Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.glm-5.3-flash— Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.qwen3.8-27b— Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.glm-5.3— Reasoning model — thinks before answering. Omit max_tokens or allow at least ~1,000.deepseek-v4.1-flash— Multimodal reasoning model (text + images). Omit max_tokens or allow plenty of headroom for the chain of thought.mistral-small-4-119b— Hybrid model from Mistral: answers directly by default; send reasoning_effort (any value but "none") to turn on thinking, returned in reasoning_content.
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.
Data routing
Each model has a routing chain: a single provider, or a primary provider followed by fallbacks. Two optional signals — a request header and a per-key setting — decide which of those routes a call may use:
| Signal | Routes a call may use |
|---|---|
| Nothing set (default) | A model labeled EU sovereign uses sovereign providers only — its fallbacks included. A fast-access model may use all its routes, which are run by US companies and labeled as such. |
X-Data-Sensitivity: sensitiveor a key set to “Sovereign only” | Sovereign providers only, for every model. A fast-access model then answers 503 no_sovereign_provider instead of being served by a US company. |
X-Data-Sensitivity: insensitiveor a key set to “All providers (US fallback allowed)” | Every route of the model, including a non-sovereign fallback behind a sovereign model. The response headers then tell you which provider actually served the call. |
Live sovereign models that have a non-sovereign fallback (flagged requires_opt_in: true in GET /api/v1/models) — the only ones the “All providers (US fallback allowed)” setting changes: glm-5.3, deepseek-v4.1-flash.
The per-key setting is in your dashboard (API keys → Data sensitivity), one value per key. When the header and the key disagree, the stricter one wins: a key set to “Sovereign only” cannot be loosened by the header, so every call made with it stays on sovereign providers.
curl -i https://getfrontiereai.eu/api/v1/chat/completions \
-H "Authorization: Bearer $FRONTIERE_KEY" \
-H "Content-Type: application/json" \
-H "X-Data-Sensitivity: sensitive" \
-d '{
"model": "glm-5.2",
"messages": [{"role": "user", "content": "Bonjour"}]
}'Every chat-completion response that reached a provider — streamed or not — carries headers that say where it was served:
| Response header | Value |
|---|---|
x-routed-provider | The provider that served the call: aki, infomaniak, mistral, ovhcloud, scaleway, modal, or openrouter. |
x-sovereign | true if that provider is EU sovereign, false if it is a US company. |
x-fallback-provider | true when the first eligible route failed and a later one answered; absent otherwise. |
x-fallback-attempts | Number of routes tried, sent together with x-fallback-provider. |
HTTP/2 200
content-type: application/json
x-routed-provider: scaleway
x-sovereign: trueFailover happens when a provider answers 429, 500, 502, 503 or 504, or cannot be reached, and the model has another eligible route. It never widens the rules above: a call restricted to sovereign providers that runs out of sovereign routes gets the provider's error, never an answer from a US company.
With the OpenAI SDK, set the header once on the client and read the routing headers from the raw response (in JavaScript: defaultHeaders and .withResponse()):
client = OpenAI(
base_url="https://getfrontiereai.eu/api/v1",
api_key=os.environ["FRONTIERE_KEY"],
default_headers={"X-Data-Sensitivity": "sensitive"},
)
raw = client.chat.completions.with_raw_response.create(
model="glm-5.2",
messages=[{"role": "user", "content": "Bonjour"}],
)
print(raw.headers.get("x-routed-provider"), raw.headers.get("x-sovereign"))
reply = raw.parse()The REST chat endpoint applies everything above. The web console applies the default rule. The MCP chat_completion tool applies your key's setting (it does not read the header). Embeddings responses carry x-routed-provider and x-sovereign too, but never the fallback headers: each embedding model is served by a single provider, given by its provider and sovereign fields in GET /api/v1/models.
Routing decides which inference provider processes your prompt. The gateway in front of it runs in Paris on Vercel, a US company, and stores no prompt or completion — details on the privacy page.
Errors
Errors are JSON, OpenAI-style — an error object with a human-readable message and a stable type you can branch on:
{
"error": {
"message": "Insufficient credit balance. Top up your account from the dashboard.",
"type": "insufficient_credit"
}
}| Status | type | Meaning |
|---|---|---|
| 400 | invalid_request | The body is not valid JSON, or a required field is missing (model; input for embeddings). |
| 401 | invalid_api_key | Missing, malformed or revoked API key in the Authorization header. |
| 402 | insufficient_credit | Your prepaid balance is at or below zero. Top up from the dashboard to resume. |
| 404 | model_not_found | The model ID is not in the catalog, or not of the right kind for this endpoint — list valid IDs via GET /api/v1/models. |
| 409 | model_not_live | The model exists but is still coming soon. Pick a live model. |
| 503 | model_paused | The model was live but is temporarily paused (its provider route is cut). The message and GET /api/v1/models?include=all give the reason; it comes back with the same id and price. Pick another model meanwhile. |
| 502 | upstream_error | The provider could not be reached, returned an unreadable response, or refused Frontière AI's own credentials or account — a provider 401/402/403 is never passed through as-is, because it is not about your key. Retry; report it if it persists. |
| 503 | provider_not_configured | No provider credentials for this model on this instance. |
| 503 | no_sovereign_provider | Sovereign-only routing applies (header or key) but the model has no sovereign provider — it is a fast-access model. Pick a model labeled EU sovereign. |
Provider-side errors (rate limits, overloaded model, invalid parameter for that provider) are relayed with their upstream status code and body — what you would get calling the provider directly. If the model has another eligible route, a 429 or 5xx first triggers a failover (see Data routing); only the last route's error reaches you, with its body, and with Retry-After when the provider sends one. Deterministic refusals that retrying cannot fix — 409 model_not_live, 503 model_paused, 503 provider_not_configured and 503 no_sovereign_provider — carry x-should-retry: false, so the official OpenAI SDKs stop instead of retrying them with backoff.
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. Prices are VAT-inclusive, so the amount charged is the amount credited — nothing is added at checkout. No subscription, no card on file, no end-of-month bill.
New calls are refused with 402 as soon as the balance is at or below zero. Calls already running at that moment — or fired at the same instant — are still billed in full once the provider reports their usage, so the balance can dip slightly below zero; that amount is deducted from your next top-up. Nothing is ever charged to a card automatically.
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.
Invoices for your top-ups are issued on request — the dashboard does not generate them. Write to contact@fleeceai.agency with the date and amount of the top-up, adding your company name and VAT number if the invoice is for a business (FLEECE AI SASU, intra-EU VAT number FR45932329188).
Reasoning models
Reasoning models such as glm-5.2 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 https://getfrontiereai.eu/api/v1/embeddings \
-H "Authorization: Bearer $FRONTIERE_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bge-multilingual-gemma2",
"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.
| Model | Dimensions | Context |
|---|---|---|
bge-multilingual-gemma2 | 3584 | 8192 |
qwen3-embedding-8b | 4096 | 40960 |
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.
Images
POST /api/v1/images/generations turns a prompt into images, with the same key and the same prepaid credit as chat. The body follows OpenAI's: model, prompt, n (1 to 5) and size. The images come back as JPEG in data[].b64_json; nothing is hosted or kept on our side, so response_format: "url" returns a data URL rather than a link. The official OpenAI SDKs work unchanged (client.images.generate).
curl https://getfrontiereai.eu/api/v1/images/generations \
-H "Authorization: Bearer $FRONTIERE_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-schnell",
"prompt": "A lighthouse at dusk, watercolor",
"size": "1024x1024"
}'POST /api/v1/images/edits serves PhotoMaker V2: send 1 to 4 face photos (JPEG or PNG) as image[] in multipart, or as base64 data URLs in a JSON images array, plus a prompt with the trigger word img right after the subject — "a woman img as an astronaut". A face photo is personal data: send only photos you are allowed to process. Both models are served by Infomaniak in its own datacenters in Switzerland, outside the EU but under an EU adequacy decision.
| Model | Endpoint | Sizes | Price per second |
|---|---|---|---|
flux-schnell | /images/generations | 1024x1024, 1792x1024, 1024x1792 | €0.0092 |
photomaker-v2 | /images/edits | 1024x1024, 1792x1024, 1024x1792 | €0.0092 |
Image generation is billed per second of generation, measured by the gateway around the provider call and rounded up to the next second — the way our provider bills us. The response's usage.generation_seconds is the exact amount billed. As a guide, measured on 7 October 2026: about 2 seconds for a 1024×1024 FLUX image, 3 seconds in 1792×1024, 5 to 6 seconds for a PhotoMaker portrait. A request refused before the call (wrong size, missing trigger word…) costs nothing.
MCP server
Frontière AI exposes a Model Context Protocol (MCP) endpoint that gives AI agents (Claude Code, Codex, Cursor, Cline, 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, balance and web tools require one. chat_completion follows your key's data-sensitivity setting (see Data routing).
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.
https://getfrontiereai.eu/api/mcpTransport: POST with application/json — JSON-RPC 2.0, stateless (no SSE, no sessions).
Available tools
| Tool | Description |
|---|---|
list_models | List all models with optional filters: filter (live/coming-soon/sovereign), provider, kind (chat/embedding), includeComingSoon |
get_model | Get detailed info for a single model by slug: pricing, vendor, license, parameters, sovereignty, compliance data |
search_models | Search models by keyword across slug, name, vendor, provider, and modality |
chat_completion | Run inference on any live model, following your key's data-sensitivity setting. Supports temperature, max_tokens, tool calling. Usage billed per token (same pricing as the REST API) |
create_embedding | Generate text embeddings for RAG/semantic search. Supports string or array input. Usage billed per token |
check_balance | Check current prepaid credit balance in EUR (no parameters needed) |
web_search | Live web search (Linkup, offices in Paris and New York) returning up to 8 results with the full page text of each — needs a positive balance; each successful search is billed €0.00756, VAT included |
web_fetch | Read one web page as clean markdown (Linkup, offices in Paris and New York) — follow up on a search result URL. Needs a positive balance; each successful page read is billed €0.001512, VAT included |
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. Anthropic-format clients such as Claude Code call POST /api/v1/messages with the base URL https://getfrontiereai.eu/api — same models, same routing, same billing:
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, with the same default routing and 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, never on our servers.
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?
New calls return HTTP 402 (insufficient_credit) as soon as the balance is at or below zero. Calls already in progress at that moment are still billed and can take the balance slightly below zero; the difference is deducted from your next top-up. 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 run by US companies are always labeled fast access, never sovereign. By default a sovereign model only uses sovereign providers, fallbacks included, and every chat and embeddings response names its provider in the x-routed-provider and x-sovereign headers.
How do I keep a key on EU sovereign providers only?
Set the key to “Sovereign only” in your dashboard (API keys → Data sensitivity), or send the X-Data-Sensitivity: sensitive header. Calls to a fast-access model then fail with 503 no_sovereign_provider instead of reaching a US company, and the header cannot loosen a key set that way.
Why did my reply come back empty?
You most likely called a reasoning model (glm-5.2, for instance) 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