No test environment yet
Version 1.0a has no sandbox and no test keys. Every key reads a real team, and everything it returns has livemode: true. The API is read-only, so no request can change data in Totem: testing is safe as long as you treat what you read as real personal data.
Where to test
Start with a team that holds only fictitious data, and use real data only when you are ready to go live.
- A dedicated team with fictitious data. Use a separate Totem team containing only fictitious contacts, then create an integration for that team. Its key is still a live key, and the team needs what a production team needs: an organization whose plan includes the API, a completed legal setup, a business sector that is not sensitive, and an administrator to create the integration (Quickstart lists them). The API is read-only, so you create the test data in Totem itself: add a few leads by hand with fictitious names, phone numbers and email addresses from the ranges below, then call, write to or book with the test team yourself to produce calls, conversations and bookings.
- Your own team. You can also build against your team's real data with your own key. Keep that data on systems your contracts cover, and delete test copies when you finish.
Example data
The integrator kit ships with the API's description and with example objects:
openapi.jsondescribes every endpoint and field;fixtures.jsonholds example objects of every kind, all withlivemode: false.
Load the example data in your unit tests before you call the API. The examples in these docs and in the kit use fictitious contacts only:
- phone numbers from
+1 202-555-0100to+1 202-555-0199; - email addresses at the
example.comdomain.
Use the same ranges in your own test data, so that no test can ever reach a real person.
What to test before you go live
Run each check against your own code, with the example data or with a test team. Keep a copy in sync explains the behavior each one proves.
Applying the feed
- Idempotency. Apply the same feed page twice: nothing may change the second time.
- Older versions. Deliver an item with a lower
versionthan the one you hold: it must be ignored. - Crash recovery. Stop your sync after saving a page and before saving its cursor, then start it again: the replayed page must change nothing.
- Removals. A removal must delete the record and, for a lead, its attribution, response and activities. Then deliver an older version of the same record: it must stay deleted.
- Full resync. Throw your cursor away and run the full resync: records missing from the new copy must disappear.
- Unknown values. An enum value or an error code you do not know must not stop the sync.
Errors and limits
- A team that is not ready. With a key that reads two teams, make one answer
409 capture_not_ready: the other must keep syncing in the same run, and the first must keep its cursor. - Teams that come and go.
404 team_not_accessiblemust delete the team's data only onceGET /v1/teamsconfirms the team is gone. A403must keep the data and the cursor. - Rate limit. A
429 rate_limitedmust wait forRetry-Afterand then continue with the same cursor. - Daily quota. A
429 quota_exceededmust stop the sync until 00:00 UTC and resume then with the same cursor. Make sure the waiting process cannot overlap the next scheduled run.
Contacts
- Contact permissions. A lead with
contact_permissions.do_not_contact: truemust not be contacted by any system you feed. - Unknown consent. A lead with
whatsapp_consent: nullmust not receive WhatsApp messages as if it had agreed.
Rehearse a key rotation
Roll a key once before you depend on it, so the first real rotation is routine:
- In Settings → Developers, choose Roll key and keep the previous key working for 1 hour.
- Deploy the new key to your server, the way you will in production.
- Check that your sync keeps running on the new key.
- Once that hour has passed, check that the old key answers
401 key_expired, and that nothing in your systems still uses it.
Authentication explains rolling and revoking.
Checking availability
GET /v1/health tells you whether the API is up. It needs no key and returns no data, so use it for uptime checks. Check it with GET: the firewall in front of the API answers HEAD with a plain 404. Call it with no query string: any parameter, even a cache-buster, gets 400 invalid_request. Its Totem-Release response header names the release that answered; quote it when you report an incident. To check a key, call GET /v1/me.