sphoroVOICEdocs
Markdown

The portal

Every screen of the console, control by control — the agent builder and each of its eight tabs, the queue of calls, what every page shows and what each of its states means. Written for whoever runs the account rather than for whoever writes the code.

Getting in

One screen with several states, each named at the top.

ScreenWhat it asks
Sign inEmail and password.
Create an accountYour name, work email, organisation and a password.
Create the first administratorThe same, on a deployment that has no users yet.
Check your emailA six-digit code sent to the address. It lasts ten minutes and takes five tries; a wrong one says how many tries are left. After signing up, Resend code unlocks after a minute (the button counts down) and sends a fresh code — only the newest works, and an address gets at most five an hour. A code that has expired says that code has expired — request a new one. The sign-in code has no resend: start again to get a new one.
Accept your invitationConfirms the invitation and takes a name and password. A link missing its token says that invitation link is incomplete.
Reset your passwordYour email, then one screen with the six-digit code we emailed, the new password and its confirmation. The code follows the same rules as a signup code, with the same Resend code countdown and Use a different address. Setting it signs you in and ends every other session.

Back to sign in returns from any of them. /invite lands directly on the invitation screen. Password reset has no link to land on: the code is typed into the same screen that asked for it.

An account that belongs to no client yet gets a page saying so rather than an empty console. It tells three situations apart, because only one of them needs you to do anything: a platform operator is meant to be there and has every account in the switcher in front of them; somebody with accounts but none entered can pick one; and somebody with no accounts at all is told plainly that the fix is a row in somebody else's members table, rather than being pointed at a switcher that is empty and disabled.


The shell around every page

The sidebar

Six groups. Which entries appear depends on your role and on what the deployment has switched on.

GroupEntries
AccountOverview
ObserveRequest log, Alerts, Call ratings
BuildDialer, Agents, Ideas, Agent groups, Knowledge, Phone numbers, Campaigns, Journeys, Calls
MoneyProjects, Usage, Billing
AccessTeam, API keys, Webhooks, Audit
PlatformClients, Announcements, Users, Pricing, Integrations, Product feedback — super admin only, and folded away by default

Two old bookmarks still work: /providers and /models both land on Integrations, which is what they were merged into. A dead bookmark reads as the feature having been removed rather than renamed.

The topbar

Names the page, and under it which account that page is about — the question a platform operator with six clients open asks every time they look up.

On a Platform page it reads Platform · every account instead. That is not decoration: you read "Acme Logistics" over a list of eight accounts and cannot tell whether you are about to change one of them or all of them.

On the right, five things that are reachable from everywhere because none of them is a place — they are actions you take while looking at something else:

FeedbackSend product feedback without losing your place.
DocsThe API reference, served by this deployment itself.
ComplianceThe compliance reference.
AlertsWith a count when there is one.
Your accountProfile, theme (light / dark / system), sign out.

The project lens

When an account has more than one project, pages that hold work show a project scope bar: which cost centre the page below is showing, changed in place. The topbar carries a chip saying the same thing, and rows in tables carry a coloured dot and the project's name — never the dot alone, because colour is what makes forty rows scannable and it is also the one channel a reader may not have.

A project that has since been deleted still shows on the row it was recorded on, as Deleted project, rather than vanishing.


The portal is the API

Nothing in the console is a private feature. Every screen here reads and writes the same endpoints your own code can, with the same permissions — the portal signs a person in where an API key authenticates a program, and that is the whole difference.

Which matters in two directions. Anything you can do here you can automate; and anything that looks wrong here can be checked against the API without waiting for a screen to be fixed. The Dialer places exactly this call:

Shell
curl -X POST https://voice.sphoro.com/v1/calls \
  -H "Authorization: Bearer $SPHORO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "agt_...", "to": "+919000000000"}'

Keys are minted on API keys. The full surface is the API reference, and authentication covers the header, the roles and the error codes.


Roles: who sees what

Five roles. Authorization is decided on the server for every request; the portal hides what you cannot use rather than letting you press it and take a refusal.

