Documentation

Start using Soloniq.

Soloniq is one OpenAI-compatible API for open-weight models, served from servers in the EU. Prompts and replies are never stored. If your code already talks to the OpenAI API, you change the base URL, the key and the model name — nothing else.

Quickstart

  1. Get a key. Sign in at app.soloniq.com, open Keys and create a key. It starts with sq_live_ and is shown once — store it as a server secret.
  2. Add credit under Credits & invoices — by PayPal (plus a 2.5% fee) or bank transfer, from €30. Soloniq is prepaid in euros; you get an invoice for every payment.
  3. Send a request:
curl https://api.soloniq.com/v1/chat/completions \
  -H "Authorization: Bearer $SOLONIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "soloniq/agent",
    "max_tokens": 2000,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
Base URLhttps://api.soloniq.com/v1
AuthenticationAuthorization: Bearer sq_live_…
EndpointsPOST /v1/chat/completions, GET /v1/models

SDKs and tools

Any OpenAI-compatible client works. Set the base URL and key; use a Soloniq model name.

Python

import os
from openai import OpenAI

client = OpenAI(base_url="https://api.soloniq.com/v1", api_key=os.environ["SOLONIQ_API_KEY"])
reply = client.chat.completions.create(
    model="soloniq/agent",
    max_tokens=2000,
    messages=[{"role": "user", "content": "Summarise GDPR in one sentence."}],
)
print(reply.choices[0].message.content)

JavaScript / TypeScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.soloniq.com/v1", apiKey: process.env.SOLONIQ_API_KEY });
const reply = await client.chat.completions.create({
  model: "soloniq/agent",
  max_tokens: 2000,
  messages: [{ role: "user", content: "Summarise GDPR in one sentence." }],
});
console.log(reply.choices[0].message.content);

Agent frameworks and other tools

Most tools read the standard environment variables:

OPENAI_BASE_URL=https://api.soloniq.com/v1
OPENAI_API_KEY=sq_live_…
MODEL=soloniq/agent            # main model
AUX_MODEL=soloniq/agent-fast   # summaries, compression, routine steps

In LiteLLM, add Soloniq as an OpenAI-compatible provider:

model_list:
  - model_name: agent
    litellm_params:
      model: openai/soloniq/agent
      api_base: https://api.soloniq.com/v1
      api_key: os.environ/SOLONIQ_API_KEY

Soloniq Code: coding in the terminal

Soloniq Code sets up OpenCode, an open-source coding agent for the terminal (MIT licence), to use Soloniq models. It reads your project, edits files and runs commands like other AI coding assistants. Your code is processed only on servers in the EU and never stored.

Install

curl -fsSL https://soloniq.com/code.sh | sh

Linux and macOS; on Windows, run it inside WSL. The script installs OpenCode if needed, asks for your Soloniq key, checks it, and writes a configuration with the models your key may use. You can read the script first: soloniq.com/code.sh.

Use

cd my-project
soloniq                                  # start
soloniq run "Add tests for utils.py"     # one task, no interface
soloniq --key                            # use another key
soloniq --uninstall                      # remove Soloniq Code (OpenCode stays)

Other coding tools

Coding tools that let you add an OpenAI-compatible provider work with the base URL https://api.soloniq.com/v1, your key and a model name. Turn off the tool's own telemetry and sharing features, so your code goes only to Soloniq.

Models and prices

Ten models from DeepSeek, Z.ai (GLM), Moonshot AI (Kimi), Alibaba (Qwen) and MiniMax — prices, context length, image support and fallbacks for each are on the Models & pricing page. GET /v1/models lists the models your key may use. For agents, start with these names:

ModelWhat it isInputCached inputOutput
soloniq/agentRecommended default for agents — reasoning and tool calls0.200.050.50
soloniq/agent-fastSame model with light reasoning — summaries, routine steps0.200.050.50
soloniq/agent-proThe stronger tier — harder tasks, long agent runs (today GLM-5.3)1.750.444.50

EUR per million tokens, excluding VAT.

Aliases and fallback. agent, agent-fast and agent-pro are names, not models: they point at the best model for the job today, so you never have to change your configuration when we upgrade. If the default model fails or is slow, the request is answered by the backup model automatically. You pay the price of the model that actually answered — the model field of every reply tells you which one. Every other model has its own fallback too, listed on the price page.

You can write model names with or without the prefix: agent and soloniq/agent are the same.

Streaming

Set "stream": true to receive server-sent events in the standard OpenAI format. To get token counts at the end of the stream, add "stream_options": {"include_usage": true}.

Tool calling

Standard OpenAI tools and tool_choice. Tool calls come back in choices[0].message.tool_calls; send results back as role: "tool" messages.

"tools": [{
  "type": "function",
  "function": {
    "name": "book_table",
    "parameters": {"type": "object",
      "properties": {"date": {"type": "string"}, "people": {"type": "integer"}},
      "required": ["date", "people"]}
  }
}]

Images

