Authentication
The NuTalk API authenticates every request with an API key sent as a Bearer token. Each key belongs to one workspace and can do only what its scopes allow.
API keys
Keys are created per workspace and can be limited to the exact resources an integration needs: agents, channels, contacts, contact lists, calls, conversations, campaigns, conversions, goals, competencies, webhooks, clinic setup, business scheduling, the agenda, automated testing and knowledge. The same key works with the REST API and the MCP server. You can create several keys for different applications or environments.
Key format
sk_…- A workspace key:
sk_<8-hex-prefix>_<48-hex-secret>, such assk_51e4f2a9_…. The dashboard shows the 8-character prefix, so you can tell your keys apart. rk_…- A reseller key: it reaches a reseller's client workspaces, one client per request. See Reseller API and MCP.
Create a key
Open Settings → API keys
In the dashboard, open Settings in the sidebar and choose the API Keys tab.
Name it
Click Create key and name it after the app or assistant that will use it, for example “Production app” or “Development”.
Choose what it can reach
Set each resource to None, Read or Write (write includes read), and give only what the integration needs. You can change it later with Edit access.
Review its safety settings
Deletes and changes wait for approval unless an owner or admin turns that off. You can also let AI assistants make changes over MCP, set an expiry date and limit the IP addresses it works from.
Copy the key
NuTalk shows it once: store it somewhere safe. If you lose it, roll the key to get a new one.
A key can do everything its scopes allow in your workspace. Never commit keys to version control, put them in client-side code, or share them publicly.
Send the key
Send the key in the Authorization header as a Bearer token: Authorization: Bearer sk_….
curl https://www.nutalk.ai/v1/agents \ -H "Authorization: Bearer $NUTALK_API_KEY"
/v1/auth/verifyVerify an API key
Confirms the key and returns its workspace and granted scopes. Any valid key may call it, including a verify-only key with no scopes. Use it before running an integration, and read api_key.scopes to know what the key can do.
any valid keyVerify requests count against a rate-limit bucket of their own (1,000 per hour, 100 per minute), separate from the other endpoints.
Plus the errors every request can return (401, 403, 429, 500): Errors.
curl https://www.nutalk.ai/v1/auth/verify \ -H "Authorization: Bearer $NUTALK_API_KEY"
{
"success": true,
"data": {
"authenticated": true,
"api_key": {
"id": "7b7a0ce4-0000-4000-8000-000000000001",
"name": "Production backend",
"prefix": "51e4f2a9",
"scopes": [
"agents:read",
"calls:read",
"calls:write"
]
},
"workspace": {
"id": "d3b85d84-ef8f-4c4a-8d18-3fa23e7fd48a",
"name": "Acme",
"slug": "acme",
"status": "active"
},
"verified_at": "2026-10-02T02:19:49.549Z"
}
}Who can manage keys
| Action | Who |
|---|---|
| See, create, edit and revoke keys | Owners, admins and builders |
| Give a key more access or looser limits | Its creator, owners and admins |
| Give a key the conversations scopes (it then reads every conversation) | Owners and admins |
| Give a key the scope that reads calls (it then reads every call) | Owners and admins, and builders who see every call themselves |
| Give a key the conversions scopes, while Conversions is on for the workspace | Owners and admins |
| Let AI assistants set up the workspace over MCP | Owners, admins and builders |
| Let AI assistants reach customers over MCP (messages, campaign starts, putting an agent live, bookings) | Owners and admins |
| Turn off a key's approval before deletes or changes | Owners and admins |
| Use a key | Anyone who holds it: treat it like a password |
A key reaches every record its scopes name, whatever the access of the person who created it: a key with calls:read reads every call, its transcript and its recording. That is why a person can give a key a scope like that only when they see all of it themselves. Give each integration its own key with the fewest scopes, and revoke it when the integration is retired.
Scopes
Every endpoint checks a resource scope before it runs. Use read scopes for list and get requests, and write scopes for create, update, delete, or action requests.
| Resource | Read | Write |
|---|---|---|
| Clinic setup | clinic_setup:read | clinic_setup:write |
| Business scheduling setup | business_setup:read | business_setup:write |
| Agenda | appointments:read | appointments:write |
| Agents | agents:read | agents:write |
| Channels | channels:read | channels:write |
| Phone numbers | phone_numbers:read | phone_numbers:write |
| Contacts, Contact imports | contacts:read | contacts:write |
| Contact lists | contact_lists:read | contact_lists:write |
| Calls | calls:read | calls:write |
| Conversations | conversations:read | conversations:write |
| Campaigns, Campaigns | campaigns:read | campaigns:write |
| Conversions, Conversions | conversions:read | conversions:write |
| Goals | goals:read | goals:write |
| Competencies | competencies:read | competencies:write |
| Automated testing | testing:read | testing:write |
| Knowledge | knowledge:read | knowledge:write |
| Billing and usage | billing_usage:read | |
| Webhooks | webhooks:read | webhooks:write |
A key made with an earlier version of Settings can also hold clinic:write: it only changes an appointment's doctor, and Settings no longer offers it.
Some requests need more than their own scope:
contacts:writealso defines custom fields and adds numbers to the exclusion list.- A contact import needs
contacts:writeand the write scope of where it lands:campaigns:writeinto a campaign;contact_lists:writeinto a list, pluscampaigns:writewhen that list feeds an outbound campaign. - Adding or removing the members of a list that feeds a campaign also needs
campaigns:write: it enrolls or removes people. So does deleting a list linked to a campaign. - Conversation events on a webhook need
conversations:readas well aswebhooks:write: to register an endpoint for them, to add them to one, and to change the URL of, or switch back on, an endpoint that receives them. - Call events on a webhook, and
*which includes them, needcalls:readas well: they carry each call's numbers and outcome. So does changing the campaigns of an endpoint that receives them, since those decide whose calls it gets. calls:writeplaces calls, which spend credits, and ends calls in progress.campaigns:writestarts campaigns, which call every enrolled contact.- Trying a held WhatsApp account's templates again needs
campaigns:writeas well aschannels:write: it starts again the campaigns the hold paused, which send to customers. agents:writealso archives an agent, which takes it off its channels.- Clinic setup, business scheduling, the agenda, automated testing, knowledge and channel setup act as the workspace member who created the key, with at most an admin's role: a key never does more there than that person can. If that person changes role or leaves the workspace, the key stops working and answers
401; create a new key.
A valid key can always call /v1/auth/verify. The verify response includes the key's granted scopes so your integration can confirm permissions before running. A key created with no scopes (Verify only) can call nothing else.
Expiry dates and allowed addresses
In Settings → API keys you can give a key an expiry date and a list of the IP addresses it may be used from (single IPv4 or IPv6 addresses, or CIDR ranges such as 198.51.100.0/24). Both apply to the REST API and to MCP.
- After its expiry date a key answers
401withapi_key_expired. - From an address that is not on its list, a key answers
403withip_not_allowed, and the attempt is recorded in the workspace's audit log.
Approvals
A key's deletes and changes can wait for an owner's or admin's approval: Deletes wait for approval and Changes wait for approval are on for every new key, and only owners and admins can turn them off. Such a call answers 202 with a change request instead of running, and runs once approved in Settings → API keys. Reading, creating and stopping something never wait. See Approvals.
Keep keys safe
Store keys in environment variables, never in code:
# .env file (never commit this!) NUTALK_API_KEY=YOUR_NUTALK_API_KEY
- Use a separate key for each environment (development, staging and production) and each integration, so a leaked key reaches less and revoking one breaks nothing else.
- Change secrets from time to time: Roll key… gives a key a new secret, and the old one keeps working until the time you choose. An expiry date limits how long a key works at all.
- Call the API from your server only. Never use a key in client-side JavaScript.
Revoke a key
If a key may have leaked, or you no longer need it, revoke it:
Open Settings → API keys
Choose Revoke… in the key's menu
Or Revoke key… in its details.
Confirm with Revoke
A key also stops working for good when the person who created it changes role (a promotion included) or leaves the workspace. The workspace's owners and admins are told which keys stopped; create a new key for each integration that used one.
A revoked key is refused from its next request: every API and MCP request with it answers 401 with invalid_api_key.
Authentication errors
When authentication fails, the API returns one of these errors:
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing or invalid Authorization header. |
| 401 | invalid_api_key | The API key is invalid or has been revoked. |
| 401 | api_key_expired | The API key is past its expiry date. |
| 403 | ip_not_allowed | The request comes from an address the key does not allow. |
| 403 | forbidden | The API key is missing the required resource scope. |
| 429 | rate_limited | Too many requests: slow down. |
{
"success": false,
"error": {
"code": "unauthorized",
"message": "Missing or invalid Authorization header. Expected: Bearer sk_xxxxxxxx_xxx"
}
}API requests are subject to rate limits. See Rate limits for the limits and how to stay within them.