Role
OperatorPlaces and answers calls, and nothing else. Cannot create or change anything. Gets its own console rather than this one.
MemberBuilds agents and makes calls. Cannot manage access or mint API keys.
AdminManages members, API keys and settings. Cannot delete the account or add owners.
OwnerFull control of this account, including billing, ownership and deleting it.
Super adminOperates the platform. Sees and manages every client account. Held by whoever runs Sphoro Voice — not by a customer.

The Operator role exists because "member" used to be the floor, and a member builds agents: there was no way to give somebody a handset without also giving them the configuration system behind it. A support desk hiring twenty people to take calls had to make twenty people who could each rewrite the agent that takes them.

You can never grant a role above your own, and a role picker only offers what you may actually assign.


Overview

The page the portal opens on: what this account is, what it is doing right now, and who has been in it. Overview and Monitor used to be two pages that opened on the same question and answered half of it each. They are one page now, and an old link to /portal/monitor lands here. Analytics followed for the same reason, and an old link to /portal/analytics lands here too.

The account, in one line: status, plan, members, active API keys and your role. Plan, members and keys link to the page that changes them, when your role can open it.

Right now is refreshed every five seconds, with the age of what you are reading and a Refresh now beside it. If refreshing stops working a warning says so, because a page that has quietly stopped updating looks exactly like a healthy one.

Panel
TilesCalls in progress, calls, errors and API failures. Calls, errors and API failures each open the page with the detail — Calls, Alerts and Request log.
Recent callsThe latest calls, running ones first, each named by the agent that took it. A call still running after twenty minutes is flagged: that is almost never a conversation, and far more often a leg the carrier never tore down.
Pipeline latencyEach stage of the turn — speech-to-text, retrieval, the model, synthesis — in the order a turn runs through them, with p50, p95 and p99. This is the panel that says which stage is slow, which is the only version of "calls feel laggy" anybody can act on.

Each panel says plainly when it has nothing: no calls yet, no latency samples yet. An empty panel is not the same as a healthy one. Right now appears for roles that can read the account's calls.

Over time is what the account's traffic did over a window you choose, and whether it went well. It is loaded when the page opens rather than refreshed, and it leaves out what Right now already shows: the call and error counts and the latency by stage are the same figures, and two copies of one count on one page disagree as soon as a call starts. It appears alongside Right now.

Panel
Time windowLast 24 hours or last 14 days — the span the traffic chart and the talk-time sparkline are drawn over.
TilesTalk time, with the average call, and turns per call.
TrafficCalls, minutes, turns, errors or cost across the window — one at a time, because one plot gets one axis.
How calls endedCompleted, ended early and live now. Ended early is a hang-up, a transfer that did not land, or a failure; the end reason for any one call is on Calls.
Quality signalsTools succeeded and Retrievals found context — the two numbers that say whether an agent's tools and knowledge base are actually load-bearing or merely configured.
Busiest agentsThe eight that answered the most calls, with their errors. The table lists every agent.

Every chart has a table one button away, with the numbers it is drawn from.

Under it, Team — the five members who signed in most recently — and Recent activity, the tail of the audit log. Each links to its full page.

For a super admin it is also the platform's front page, with four counts that are each a link: clients, suspended (nobody in them can sign in), without a member (created, never handed over) and users. Two counts would say how big the platform is; these say what needs doing.


Observe

Request log

Every API request this account made — requests, failed and the failure rate — and, in its own panel, recent failures. The failures panel is separate because a failure buried in a list of successes is a failure nobody finds.

With nothing wrong it says nothing has failed. This is the good outcome rather than showing an empty table you have to interpret.

Alerts

What the platform has raised about this account.

Call ratings

What callers thought, when they were asked.

Scoresaverage out of 5, responses, response rate as a share of completed calls, and promoters — beside what callers said.

On an account that has never collected one, the page explains how ratings arrive rather than showing an empty chart. An empty quality page reads as "nobody complained", which is not what it means.


Build

Dialer

A telephone in the portal: type a number, place a call, and hear it in the browser. On a call replaces the form while one is in flight.

