sphoroVOICEdocs
Markdown

Security and data

What Sphoro Voice holds, what separates your account from anybody else's, how long each kind of thing is kept, and what is never stored at all.

What isolates one account from another

Every request carries a credential, and the credential — not a parameter in the request — decides which account's data it can reach. There is no request shape that reaches across accounts, which is why an id from another account reads as "not found" rather than "forbidden": the object is not merely refused, it is not visible.

Agents, calls, transcripts, recordings, analyticsScoped to the account the key belongs to.
Knowledge basesHeld in a separate service, under a credential minted for your account alone. A fault in this platform cannot reach another account's documents, because the credential it holds cannot.
ProjectsNot an isolation boundary. A cost label inside one account. See projects.

You can see that for yourself: ask for an object that is not yours and the answer is 404, not 403.

Shell
# What this key can actually do.
curl -s https://voice.sphoro.com/v1/agents \
  -H "Authorization: Bearer $SPHORO_API_KEY"

# An id from somewhere else: not found, rather than forbidden.
curl -s -o /dev/null -w '%{http_code}\n' https://voice.sphoro.com/v1/agents/agt_000000000000000 \
  -H "Authorization: Bearer $SPHORO_API_KEY"

Credentials

CredentialLivesBelongs
API keyUntil you revoke it, or its expiryOn your server, in a secret store. Never in a page, an app bundle, or a repository.
Call tokenMinutes, scoped to one callIn a browser. This is the only credential that should ever reach one.
Webhook signing secretUntil rotatedOn your server, used to verify what we send you.
A key in a browser is a key in the hands of every visitor. Anyone can read it out of the page and place calls on your account until you notice. The whole purpose of POST /v1/realtime/tokens is to make shipping a key unnecessary — see talk from a browser.

Keys carry scopes, and the right key for a job is the narrowest one that does it: a dashboard that reads calls does not need to be able to create agents. See get an API key.

In transit

  • Every API request is HTTPS. There is no plaintext endpoint.
  • Webhook endpoints must be https — an http URL is refused, because delivering a call transcript over it would put a conversation on the wire in the clear.
  • Every request the platform makes on your behalf — a knowledge-base crawl, a journey's API node, a webhook delivery — goes through a guard that validates the resolved address immediately before connecting. A URL you supply is input, and it does not get to name a private address.

What is kept, and for how long

DataKept
Call records — times, numbers, direction, end reason, costFor the life of the account.
TranscriptsWith the call record.
Summaries and extractionsWith the call record.
Audio recordingsOnly if record_calls is on, and then for the retention window agreed with your account.
Knowledge-base documentsUntil you delete them.
Suppression list and consent recordsIndefinitely — deleting a do-not-call entry is not a thing you want to happen automatically.
API keysStored hashed. The key itself is shown once, at creation, and cannot be retrieved afterwards.

Retention is set per account rather than per agent, because it is a policy rather than a setting. Tell us what your obligations are and it is configured to them.

What is never stored

  • Audio, unless you asked for it. With record_calls off, the audio of a call passes through and is not written down. The transcript is, because transcription is how the agent hears the caller at all.
  • The audio of a bridged call, ever. On a webrtc agent the media runs directly between the two clients and does not reach this deployment. See the realtime protocol.
  • Anything on a simple agent's call. A person holds that call from their browser; no recogniser, model or synthesiser is opened for it, and there is no transcript because nothing on this side heard it.
  • Your API key in readable form.

Where calls are processed

Your account runs in one region, and the speech and language vendors behind it are part of that picture — a model call leaves the platform even when the call does not leave the region. If data residency is a requirement rather than a preference, two things are worth knowing:

  • The model chain speaks the OpenAI wire format, and several presets are self-hosted runtimes. A deployment that must keep transcripts inside its own network can point the model at one. See vendors.
  • Dedicated and in-region deployments are available. Talk to us before you build, not after.
Recording is a legal decision before it is a technical one. Most jurisdictions require the caller to be told and several require consent. Put the notice in the greeting. This is also why an agent group can never switch recording on for the members it already has — it must be adopted per line, by somebody who knows the consent position for that line.

Outbound calling has its own rules, and they are enforced rather than documented: the suppression list, consent records, and calling hours in the timezone the number actually belongs to. See compliance.

If something goes wrong

If you believe a credential has leaked, revoke it in the portal first and tell us second — revocation is immediate and does not need us. If you have found a vulnerability, get in touch before disclosing it anywhere else.