sphoroVOICEdocs
Markdown

Get an API key

Your key is how Sphoro Voice knows a request is yours. You create it in the portal, you see it exactly once, and it carries a role that fixes what it is allowed to do.

Step 1 · Sign in to the portal

Open the portal on this deployment and sign in. Keys are created there and nowhere else — there is no API call that mints your first key, because it would need a key to authenticate.

If you have no login yet, ask whoever set up your organisation's account to invite you. The invitation arrives by email and is good for one sign-up.

Step 2 · Open API keys

In the left-hand navigation, choose API keys, then Create an API key.

Step 3 · Fill in the four fields

Every one of them matters later, and only the role cannot be changed afterwards.

FieldWhat to put
NameWhere the key will live, not what it is for — orders-api-production, zapier, sameer-laptop. In six months this name is the only thing telling you what breaks if you revoke it.
Rolemember to follow this site: it creates agents, places calls and registers webhooks. Once you are live, a service that only dials with an agent that already exists should hold a default key instead. See which role to pick.
ExpiresNever for a key your production service holds. A date for anything temporary — a trial integration, a contractor, a one-off migration.
TagsOptional and free-form: an environment, a ticket number, a customer. They grant nothing at all and exist for whoever has to work out, a year from now, whether this key is still in use.

Step 4 · Copy the key — this is the only time you will see it

The key appears once, on the screen that created it. We store only a SHA-256 hash of it, so nobody can recover it afterwards: not you, not your account owner, not our support. If it is lost, the only remedy is to revoke it and create another.

Shown once, on that screen
vsk_4f3c9a17b2e84d05c6b1f7a930e2d84c5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d

Every key on this platform begins vsk_, so a secret scanner can be taught to recognise one, and so a key pasted into the wrong field is obvious at a glance.

Step 5 · Store it as an environment variable

Put it in your service's secret store — the same place your database password lives. The rest of these docs assume it is in SPHORO_API_KEY, so every command on every page can be pasted as it stands.

Shell
export SPHORO_API_KEY=vsk_...
Never put a key in anything a browser or a phone downloads. Front-end JavaScript, a mobile app bundle, a public repository — anything shipped to a device is readable by whoever has that device, and a key that places calls is a key that can spend your balance. Calls are placed by your server; the browser talks to your server, and your server talks to us.

Which role to pick

A role is a fixed set of permissions, chosen when the key is created and not editable afterwards — to change it, create a new key and revoke the old one. Pick the least that does the job: this is the single choice that decides how much damage a leaked key can do.

RoleCan doUse it for
defaultweakestagents:read calls:read calls:write tts:writeA production service that only dials, using an agent that already exists. It can place and end calls and read them back, and can see nothing about the account behind them. It cannot create an agent, so it cannot follow step 3.
memberpick this oneagents:read agents:write analytics:read calls:read calls:write knowledge:read knowledge:write tts:writeEverything on this site: creating agents, placing calls, registering webhook endpoints. The right role for the key you are creating now.
adminagents:create agents:read agents:write analytics:read billing:read calls:read calls:write keys:read knowledge:read knowledge:write tts:writeA key that also reads the account: other keys, usage and plan.
owneragents:create agents:read agents:write analytics:read billing:read billing:write calls:read calls:write keys:read keys:write knowledge:read knowledge:write tts:writeAlmost never. It can mint further keys, so a leaked owner key is indistinguishable from a leaked password.

Each role contains the one before it, and a key can never be given a role stronger than the person creating it holds — an admin cannot mint an owner key. That is what stops the key screen being a way around every other permission on the account.

A request that reaches an endpoint its role does not cover is refused with 403 and permission_denied, and the message names the permission that was missing rather than leaving you to guess:

Response403 Forbidden
{
  "status": 403,
  "code": "permission_denied",
  "detail": "this credential does not carry the agents:write scope"
}

Full list of what each permission covers, and every other error, in step 2.

Using more than one key

Use a separate key per place a key lives — production, staging, each third-party tool. It costs nothing, and it is the difference between revoking one integration and taking down every integration you have at once.

SituationWhat to do
A key leakedRevoke it in the portal — it stops working immediately, mid-request. Then create a replacement and deploy it.
Routine rotationCreate the new key first, deploy it, confirm traffic is flowing, then revoke the old one. Both work at once, so there is no gap.
Someone leftRevoke the keys tagged or named for them. This is what the name and tag fields were for.
A key expiredExpired and revoked are different states and are reported separately, but both stop working. Create a new one — an expiry cannot be extended.

Revoking keeps the row, deliberately: months later the question is which key leaked, and a list with the revoked ones missing cannot answer it. Once a key is revoked or expired the portal offers a second, separate Delete — for tidying a list full of one-off keys, and not for a key that was involved in an incident. It is refused on a key that still works, so deleting is never how a key gets stopped. Whatever happens to the row, the audit log keeps that the key existed, who deleted it and when.

Give short-lived work short-lived keys. A key issued for a two-week migration and set to expire in two weeks stops working whether or not anybody remembers it exists — which is the only kind of cleanup that reliably happens.

Check it before you move on

  • The key is in a secret store or an environment variable, not in your source code.
  • It has the weakest role that does the job — member to work through this site, default for a service that only dials.
  • Its name says where it lives, so you know what breaks if you revoke it.
  • No browser, mobile app or public repository has a copy.

Step 2 makes the first request with it and confirms it works.