The number is entered in two halves — a country and the national number — because that is what a person actually chooses and types. Pasting +44 20 7946 0958 is handled, so it is not dialled as an Indian number.

Style decides who takes the call:

Style
Agentic — the agent handles itIt talks, looks things up and can call your functions. You listen in.
Simple — I talkYou take the call yourself. Nothing here listens, and there is no transcript.
CustomOne of the agents you have built.

Agent appears only for Custom — it is the one style that cannot work without it, and the other two have nothing to guess. With no agents built yet, it says so and points at Agents.

Use this to hear an agent before pointing a phone number at it.

Agents

The list, with bulk selection: select the agents shown, move to group, delete.

Recently deleted is a folded panel at the bottom with restore and delete for good. It is folded because it is a list of things somebody has already decided against, and absent entirely when it is empty. It is here rather than on a settings screen because the operator who deletes the wrong agent looks for it where the agents are.

Making a new agent

Start a new agent asks the shortest useful question first — who takes these calls? — and then how do you want to start?

Route
Describe the lineWhat does this line do? in a sentence, plus the language and direction, and the platform writes the first version. It then puts it in front of you under the heading "Read it before it answers a telephone" — name, greeting and instructions, all editable — because a generated prompt nobody read is how an agent says something you would not have.
From a templatePick one, name it, and choose the language and any knowledge bases.
BlankName, language, knowledge bases.
New line you answerA person-held line rather than an agent-held one.

Creating an agent hands over to the builder with the "which numbers reach it" dialog already open, because the form that made it no longer asks.

The agent builder

Eight tabs. Arrow keys move between them; on a phone the bar scrolls and the edges are marked when there is more.

Fields you are not allowed to change are locked rather than hidden, so the form is the same form for everybody. Where a value comes from a group it says so, with what it inherited.

On an agent that was built for you, editing a locked field says so in full rather than failing quietly: this agent was set up for you, so its <field> is not yours to change here — and then names what is: you can point numbers at it, choose the caller IDs and the carrier, and decide whether calls are recorded.

1. Agent — what it is and what it says

Field
Name
DescriptionFor your team. Callers never hear it.
ProjectWhich cost centre its calls are attributed to.
GroupWhich agent group it belongs to.
How it takes inputThe agent's mode.
Who holds this conversationAgent-held or person-held.
What it may doIts autonomy.
What it saysThe greeting and the opening lines.
Filler phraseWhat it says while it is thinking, so a pause is not silence.

2. Languages — every language it speaks

One chip per language, the one calls open in marked as the default. Everything below the chips belongs to whichever chip is selected — you pick a language and then configure that language, rather than deciding for every field whether it means the default or one of the others.

Per language:

Field
Language
SynthesizerThe TTS vendor.
Voice
RecognizerThe STT vendor.
Greeting

Plus, for the agent as a whole:

Field
How it speaksSpeed and pitch.
Cached audioFixed lines rendered once instead of on every call — see voice-lines.md.

Which vendors appear in the per-language pickers depends on what the deployment has connected under Integrations. A vendor with no key is not offered.

3. Intelligence — the model and what it knows

Field
Model
Max tokens
Knowledge basesWhich corpora it may retrieve from.

A Voice engine card picks how the agent runs. If it is set to the realtime engine on a deployment with no realtime provider connected, the card says so in the error tone rather than letting you find out on a live call: calls to it will connect and then say nothing.

4. Calling — the telephone line

Field
Rings forHow long before it answers.
Record calls
Transcribe calls

Below the tabs, the line itself:

Field
DirectionAnswers calls, places calls, or both.
Numbers that reach this agent
Caller IDsWhat it shows when it dials out.
Carrier

5. Engine — how it listens, when it gives up, what it keeps

How it listens — the keypad menu:

Field
Keypad menuThe IVR tree.
When nothing matches
When nobody presses
Wait for a keypress
Reminders before hanging up

Conversation:

Field
Words before it stops talkingBarge-in sensitivity.
Extra stop words
Ask if they are still there after
Hang up on a quiet line after
Longest call
When an answering machine picks upAnd the message to leave.

