Skip to content

Security

Every read is filtered by the company on the access token. The company comes from the token claim, never from a request parameter, so there is no input that widens the scope of a credential.

Resources are addressed by opaque, prefixed identifiers (mtg_, call_, usr_, tpl_) that are allocated per company. Internal sequential ids are never exposed, so record volume cannot be inferred and ids cannot be enumerated.

An identifier your company does not own returns 404, never 403 — the API does not confirm that a resource exists elsewhere.

A record belongs to the default company of the user who owns it, evaluated at query time rather than frozen when the record was created.

The consequence is worth stating plainly: if a user’s default company changes, their historical records move with them. A rep who moves between companies in the same group takes their meeting history to the new company’s API.

This is a deliberate trade-off of not denormalising ownership onto the record. If that behaviour does not fit your data agreement, raise it with your Salesbud contact before building on it.

transcriptions.read is a distinct scope from meetings.read and calls.read, and a credential can hold the collection scopes without it. A transcript is the most sensitive payload the API serves — verbatim customer speech — so access to the metadata of a meeting does not imply access to what was said in it.

The gate composes rather than replacing the collection scope: a transcript request is checked against both, so a credential limited to calls cannot reach a meeting transcript by holding transcriptions.read.

Transcript text is sanitised before it leaves the service.

Every business read is recorded: which credential, which company, which route, which resource ids, and the calling identity.

The audit write is fail closed. If the trail cannot be written, the read is not returned — you get 503 AUDIT_UNAVAILABLE instead. A successful response therefore means the access was recorded.

  • Secrets are stored only as HMAC-SHA256 hashes with a service-side pepper. They cannot be read back, only rotated.
  • Rotation keeps the previous secret valid for seven days so you can deploy without downtime; revoke it once the new one is live.
  • On a suspected leak, revoke the client — that invalidates issued tokens immediately. Rotation does not, because the old secret stays valid.
  • Set an IP allowlist when your integration runs from fixed addresses. It is enforced at token issuance and on every request, so a leaked token is useless from elsewhere.

Stack traces, source paths, internal ids, tokens, secrets and request bodies are never returned in a response, and never written to logs.