API referenceGetting started
API keys
An API key lets your code act for your Sogni account. Each account can hold up to 99 keys at a time, each with its own name and usage, so every app, agent, server or worker fleet can have a key of its own. Revoke one and the others keep working.
Manage keys on the API Keys page at
dashboard.sogni.ai/api-keys while signed
in. The older dashboard.sogni.ai/api-key link opens the same page. Only a
signed-in session can create, change, rotate or revoke keys; an API key can
never manage keys, including itself. If you signed in to a password account
with Google or Apple, sign in with your Sogni password to change keys.
#Key types
| Type | Looks like | Use it for |
|---|---|---|
| Developer key | sogni_dev_… |
Your apps, the Sogni SDKs, the REST API and AI agents. It cannot sign in a GPU worker. |
| Worker key | sogni_wkr_… |
GPU workers, such as Sogni Fast Worker. It cannot start paid work. |
| Original key | A UUID, such as 3f1c9a2e-… |
Everything, exactly as before. It works for apps, the SDKs, the REST API and GPU workers. |
Worker keys cannot spend. REST chat, direct tools, chat runs, creative
workflows and personal LoRA imports refuse them with 403; SDK sign-in
closes with 4021. Use a developer key for these operations. Worker keys can
still read some account information, such as balances, so keep them private.
Developer keys cannot sign in a worker. Create a worker key for GPU hosts.
The Original key is the key every account already had. It is listed on the API Keys page as Original key and keeps working everywhere it did before, including in a WebSocket URL. You can rename, rotate or revoke it. You cannot pause it, give it an expiry, restrict its models or IP addresses, or set spending limits on it, because Sogni's hosted chat and workflows use it on your behalf. Unlike new keys, the Original key can be shown and copied again from the API Keys page. When you want restricted access, create a new key instead.
#Create a key
- Sign in at dashboard.sogni.ai/api-keys.
- Create a key. Choose Developer or Worker, give it a name of up to 64 characters, and optionally set an expiry date and allowed IP addresses. Developer keys can also have spending limits and model restrictions.
- Copy the key when it appears. It is shown once, at creation and after each rotation. Sogni cannot show it to you again, so store it in your secret manager or environment configuration straight away.
The 99-key limit includes the Original key, and paused and expired keys count toward it. Revoked keys do not: revoke a key you no longer use to free a slot.
#Send the key
Send the key in a request header, never in a URL:
curl --fail-with-body https://api.sogni.ai/v4/account/balance \
-H "Authorization: Bearer $SOGNI_API_KEY"
REST endpoints accept Authorization: Bearer YOUR_API_KEY or
api-key: YOUR_API_KEY. The Sogni SDKs take the key as apiKey (JavaScript)
or api_key (Python) and send it in a header for you.
URLs end up in browser history, proxy logs and analytics, so keys created on
the API Keys page are refused when they arrive as a WebSocket ?apiKey= URL
parameter, with the reason "Send this API key in the api-key header, not in
the URL". The Original key is still accepted there for existing integrations;
move it to a header when you can.
Keep keys on your server. Never put one in a browser bundle, a mobile app binary, a prompt, a repository, a screenshot or a support message.
#Spending limits
Each developer key can have daily, monthly and lifetime spending
limits, set separately for Spark and SOGNI. Set or change them when you create
the key or later on its page. Leave a limit empty for no limit. A limit of 0
also means no limit; to stop a key from spending, pause it.
| Limit | Resets |
|---|---|
| Daily | 00:00 UTC each day (5 PM PT during daylight time, 4 PM PT during standard time, on the previous date) |
| Monthly | 00:00 UTC on the 1st of each month |
| Lifetime | Never. Raise the limit to keep using the key. |
What counts. Spark limits count work paid with Spark, plus work your
Unlimited plan covers, counted at its Spark
value. SOGNI limits count work paid with SOGNI. A request counts in the token
that actually pays for it: with token_type: "auto", a request that falls back
to SOGNI counts against the SOGNI limits.
How a request is checked. When you submit work, Sogni estimates its cost. If that estimate would take the key past any of its limits for that token, the request is refused before anything is charged. Otherwise the estimate counts against the key straight away, and is corrected to the actual cost when the work finishes. Work that fails or delivers nothing ends up counting nothing. Because estimates count while work is in progress, a burst of requests can be refused before the key's finished spend reaches the limit.
Limits apply to work started with the key: SDK renders and chats, REST chat completions, direct tool execution, chat runs and creative workflows. Interrupted hosted work retains the originating key's restrictions and usage when it resumes. Pausing, expiring or revoking that key prevents it from starting further paid work.
#Model permissions
A developer key can use all models unless you restrict it. Choose Allow only selected models when creating or editing the key, then select the models it needs. You can also enter an exact model ID. An empty selection allows no models.
Permissions apply to the model that will actually run, including models used by hosted tools and later workflow steps. If a workflow needs both an LLM and a video model, allow both. Different model variants have different IDs; allowing one does not allow every model in its family. Newly added models are available only to unrestricted keys until you add their IDs to a restricted key.
These permissions control work requested by a developer key. Worker keys cannot request paid work and do not have a model selector.
#IP allowlists
New keys accept requests from any IP unless you restrict them. Choose
Allow only selected IP addresses and enter your server or worker's public outbound
IP addresses or CIDR ranges, one per line. IPv4 and IPv6 are supported, for
example 203.0.113.10, 203.0.113.0/24, or 2001:db8:1234::/48.
These are documentation examples; replace them with your own addresses.
An empty restricted list allows no addresses.
Use the outbound address Sogni sees, which may belong to your NAT gateway or VPN. Include each address your application uses, including IPv6 where applicable. If it changes, update the allowlist from your signed-in dashboard session. Key restrictions do not prevent you from managing the key there.
Hosted tools and recovered work retain the original request's verified source IP for this check. Moving execution to a Sogni server does not remove the key's restrictions.
#Usage
The API Keys page shows, for each key, what it has spent today, this month and in its lifetime in Spark and SOGNI, a 30-day daily chart, and a per-model breakdown by month. Days and months are UTC. Last used updates at most once a minute. Revoked keys stay listed with their usage history.
Per-key usage and limits are on the dashboard only; an API key cannot read them. For the account's balances and plan usage, see Balances and Usage.
#Pause, expire, rotate, revoke
- Pause and resume. A paused key is refused everywhere until you resume it. Pausing disconnects the SDK sessions and workers signed in with that key.
- Expiry. An expired key can no longer sign in, and connections already open with it cannot start new paid work. A worker that is already connected stays connected until it next reconnects, so replace a worker's key before its expiry date.
- Rotate. Rotation gives the key a new secret and keeps its name, limits and usage. By default the old secret keeps working for 10 minutes, so you can deploy the new one without downtime. Connections already open with the old secret stay connected until they next reconnect. You can instead stop the old secret immediately, which also disconnects those connections and stops further steps in hosted runs started with it.
- Revoke. Revoking is permanent. The key stops working at once, even during a rotation's overlap, and any live SDK sessions and workers using that key are disconnected. Your other keys are not affected.
Rotating or revoking the Original key affects only connections that use the Original key.
If a key is exposed, revoke it, or rotate it and stop the old secret immediately. Put the new key where the old one was used, then check the key's usage on the API Keys page for anything you don't recognize.
#Errors
A refusal caused by the API key carries one of these codes and a plain-English message. Nothing is charged for a refused request.
| Code | Meaning | What to do |
|---|---|---|
| 4200 | The key is paused, expired or revoked. | Check the key on the API Keys page. Retrying will not help. |
| 4201 | The key's permissions or limits could not be checked. | Retry shortly, with backoff. |
| 4202 | The key reached its daily limit. | Wait until 00:00 UTC, raise the limit, or use another key. |
| 4203 | The key reached its monthly limit. | Wait until the 1st of the month (UTC), raise the limit, or use another key. |
| 4204 | The key reached its lifetime limit. | Raise the limit, or use another key. |
| 4205 | The key does not allow the requested model. | Add the model to the key's permissions or use an appropriate key. |
| 4206 | The key does not allow the source IP address. | Update its IP allowlist or send the request from an allowed address. |
Refusals for 4202, 4203 and 4204 also carry a structured apiKeyLimit
object, so an app can show the limit without reading the message:
{
"window": "daily",
"currency": "spark",
"limit": "25",
"used": "24.5",
"requested": "1.2",
"resetAt": 1790899200000
}
| Field | Meaning |
|---|---|
window |
daily, monthly or lifetime. |
currency |
spark or sogni. |
limit, used, requested |
The limit, what the key has used in this window, and the refused request's estimated cost, as plain decimal strings such as "1000" or "24.5". |
resetAt |
When the window resets, in milliseconds since the Unix epoch (UTC). null for a lifetime limit. |
SDK. In the JavaScript SDK, a refused render's project error carries
code (for example 4202) and apiKeyLimit. A refused chat request's error
carries code, with the server's full response, apiKeyLimit included, on
its payload. The codes are exported as API_KEY_ERROR_CODES.
REST chat completions. A limit refusal returns 429; an unavailable
check returns 503. The JSON error object carries message, type,
string code, and apiKeyLimit for a spending-limit refusal.
code is a string. A 429 of type api_key_limit_reached is a spending
limit, not a rate limit: retrying will not succeed until the window resets or
you raise the limit. A key that is paused, expires or is revoked while a
request is being accepted returns 403 with type api_key_unusable and code
4200.
Paused, expired and revoked keys. REST requests made with one return 401
with a message saying which, such as "This API key has expired". An SDK
connection is closed with code 4021 and the same reason.
See Getting Started for how authentication works across the API, and Production Integrations for the other errors to handle.