Hang up when the conversation is finished — with when is it finished?, which is the condition it is judged against.

6. Tools — what it can reach mid-call

Tools this agent carries, laid out as a catalogue rather than one form, because the interesting decision is which kind of tool this is and each kind then needs a different half-dozen fields. One form covering all of them would show a calendar timezone to somebody configuring a transfer.

KindWhat it is for
Calendar availabilityRead the open slots before offering a time.
Book appointmentWrite the agreed time into the calendar.
Transfer callHand the caller to a person.
Custom functionAny HTTP endpoint of your own, described to the model as a function.

Every tool has these two, whatever its kind:

Field
Task nameWhat the model calls, and what you will see in transcripts and analytics.
Description (prompt)Say when to use it and when not to. This is the single biggest lever on whether the tool fires at the right moment — it is the whole of what the model has to go on, and a blank one produces an agent that books appointments nobody asked about.
Pre-tool messageSpoken while the tool runs, so the caller hears what is happening rather than silence. Empty uses the agent's own filler phrase.

Calendar tools add:

Field
API key (Cal.com)Generated under Settings → Developer → API keys on cal.com. Encrypted before storage and never shown again.
Event typeWhich bookable thing on that calendar. It carries the length, the availability schedule and the questions asked at booking, so it is most of the configuration.
TimezoneThe caller's zone, not the business's — a time read back to somebody is only right in theirs.

Transfer call adds:

Field
Transfer toFixed here, never chosen by the model: a destination a model could name is a toll-fraud primitive wearing a feature's clothes.
Tell your server before the transferPosted the transfer's details before the call moves, so whatever picks up knows what is arriving. Waited on for three seconds at most — a slow endpoint must not be able to hold a caller.

Custom function adds:

Field
ParametersWhat the model is asked to supply. Everything not listed is fixed, and the schema is closed — a model that invents an argument is corrected rather than having it forwarded to your endpoint.
BodyEmpty sends the parameters as a JSON object. Fill it in for an endpoint whose body is mostly fixed, using {{parameter}} where a value varies; the caller's words are escaped into it.
HeadersTick secret for anything that is a credential. Secret values are encrypted before storage and never shown again.
TimeoutHow long this may run. A caller is waiting on it with nothing but the pre-tool message over the gap.

Paste the command takes a curl and fills the form in from it: method, URL, headers and body are read out, the values in the body become parameters, and anything that looks like a credential is lifted into the sealed half of the headers.

Secrets go out and never come back — a key field shows a hint and stays empty, and an unedited one is not re-sent, which is what makes changing a description possible without retyping a key.

Below the tools, transfer number is the agent-wide fallback. See functions.md.

7. Flow — the steps a call moves through

Field
Use a flowOff, and the agent is a single prompt.
Calls open onThe node a call starts at.
DefinitionThe same flow as JSON, parsed when you leave the box — the escape hatch for anything the visual editor cannot express.

Per node:

Field
Node id, Kind
What this node is forRead by the router as the objective when the node has no prompt.
Instructions for this stepAppended to the agent's prompt while the call is here. {{variables}} captured earlier are filled in.
The lineRead out exactly as written.
Re-prompt after silenceSeconds. 0 leaves it to the agent's own silence settings.
Must call this toolForced until it has run once on this visit.

Per edge:

Field
Go to
WhenThe condition.
Which isWritten as the caller's behaviour: "the caller confirms the amount".
CaptureValues to pull from what they said, as name:type pairs — date:string, amount:number. All of them are required for the edge to fire.
Event nameWhat an outside system posts to /v1/calls/{id}/events to move the call from outside.

Full reference: flows.md.

8. After the call — what is written down once it ends

Field
Summary
Fields to extractEach with a name, a type, and options where the type takes them.
ModelWhich model does the analysis.

Full reference: post-call.md.

Trying it

Three ways, offered according to what the agent is:

Mode
PhoneType a number; it dials.
WebThe call is held in this browser.
ChatText, no audio.

Any {{variables}} the agent expects are asked for first — the panel will not place a call with one missing. On a person-to-person line with no number, the two modes meet in the browser: this tab joins on one URL and whoever answers joins on the other.

