API quick start
The 360 API lets your own systems read agents and calls, publish changes and start outbound calls. Each request carries an API key. A key belongs to one organisation and can only reach that organisation’s data.
You need a workspace role of Admin or Owner to create API keys. Other roles don’t see API keys in Settings.
What you need from 360 and the app
Section titled “What you need from 360 and the app”Besides a key, every request needs the API address and your organisation ID, and most need an agent ID. Here is where to get each one today:
| You need | Where to get it |
|---|---|
| API address | Ask your 360 contact. The app doesn’t show it. Don’t use the address you open the app on: it only accepts people signed in through a browser, and answers an API key with 401 “Not signed in”. |
| Organisation ID | Ask your 360 contact. The app doesn’t show it. The name after /o/ in the app’s address bar is your organisation’s short name, not its ID. If an Admin has already set up an event webhook, every event carries the ID in orgId: click Send test and read it from the request. |
| Agent ID | Open the agent in the app. The last 8 characters of its ID are next to its name at the top: click them to copy the whole ID. The ID is also in the browser’s address bar, after /agents/. With a key, GET /agents lists every agent’s id. |
This page writes them as https://<your-360-host>/v1, <org-id> and <agent-id>.
Create a key
Section titled “Create a key”-
Open Settings → API keys and click Create key.
-
Enter a Name that says which system uses the key, for example CRM sync.
-
Under Permissions, tick what the key may do. Read is ticked to start with. See what each permission allows.
-
Choose when it Expires: Never, 30 days, 90 days or 1 year. The default is 90 days.
-
If your system always calls from the same addresses, enter them under Allowed IP addresses, one per line, for example
203.0.113.7or198.51.100.0/24. Leave it empty to allow any address. -
Click Create key.
-
Click Copy, store the key where your system keeps its secrets, then click Done.
The key looks like vb_live_ followed by 40 letters and digits. 360 stores only a hash of it.
What each permission allows
Section titled “What each permission allows”| Permission | The app says | What the key can do |
|---|---|---|
| Read | Agents, versions, calls and analytics | Read agents, drafts and versions, calls, transcripts, recordings, post-call analysis, analytics, alerts and knowledge bases. |
| Write | Edit and publish agents | Create agents, save drafts, publish, put a version live, roll back, and manage knowledge bases. It can read agents, but not calls. |
| Calls | Start outbound calls | Start outbound calls. |
Tick more than one for a key that needs both. A system that starts calls and then fetches the transcript needs Calls and Read.
No key can manage members, phone numbers, webhooks, API keys, provider keys, billing or organisation settings, and no key can run tests. Do those in the app. The API reference lists every endpoint a key can use.
Make your first request
Section titled “Make your first request”Every request goes to an address under your organisation:
https://<your-360-host>/v1/orgs/<org-id>/...Send the key in the Authorization header:
Authorization: Bearer vb_live_xxxx…This request lists your agents. It needs a key with Read or Write. Keep the key in an environment variable, never in your code:
export VB_API_KEY="vb_live_xxxx…"
curl "https://<your-360-host>/v1/orgs/<org-id>/agents?limit=10" \ -H "Authorization: Bearer $VB_API_KEY"// Node.js 18 or laterconst res = await fetch("https://<your-360-host>/v1/orgs/<org-id>/agents?limit=10", { headers: { Authorization: `Bearer ${process.env.VB_API_KEY}` },})const body = await res.json()if (!res.ok) throw new Error(`${body.status} ${body.code}: ${body.detail ?? body.title}`)
for (const agent of body.items) console.log(agent.id, agent.name)import osimport requests
res = requests.get( "https://<your-360-host>/v1/orgs/<org-id>/agents", params={"limit": 10}, headers={"Authorization": f"Bearer {os.environ['VB_API_KEY']}"}, timeout=30,)body = res.json()if not res.ok: raise RuntimeError(f"{body['status']} {body['code']}: {body.get('detail') or body['title']}")
for agent in body["items"]: print(agent["id"], agent["name"])The answer is a page of agents:
{ "items": [ { "id": "3f9d2c4e-…", "name": "Acme India support", "agentType": "single_prompt", "language": "en-IN", "tags": [], "hasUnpublishedChanges": false, "latestVersionNumber": 3, "environments": { "staging": { "versionId": "…", "versionNumber": 3, "deployedAt": "2026-10-20T09:14:02+00:00" }, "production": { "versionId": "…", "versionNumber": 2, "deployedAt": "2026-10-12T11:30:45+00:00" } }, "createdAt": "2026-10-01T06:02:11+00:00", "updatedAt": "2026-10-20T09:14:02+00:00" } ], "nextCursor": null}The API calls the test line staging and the live line production. When nextCursor isn’t
null, send it as cursor to get the next page.
Each agent’s id is the agent ID you use in other requests, such as starting an outbound call.
If something goes wrong
Section titled “If something goes wrong”Errors come back as JSON with a code you can check in your code:
{ "type": "about:blank", "code": "unauthenticated", "title": "Unauthenticated", "status": 401, "detail": "Invalid, expired or revoked API key."}| Status | code |
What to do |
|---|---|---|
| 401 | unauthenticated |
Check the Authorization header. The key may be wrong, expired or revoked. |
| 403 | forbidden |
The key doesn’t have the permission this request needs, or the request came from an address that isn’t in Allowed IP addresses. |
| 404 | not_found |
Check the IDs in the address. A wrong organisation ID also answers 404. |
| 429 | rate_limited |
The key made more than 120 requests in a minute. Wait for retryAfterSeconds, then try again. |
All codes are in Error messages.
Rotate or revoke a key
Section titled “Rotate or revoke a key”On Settings → API keys, each key shows whether it’s Active, Expired or Revoked, its permissions, and when it was last used.
- Rotate gives you a new key with the same permissions. The current key stops working straight away, so update your system as soon as you’ve copied the new one.
- Revoke stops the key for good. Requests that use it fail with 401 from then on.
An organisation can have up to 50 keys that aren’t revoked. Give each system its own key, with only the permissions it needs, so you can revoke one without stopping the others.