Provider keys and pricing
Provider keys, any OpenAI-compatible provider, and pricing per call, per 1,000 tokens or per job unit.
Provider keys
The AI page holds one key per provider, per environment. Paste it, make a test call, and it is set. A key is 8 to 512 printable characters. Replace it by pasting again. A job provider's key is pasted like a chat key; its test call is one authenticated read that spends nothing.
The key is write-only. No response, no audit record and no page shows more than its last
four characters. The AI page shows the last four characters of a key of 16 or more characters
(a shorter key shows dots) and the last call. A provider that echoes the key in a refusal
reaches the app as ***<hint>.
In Live, removing a key asks for a code from your email first, and your app's AI features stop the moment it is removed.
Optionally, list up to 20 models the app may call; the test call uses the first. Any other
model answers model_not_allowed. The model name is the provider's, 1 to 80
characters of letters, digits, dots, colons, underscores and hyphens. Google needs one;
OpenAI and Anthropic refuse a missing one themselves.
Any OpenAI-compatible provider
Chat runs on a standard, not a list. Besides OpenAI, Anthropic and Google, a chat tool, an
alias or a raw call runs on any server that speaks the OpenAI Chat Completions format, as
provider openai-compatible. On the AI page, add a provider and pick Any
OpenAI-compatible provider, then fill in four things: a name (what you call it), the base
URL from the provider’s docs, the API key, and the models you allow (optional; a tool names its
model either way). One per environment.
| Provider | Base URL |
|---|---|
| OpenRouter | https://openrouter.ai/api/v1 |
| Mistral | https://api.mistral.ai/v1 |
| Groq | https://api.groq.com/openai/v1 |
| DeepSeek | https://api.deepseek.com |
| xAI | https://api.x.ai/v1 |
| Together AI | https://api.together.ai/v1 |
| Fireworks AI | https://api.fireworks.ai/inference/v1 |
Ollama (gemmein dev only) | http://localhost:11434/v1, set as GEMMEIN_AI_URL_OPENAI_COMPATIBLE in the shell; a key is optional there |
Gemmein sends POST <base URL>/chat/completions with
Authorization: Bearer <key> and the standard body (model, messages,
max_tokens from the tool’s output cap, stream) and nothing else, passes the
answer back in the standard’s shape, and meters from its usage field. It checks
the base URL on every call: https only, a host name and never an IP, never a gemmein.com host,
every address it resolves to public, and the connection pinned to the address it checked. It
never follows a redirect. The key is encrypted and write-only, and a new base URL is saved only
with its key pasted again.
{
"label": "Quick answer",
"provider": "openai-compatible",
"model": "meta-llama/llama-3.3-70b-instruct",
"credits": 1,
"promptTemplate": "{{question}}",
"inputs": [{ "name": "question", "type": "text", "required": true }]
}
A tool names one of the endpoint’s own model ids (up to 120 characters; slashes,
:, @ and + allowed), or an alias to one. It reads text only
until it ticks image under accepts; tick it only for a model that reads
images. It takes no audio, video or document inputs.
| If… | What happens | What you do |
|---|---|---|
The base URL is http://, an IP address, a gemmein.com host, or carries a user and password, a ?query or a #fragment | 400 invalid_base_url at save, naming the rule | Give the https:// base URL the provider’s docs show |
| The host resolves to a private, loopback, link-local or cloud-metadata address when a call runs, or the endpoint answers a redirect | 502 endpoint_refused; nothing spent, no connection made, and the AI page’s last error names the rule | Point the base URL at the final, public address |
| The base URL changes without the key pasted again | 400 missing_key; the old address and key stay | Paste the key with the new address |
| The key is wrong, or the endpoint is rate-limited or fails | Its own status and the first 4 KB of its body pass through, the key masked; the credits are refunded | Fix the key, or retry after the wait it names |
The endpoint reports no usage in a stream, or only half of it | A per-token tool costs its ceiling, never less; a per-call tool its price | Price the tool per call, or set bounds.stream: false |
| The environment’s answers pass 50 MB in an hour or 500 MB in a day (Development; Live: 1 GB and 4 GB) | 429 endpoint_budget before anything is spent, until the window opens again | Lower the tools’ output caps; in Live, write to hello@gemmein.com to raise it |
| 5 calls to the endpoint are already open in Development (50 in Live) | 429 endpoint_busy, nothing spent | Retry after a moment |
| One answer runs past 8 MB (32 MB on the three host providers) | It is cut where it stands and costs its ceiling | Lower the tool’s output cap |
| The app goes live | Tools copy as always. The key copies only when your human ticks Use the same key as Development, and then with its base URL and name | Nothing |
Pricing
A tool holds one credit price. For a price that depends on the plan, make two tools, each with its own access requirement. How credits are bought, granted and spent is on Credits.
Per call
call is the default unit. The tool's credits are spent before the request is
forwarded; the default tool spends one. A person short of the price is answered
402 credits_exhausted before anything is sent, with the balance in the
message.
Per 1,000 tokens
With unit: "tokens", per is 1,000 by default. Before the call the
tool reserves a ceiling: the price of the request's bytes ÷ 3 plus the output cap (4,096 when
the tool sets none). When the answer ends cleanly, the call settles at the provider's usage,
up to the ceiling, and what was not used returns. Per-token pricing is for text: a tool that
takes files is priced per call.
The call costs the ceiling when the provider reports no usage, when a stream does not end cleanly, or when the call is abandoned mid-answer. A call abandoned before the provider answered costs the input estimate.
Per job unit
A generate tool meters images, seconds or characters
(or call: one price per run). A transcribe tool meters seconds (or
call). A tool's unit is the one its model meters: an image model per image, a
video or transcription model per second, a speech model per character, or call.
Any other unit is refused when the tool is saved, since a unit nothing meters would charge every person the
ceiling.
A metered job tool reserves credits × ceil(bounds.maxUnits / per) when its run
starts, and settles at what the provider metered when the run succeeds.
Refunds
Credits spent before the request are refunded only when the provider fails before its
first byte, with a non-2xx answer or no answer at all. The response then carries
x-gemmein-credit: refunded. A stream that dies after the first byte is not
refunded, and hanging up early does not refund.
Response headers
Every answer that passed the spend carries x-gemmein-credits-remaining.
x-gemmein-tool names the tool; absent on the implicit default.
Usage & billing
The Usage & billing page counts AI calls for the last 30 days: spent from your people's credits, priced by your provider. Gemmein meters the calls; your provider bills the tokens.
Thanks for telling us.
Thanks for telling us.
Last updated