Deleting

At the bottom, behind a typed confirmation.

Ideas

An idea is a script several agents share — the instructions, the greeting and the languages, and the voice, knowledge, tools and flow behind them — kept apart from the telephone, so one idea can run an inbound line, an outbound campaign and a web widget.

The list shows each idea as a tile: its greeting (or the start of its instructions), its languages, and the agents used by it, each a link to that agent. Search matches names, greetings, instructions and agent names. An account with no ideas sees the three steps instead.

New idea starts one in either of two ways:

  • Write it — a name, an optional greeting, and the instructions.
  • Copy an agent — copies an agent's instructions, languages, voice, knowledge, tools and flow into a new idea and moves that agent onto it, so nothing it says changes. Agents already on an idea are not offered.

Opening an idea edits its name, description, greeting and instructions — per language, when it speaks more than one. The save bar says how many agents a save reaches, and a refused save lists each field to fix. Used by links every agent on the idea; Also part of this idea summarises the model, knowledge, tools and flow, which are edited on any agent using it (saving there saves to the idea). An idea can be deleted only once no agent uses it.

An agent picks its idea on its Agent tab, under Idea, where the idea's name links back here. See personas.md.

Agent groups

Settings shared across a fleet of agents. Joining a group changes nothing on its own — see agent-groups.md.

New group: a name and a colour, picked from the server's palette so the page cannot offer one a save would refuse.

Inside a group:

Card
What it isName, description, colour.
What it setsThe defaults: model, per-vendor models, temperature, reply length, speaking speed, pitch, what it does besides talk, what it may do, tool rounds per turn (0 uses the default of three — every round is another wait with the caller on the line), knowledge lookup budget in milliseconds (50–2000, or 0 for the default; it is spent inside the turn, with the caller waiting), call recording, call transcription (billed by the minute and by the person), and a webhook URL where the record of every call these agents take is posted.
N of M agents differ from these defaultsEach difference shown the way an operator reads one: field — from → to. Select the ones you want and adopt the group's value.
MembersWith add an agent.
Delete this groupBehind a typed confirmation.

Knowledge

The knowledge bases this account's agents may retrieve from.

Knowledge workspace names where all of this actually lives. Every account has exactly one workspace in the knowledge platform, created with the account and named after it, and its id is this account's id — so a document added on either side is answerable on both with nothing to sync. While the account exists that workspace cannot be deleted or suspended over there; deleting the account releases it. If the panel warns that the knowledge platform does not have the workspace marked as this account's, say so: it means somebody there could remove it, and agents would keep answering and quietly stop citing documents.

New knowledge base creates one. Already in the knowledge platform lists corpora that exist on the knowledge platform but have no row here — almost always somebody who built one over there and came here looking for it. Add adopts it: its documents are already indexed, so agents can use it immediately.

Inside one, add a document:

Field
Where it comes fromText, a web address, or a file.
Title
Text / Web address / File

Plus the Documents list. Full behaviour: knowledge-base.md.

Phone numbers

Field
Connect a numberThe number itself.
CarrierAnswers itself when the deployment has only one — a field with one possible answer is not a question.
DirectionInbound, outbound or both.
Answered byWhich agent. Every agent is offered, not just the current project's: a number in one project may perfectly well be answered by an agent in another, and narrowing the picker would make a legal choice unreachable.
Belongs toA member's name, making it their direct line — or blank for the account's pool. One name, not a set.

Whether this account may bring a number of its own is decided by the same rule that would refuse the save, so the form never offers a control that is going to be turned down.

Campaigns

Run a journey or an agent over a list of contacts.

New campaign:

Field
NameFor your team. Nobody called ever hears it.
Agent
ContactsA file upload, or numbers typed one per line or comma-separated.
When it is readyStart now, or hold it.

The list carries search, bulk selection, and per-campaign add contacts.

A running campaign reports as it goes. Contacts outside the recipient's local calling window are marked as such — they are dialled when it opens, not dropped. Read compliance.md before running one.

Journeys