Send images as image_url content parts (a URL or a data:image/png;base64,… URI). Requests with an image go to a model in the chain that can see it, billed at its price; the price page shows which models take images. If no model in the chain can, you get 400 vision_not_supported.

Reasoning

soloniq/agent thinks before it answers. The thinking text is returned in message.reasoning_content (don't show it to end users) and counted as output tokens (usage.completion_tokens_details.reasoning_tokens).

Prompt caching

Caching is automatic. When a request starts with the same text as a recent one — a fixed system prompt, the same tool list, the conversation so far — those tokens are billed at the much lower cached-input price. Agents resend their context constantly, so keep the beginning of your prompts stable. Cached tokens are reported in usage.prompt_tokens_details.cached_tokens — you pay the cached price only for tokens reported there. Cache hits are likely but not guaranteed for every request.

Keys and budgets

Limits

Every key has a requests-per-minute limit. New accounts also have a daily spending cap and a maximum number of keys; we raise them as your account builds history. You can see your current limits under Credits & invoices — or ask us for more at info@zana.ai.

Errors

Errors use the OpenAI shape: {"error": {"message", "type", "code"}}.

StatusCodeMeaning — what to do
400invalid_requestCheck the parameters and message format.
400context_length_exceededThe input is longer than the model's context window.
401invalid_api_keyMissing, wrong or revoked key.
402budget_exceededThe key used its monthly budget. Raise it in the console. Don't retry.
402daily_budget_exceededThe key used its daily budget (type budget_exceeded). It resets at midnight UTC. Don't retry.
402balance_emptyYour prepaid balance is used up. Add credit. Don't retry.
403key_blocked / model_not_allowedThe key is blocked, or may not use this model.
404model_not_foundUnknown model name — see Models.
429rate_limited / token_rate_limited / daily_limitToo many requests or tokens this minute (type rate_limited), or the account's daily cap. Retry after a short wait; the daily cap resets at midnight UTC.
503model_unavailableDefault and backup were both unavailable. Retry with backoff.

Every reply carries an x-request-id header — include it when you contact us.

Privacy

Partner API

For partners who resell Soloniq inside their own product: create one key per customer, set its budget, and read usage — your customers never need a Soloniq account. Create a partner key (sq_partner_…) in the console under Invoices & webhooks; partner accounts are set up by us — get in touch.

Base URL https://api.soloniq.com/partner/v1, header Authorization: Bearer sq_partner_…, amounts in EUR.

CallBody / queryReturns
POST /keysname, customer_ref, models, monthly_budget_eur; optional daily_budget_eur, rate_limit_rpm, rate_limit_tpmthe key (key, shown once) and its id
GET /keysoptional customer_refyour customer keys with spend this month (filtered by your reference)
GET /keys/{id}—budgets, spent this month and today, remaining, limits, status, last use
PATCH /keys/{id}any of name, customer_ref, models, monthly_budget_eur, daily_budget_eur, rate_limit_rpm, rate_limit_tpm, blocked + reason; null removes a daily budget or token limitthe updated key
POST /keys/{id}/creditamount_eurraises this month's budget
POST /keys/{id}/rotate—a new key; the old one works 10 more minutes
DELETE /keys/{id}—the key stops working
GET /summary—number of keys, total spend this month
GET /usagefrom, to (YYYY-MM-DD), optional key_idper key, per day, per model: requests, input, cached, output tokens, errors, fallbacks, cost
curl -X POST https://api.soloniq.com/partner/v1/keys \
  -H "Authorization: Bearer $SOLONIQ_PARTNER_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Customer 1042", "customer_ref": "cust-1042",
       "models": ["agent", "agent-fast"], "monthly_budget_eur": 25, "rate_limit_rpm": 60}'

Monthly budgets run per calendar month, daily budgets per calendar day (both UTC). rate_limit_tpm counts input + output tokens per minute — the limit that fits agents, whose cost depends on context size more than on the number of requests. Partners are invoiced monthly for all their customers' usage.

Webhooks

Set a webhook address in the console. Events: usage.daily (yesterday's usage per key, after 02:00 UTC), key.b80 and key.b100 (budget at 80% / used up), key.blocked. Each call is a JSON POST — {"id", "event", "created_at", "data"} — signed with your webhook secret. Answer with any 2xx status within 10 seconds; otherwise we retry up to three times with the same id, so ignore an id you have already processed. When one request takes a key past both thresholds, you receive key.b80 and key.b100.

X-Soloniq-Event: key.b80
X-Soloniq-Timestamp: 1792057830
X-Soloniq-Signature: sha256=<hex HMAC-SHA256 of "timestamp.body" with your secret>
// Node.js — verify a webhook
import { createHmac, timingSafeEqual } from "node:crypto";
const expected = "sha256=" + createHmac("sha256", process.env.SOLONIQ_WEBHOOK_SECRET)
  .update(`${req.headers["x-soloniq-timestamp"]}.${rawBody}`).digest("hex");
const ok = timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-soloniq-signature"]));

Reject calls whose timestamp is more than five minutes old.

Questions? info@zana.ai