Authentication
The widget API uses project API keys. A project API key:
- starts with
vois_pk_ - belongs to one project
- is sent in the
X-API-Keyheader
Workflow webhooks do not use API keys. The secret is part of the webhook URL. See Workflow webhooks.
Create a key
You can create a key in two places in the console.
From a website channel (recommended for embeds)
- Sign in at app.voisx.ai and open your project.
- Go to Channels and open your voice widget or form channel.
- In the Widget API key card, enter the site that will use the key under Allowed domains, for example
https://www.example.com. You can leave it blank to allow any domain. - Select Generate key.
- Copy the key. The embed snippets on the page already include it.
A key created here can read the widget config, start sessions and run tools. It only works with the agent the channel uses.
From the API keys page
- Sign in at app.voisx.ai and open your project.
- Go to Settings › API keys. You can also generate a key for any project from Organization › API keys.
- Select Generate key.
- Copy the key. You can also download it as a text file.
A key created here can read the widget config and the project context, and send session events. It cannot start sessions or run tools. To start sessions, use a key from a website channel.
The console shows the full key only once, right after you create it. After that you only see the first characters. Store the key somewhere safe before you close the page.
Send the key
Send the key in the X-API-Key header on every request.
- cURL
- Node.js
- Python
curl https://in.api.voisx.ai/widget/v1/config \
-H "X-API-Key: $VOISX_API_KEY"
const res = await fetch("https://in.api.voisx.ai/widget/v1/config", {
headers: { "X-API-Key": process.env.VOISX_API_KEY },
});
const config = await res.json();
import os
import requests
res = requests.get(
"https://in.api.voisx.ai/widget/v1/config",
headers={"X-API-Key": os.environ["VOISX_API_KEY"]},
)
config = res.json()
A missing header returns 422. A key that is unknown, revoked, missing a permission, or used from a domain it is not allowed on returns 401 with:
{ "detail": "Invalid API key or origin" }
Permissions
Each key carries a set of permissions. Each endpoint needs one of them.
| Permission | Lets the key call |
|---|---|
widget:read | GET /widget/v1/config, GET /widget/v1/context, POST /widget/v1/analytics |
widget:session | POST /widget/v1/session, GET /widget/v1/elevenlabs-convai/signed-url |
widget:tools | POST /widget/v1/tools/execute |
Keys created from a website channel, or with Get widget code on the project's Settings › Widget page, have all three. Keys created from the API keys page have widget:read only.
Domain restrictions
When a key is restricted to a domain, the API checks the Origin header of each request. Browsers send this header for you.
| Restriction | Allows |
|---|---|
https://www.example.com | Exactly that origin |
*.example.com | example.com and any subdomain of it |
| No restriction | Any origin, and requests with no Origin header |
A restricted key rejects any request that has no Origin header. Server-side code, such as the cURL, Node.js and Python examples in this reference, does not send one. To call the API from your server, use a key without a domain restriction and keep it out of your web pages.
If your widget works in the console but returns 401 on your site, the domain restriction is the first thing to check. The origin must match exactly, including https:// and any port.
Restrict every key that is used in a web page to your own domains. The key is visible to anyone who views the page source.
Agent restrictions
A key created from a channel only works with that channel's agent. Using it with another agent returns 403:
{ "detail": "Agent is not allowed for this API key" }
An agent from a different project returns 403 with "Agent is not part of this project".
Rate limits
Each key has its own limits. Keys created in the console allow:
| Window | Requests |
|---|---|
| Per minute | 60 |
| Per day (UTC) | 10,000 |
Every request to config, sessions, tools and session events counts, from all visitors that use the key. Going over a limit returns 429:
{
"detail": {
"message": "Rate limit exceeded",
"minute_count": 61,
"day_count": 412,
"minute_limit": 60,
"day_limit": 10000
}
}
Wait for the next minute, or the next UTC day if day_count has reached day_limit, before you retry. If you need higher limits, contact us.
Revoke a key
- Go to Settings › API keys in your project.
- Select Revoke next to the key.
- Confirm.
Revoking takes effect immediately. Any site or app that uses the key stops working, so put a new key in place first.
Replace a key
On a website channel, select Regenerate key in the Widget API key card. You get a new key, and the embed snippets on the page update to use it. Copy the new snippet to your site.
You also need to regenerate the key to change its domain restriction.