Multi-step automation across many calls and days: call, branch on the outcome, wait, retry, fall back to a message.

New journey takes a name. Inside, the definition — nodes and edges — on a canvas: click a box to edit it, drag from a box's right edge onto another to connect them, drag the background to pan, scroll to zoom. A This journey panel beside it counts the nodes, names what calls start on, and counts the problems.

A separate panel lists things to fix before publishing, so a draft cannot be published into a state that would fail on a real contact.

Per node, depending on its kind:

Field
DescriptionWhat this step is for. Shown on the contact's timeline.
AgentWhose voice makes this call.
Wait for the call to be analysed
Wait forA duration: 30m, 24h, 72h.
Only resume betweenA window, so a retry does not fire at 3am.
Method, URLHTTPS only. {{variables}} are filled in per contact.
Channel, MessageFor the message fallback. {{variables}} filled in per contact.
WorkflowOne of your post-call workflows.
OutcomeWhat this ending is counted as: converted, unreachable, opted out.
Try this node at mostThe retry ceiling.

Put one contact through takes a single E.164 number — +919000000000 — and runs the journey against it. The field says plainly that this places real calls.

Full reference: journeys.md.

Calls

Every call, with a detail drawer.

Control
SearchNumber, id, agent or summary. Press /.
Outcome chipsWith counts. Chips rather than a dropdown, because the counts are half the answer — "how many needed somebody and got nobody" is read off the row without opening anything. Only outcomes that have actually happened are offered, plus whichever one is selected.
Export CSVThe calls the filters are showing, not the whole table — the button's tooltip says which.
N liveRefreshes every five seconds while a call is in flight.
Updated <when>With the exact time on hover.

The filter controls only appear once there is a first call, so a new account meets a list rather than a toolbar.

Tiles: Calls, Talk time, Answered, Turns, Recorded.

A row marks whether it has a recording and which digits the caller pressed, in order. Opening one gives the transcript, then What was said — the post-call summary and the extracted fields, stamped with when the analysis ran — and the call id with a copy button. That id is the thing to quote in a support ticket.


Money

Projects

Cost centres inside the account: what work is attributed to, with a monthly budget and a decision about what going over does.

Cost centres lists them. Each has a name, a description, a colour — which is what the dot beside a row in every other table is drawn from — and a monthly budget. Each can be edited, and deleted behind its own confirmation.

One row is marked · default: the project everything unfiled is attributed to. It has no Delete button and cannot be archived, because a control that only ever refuses is worse than no control. Make default on any other row hands it the marker, which is also how the current default is freed to be deleted — nothing is re-attributed, and the old project keeps everything it has already cost.

Work that names no project shows as Unassigned rather than being hidden. See projects.md.

Usage

Panel
Call volumeCalls over time.
Where the tokens went
Where the minutes went
Latency by stage
Quality signalsTool calls, retrievals and turns per call.
Against your <plan> planWhat is used against what is included.

Each panel names its own empty state — no calls in this window yet is a different statement from no calls recorded yet, and the page keeps them apart.

Billing

At the top, the balance as arithmetic: what was granted, what has been spent, and tokens remaining — with that last figure also expressed as ≈ N minutes and about N days, since a token count is not something anybody can plan around.

Panel
What the pending charge is made ofOnly when the account is billed on more than conversation time. Every driver, with what was used, the rate and the tokens.
What you are chargedPer minutemetered by the second, not rounded up. Token price per 1,000. Plan fee per month, or by contract. Monthly grant, as tokens and as minutes. Billed in — the currency. Last settled.
Usage against your planGauges over the stated window.
LedgerEvery movement. An account where nothing has moved says so.
Add tokensA pack, or a specific number of tokens, with a reference — e.g. Invoice 1042.
Have a plan code?PLAN-XXXX-XXXX-XXXX-XXXX. Redeeming one is how a plan changes; ask for a code is how you get one.

The page recommends a plan when it should, and says which of two reasons it is: the account has outgrown this plan and the exceeded limits are in red, or at this volume another plan would simply cost less. Those are different arguments and it does not blur them.

