Authentication
One API key, sent whole in the Authorization header. There is no OAuth flow, no token exchange and no expiry to refresh.
The header
Send the key exactly as issued. There is no Bearer prefix and no other scheme name: the value of the header is the key itself.
curl "https://api.neurall.io/v3/pricing" \
-H "Authorization: $NEURALL_KEY"Anything else, including a missing header, a mistyped key or a key that has been deleted, answers 401 Unauthorized.
What a key is
Keys are created in the app at Settings › Project › API keys. The secret half is shown once, at creation, and never again: we store a hash, so a lost key is replaced rather than recovered.
The project is not a label on the key, it is what the key is. Every call it makes reads and writes that project’s generations, files and voice clones, and nothing outside it. Separating staging from production, or one customer’s work from another’s, means separate projects with their own keys.
- Scoped to a project
- The generations, uploads and voice clones a key can see are the ones in its project.
- Billed to the organization
- Spend does not follow the project. Every project in an organization draws on the same prepaid balance, so a runaway loop in staging spends production’s money.
- No expiry
- A key is valid until you delete it. Nothing rotates on its own, which is why the section below exists.
Server-side only
A key carries the ability to spend the organization’s balance, so it belongs on a server you control, in an environment variable or a secret manager. Never in a mobile app, a browser bundle, a repository or a client-side fetch: shipping it there publishes it, whatever the bundler does to the string.
Front ends should call your own backend, which holds the key, applies whatever per-user limit you want and forwards the call. That is also where you decide what an individual user is allowed to spend, which is not something the key itself can express.
If a key leaks
Rotating without downtime
A project can hold more than one key at a time, which is the whole rotation mechanism. Both old and new work until you delete the old one, so there is no window where a running deployment is unauthenticated.
- Create the second key at Settings › Project › API keys.
- Roll it out to your servers and wait until nothing is using the old one.
- Delete the old key.
In-flight generations are unaffected by any of this. A generation belongs to the project, not to the key that submitted it, so deleting a key does not cancel or orphan work it started, and the new key can poll for results the old one asked for.
The webhook secret is a different credential
If you use webhookUrl, deliveries arrive signed with a per-project webhook secret (whsec_…), readable on the same API keys page. It is not interchangeable with an API key and points the other way: an API key proves you to us, the webhook secret proves us to you.
Rotating it keeps the previous secret co-signing for 24 hours, so deliveries carry two signatures and your servers can be updated at their own pace. How a generation works has the verification recipe.