This page is for whoever reviews the security of an integration, on the customer's side or on yours. It sums up how Totem protects keys and data, and what to do with the personal data you copy. Authentication has the details of each control.
Keys
- A key is a long random secret. It starts with
tsk_live_, then a lookup id, then about 256 bits of random secret and a checksum. The checksum lets Totem refuse a mistyped key before looking it up. - Totem never stores the key itself. It keeps a one-way digest of the secret, computed with HMAC-SHA-256 and a separate secret that is kept outside Totem's database, so a copy of the database is not enough to use a key. Totem shows the key once, when it is created, and its logs name a key by its lookup id, never by its secret.
- Keys do not expire. A key works until you roll it or revoke it. Roll keys on a schedule that suits you, for example every 90 days, and whenever someone who had access leaves; Testing and go-live shows how to rehearse it.
- Keys are managed only in Settings. Creating, rolling and revoking keys happen in Settings → Developers, never through the API. Creating or rolling a key, adding a team and changing the IP allowlist ask the administrator to sign in again if they have not done so recently, and the administrators who manage the integration, and those of every team it covers, are told about every change, in Totem and by email.
- Revoking is fast. A revoked key stops working within 5 seconds, and revoking never needs a new sign-in, so it can be done at once during an incident.
- Access is read-only and scoped to teams. No key can create or change anything in Totem. A key reads only the teams of its integration, with administrator-level access to them, including channels and records marked Private, so give an integration only the teams it needs.
- A key can be bound to your servers. An IP allowlist limits a key to the IPv4 addresses you list.
- Guessing is throttled. Repeated failed attempts lock out the address or the key for a while, as Failed attempts explains.
Activity records
For each key, Settings → Developers shows Last used: when the key last made a request, and the /24 network the request came from. It can lag by up to 10 minutes.
Each integration's Recent activity shows its most recent changes, such as its creation, each key roll or revocation, and each change to its teams, its IP allowlist or its name, with the date and who made it. Totem keeps each of these entries for 365 days.
Totem also counts each key's requests per day and endpoint, and keeps those counts for 90 days.
Where the API runs
- Region. The API runs on Google Cloud in the
europe-west1region, in Belgium, and reads Totem's database, which is stored in the European Union. - Encryption in transit.
api.totemstudio.aianswers only on port 443, over HTTPS with TLS 1.2 or later. There is no plain-HTTP listener, so a key never travels unencrypted, and the API's own responses carryStrict-Transport-SecurityandX-Content-Type-Options: nosniff. - No caching. No CDN or shared cache sits in front of the API, and every response from the API itself carries
Cache-Control: no-store. - No browsers. The API sends no CORS headers and refuses a secret key sent with an
Originheader (400 secret_key_in_browser), so a key pasted into a web page fails at once instead of working quietly. - A firewall in front. A firewall filters requests before they reach the API, as Errors describes.
Personal data you receive
The API returns personal data: leads' names, email addresses, phone numbers, company and tags, where each lead came from (UTM values and ad, campaign and form names) and its activities, team members' display names, and the metadata of calls, conversations and bookings. It never returns message text, call transcripts or recordings. Once you copy this data, protecting it is up to you and the customer whose data it is. We recommend that you:
- Use the data only for what the customer asked. If you build the integration for a Totem customer, use what it returns only for that customer's purposes.
- Protect your copy. Store it encrypted, limit who can read it, and keep records out of logs, error reports and support requests. Print ids, not whole records.
- Apply removals as soon as they arrive. Delete the record from your copy and from every system you fed from it, and keep only its tombstone. Removals explains, and How do I honor erasure requests? covers erasures.
- Apply contact permissions first, before any of your systems contacts a person, as Contact permissions first explains.
- Send opt-outs back. The API is read-only, so Totem cannot learn about an opt-out recorded in your systems. When a person opts out there, make sure it is also recorded on the lead in Totem.
- Treat text fields as untrusted input, as Conventions explains.
- Delete what you no longer receive. When an integration is revoked or a team leaves it, Totem can no longer send you removals for that data: delete your copy, unless the customer asks you to keep it and has its own reason to. While access is refused, for example because the customer's plan no longer includes the API, no removals arrive either: if that lasts longer than your retention policy allows, delete your copy.
Report a vulnerability
If you find a security problem in the API, in these docs or in the TypeScript SDK, write privately to hello@totemstudio.ai. Say what you found and how to reproduce it with fictitious data, and include request ids when you have them. Never include a live key or real customer data, and do not report it in a public issue. If one of your keys leaked, follow If a key leaks first.