Owner only.

The controls a super admin also sees

Four more cards appear on this page for whoever operates the platform.

Card
Adjust tokensGrant or claw back tokens outside a purchase — goodwill after an outage, a correction, a migration balance. Positive adds, negative removes, and a reason is required. This is not a top-up: the ledger keeps the two apart so "did we ever charge for this?" stays answerable.
Billing currencyWhat this account pays when it buys tokens. Balances are market-neutral, so this changes the price of a pack and nothing else. Locked once credit has moved — changing it then would reinterpret what every past purchase cost.
Set the planApplies immediately, settling the meter at the current rate first. The only route to a custom tier, which cannot be issued as a code.
Plan codesMint a code for a plan, valid for a period, with a note. Use this to let the customer pick the moment instead of switching them yourself.

Access

Team

Invite someone — an address and a role. Invite a team takes several at once. An address that already had an account is added straight away and says already had an account — added, rather than sending an invitation nobody needs.

Project access decides which cost centres one member may reach: every project, or only these. An owner or admin reaches every project by role, so on their rows the control is said rather than simply not offered — a missing control reads as a bug. An account with no projects yet says so instead of offering an empty picker.

What the roles mean sits under the table: each role with the sentence describing it, so the picker is not a question you cannot answer.

API keys

Create an API key:

Field
NameWhat will use it — production-api.
ExpiryEither days until the key expires or a date, whichever way you think about it.
TagsFree labels — staging — for finding a key later.

The secret is shown once, on a panel that says so. Revoke from the list. An account with none says no keys yet.

On a platform login with no account selected the page says choose a client account first, because a key belongs to an account and there is nothing to mint one against. See authentication.md.

Webhooks

A name (Zendesk ticket sync), an endpoint (https://example.com/webhooks/voiceai), and which events it wants — everything, or only these. Creating one shows a signing secret, once.

Deliveries lists what was sent and what came back, which is where a webhook that "never fires" is actually diagnosed. Deleting one asks first.

As with keys, a platform login with no account selected says choose a client account first. See webhooks.md.

Audit

Who did what.

Filtered three ways: free text, and by area — the prefix of the action, client, user, key — which is the only grouping the log has and the one people read it by: what did we do to accounts this week. A super admin also gets a platform-wide scope.


Platform

Super admin only. The server refuses these to everyone else regardless of what the browser renders.

Clients

Every client account.

Create a client takes a name and a plan. The list filters by name, slug or plan, and marks:

  • suspended — nobody in these accounts can sign in.
  • no owner — nobody can sign in to this account; invite an owner.

Inside one: Settings, Plan, Activity, its members and its API keys, and a danger zone with a permanent delete behind a typed confirmation. An account nobody has been added to says nobody has access to this client yet, and one with no keys says no keys — both of which are states worth seeing rather than blank space.

Creating an invitation from here reports invitation created.

Announcements

What the portal says to customers.

Field
Where it appears
MessageOne line. It shares a row with the link on a phone.
More, if it needs it
ToneEach with what it is for, so a palette is not picked by hue.
ColourThe tone's colour, or one of your own as hex.
Icon
Link
Can they close it?
RunsA first and last day. Blank first day means as soon as it is published.
Who sees itIncluding plans, drawn from the billing catalogue so it cannot name a tier that does not exist.

Bump the revision shows it again to people who had closed it.

Users

Every person on the platform, across every account.

Create a user makes one directly, rather than by invitation. Filter by email or name.

Each row marks whether they are a super admin — full access to every client account — or reach only the accounts they are a member of, and whether they cannot sign in.

Row actions: disable — signs them out everywhere and blocks the next sign-in, reversible — and grant super admin.

Pricing

What a token costs, and what a plan costs.

Field
Monthly fee — INR / — USDPer plan, in both currencies, because accounts are billed in one or the other.
Monthly token grantWhat the fee includes.
Pack price — INR / — USD
Tokens per pack
Rates — tokens per unitWhat each metered thing costs in tokens.
IncludedWhat the plan carries without metering.

Reset to shipped pricing puts the defaults back. Only a platform administrator can see this page at all — the note on it says so.

Integrations

Every external service this deployment can reach, on one page, in the order a deployment is set up — because the call has to reach you first:

Telephony · LLM · TTS · STT · Knowledge · Notifications

One card per vendor, connected or not, with its models on it, and a filter box over them. A vendor with no credentials reads not connected; a deployment that can reach nothing at all says nothing can be connected yet.

Nobody types a model in. Which models a vendor publishes is a fact about the vendor rather than a preference, so connecting one offers everything this build knows it serves, and disconnecting takes it back out. There is no half-filled state in between.

Connected means in service. A vendor with the credentials it needs serves calls; removing the key is how you take it out. A row disabled by the old switch shows as paused with the one button that fixes it, rather than being quietly dropped from the chain forever.

What this page decides is which vendors are reachable and which of their models are on offer. Which model actually answers is decided on the agent, every time — no card here carries a fallback, because the words a caller hears must not change when a super admin edits a credential on a page the person who built the agent has never opened.

Product feedback

What customers have sent, via the topbar's Feedback button.


Your account

Card
Your detailsIncluding platform access: either super admin — every client, or client-scoped.
Your accessEvery client account you belong to, with your role in each.
Change passwordCurrent password, then a new one of at least 12 characters, confirmed. Changing it signs out every other session you have open — which is the point of doing it when you think one is compromised.
ThemeLight, dark or system — in the topbar's account menu.

The operator console

A separate site for the Operator role: a telephone on a screen, and specifically the telephone everybody already owns.

Sign in, type a number, press call, talk; when somebody rings, pick up. That is the whole application. There is no agent, no prompt, no model, no voice, no knowledge base, no group, no campaign and no settings page — not because they are hidden from the role, but because a person whose whole working day is this screen should not have to look past a keypad to find the keypad.

The layout is a mobile dialer's on purpose: a number at the top, a 4×3 grid of round keys with the letters under the digits, a round green call button, and a tab bar switching between the keypad and the calls you have had. A call takes the whole screen, as it does on a phone.

* and # are on the pad because a keypad without them is not a keypad anybody recognises. They are live only where they mean something — on a call, navigating somebody else's phone menu — and on the dial screen they say why they are not, rather than sitting there dead.

Everything it can ask for is re-authorized on the server against the session cookie, and the operator role refuses every write in the product.


When something looks wrong

What you seeWhat it means
A section is missing from the sidebarYour role does not carry it. See Roles.
A field in the agent builder is lockedIt is set by the agent's group, or your role may not change it. The form says which.
A vendor is missing from the voice or model pickerIt is not connected under Integrations. A vendor with no key is not offered, so a picker that lost a vendor means a credential was removed.
An agent fails on its first live call with a vendor errorThe model it names is from a vendor that is no longer connected. Integrations shows which cards are in service.
Calls feel laggyOverviewPipeline latency says which stage. "Slow" without a stage is not actionable.
A webhook "never fires"WebhooksDeliveries shows what was sent and what came back.
Campaign contacts are not being dialledThey are outside the recipient's local calling window and are marked as such — they go when it opens. See compliance.md.
A journey will not publishThe things to fix before publishing panel lists exactly what.
A flow edge never firesEvery value in its Capture list is required. One missing value holds the call at the node.
An account exists but nobody can sign inIt has no members — the invitation was never accepted. Clients marks these; invite an owner.
An API key stopped workingIt expired or was revoked, or the account was suspended. API keys shows the first two.
Ingestion is not configured on this deployment on KnowledgeNo knowledge provider is connected, so documents cannot be added. Existing bases still work. Integrations → Knowledge.
Telephony is not configured on this deployment on Phone numbersNo carrier is connected. Integrations → Telephony.
No connect a number form on Phone numbersThis account may not bring its own — its numbers were bought on our carrier accounts and handed over, so the way to get another is to ask. The page says so rather than leaving the form absent.

Quote the call id — copyable from any call — and the account name in a support ticket. Your deployment serves its own support page at /docs/support, which names the two identifiers that let us find your call in seconds.