Overview
Start here to find out what your key can read.
GET /v1/menames the integration behind your key, the last four characters of the key, the teams it reads and its scopes. Call it first to check that a key works.GET /v1/teamslists every team the key reads, with its name, time zone and default country, in one response. It includes teams that are restricted for now.GET /v1/teams/{id}returns one of them.GET /v1/memberslists a team's members, by display name only, in one response. Totem exports no email address, phone number or role for a member.GET /v1/healthtells you whether the API is up. It is the only endpoint that needs no key.
A team is a workspace in Totem, with its own boards, members, leads and bookings. A key reads one team or several teams of the same organization. GET /v1/me and GET /v1/teams describe the key and never take the Totem-Team header; GET /v1/members reads one team, so a key with several teams names it in that header. Authentication explains when to send it.
Every timestamp the API returns is in UTC. Use a team's timezone to show its times in local time, never to store them.
A member's id belongs to one team: the same person has a different mem_ id in each team. Members are not in the changes feed, so read the list when you start syncing a team, when a record names a member you do not know, and at least once a day. A member who leaves the team drops out of the list, while older records keep naming its id: do not re-read the list for an id it did not resolve last time, and if you show names for older records, keep the name from an earlier read. Disabled members stay listed, with nothing that marks them as disabled. Read GET /v1/teams on every sync run, since a team that is no longer listed has left the key.
GET /
Returns the integration this key belongs to: its name, the last four characters of the key, the teams it reads today and its scopes. Call it first to check that a key works and to see which teams it reads; GET /v1/teams has their details.
Returns
Returns a Me object.
objectstringAlways
integration.idstring ID prefixprn_…Public id of the integration.
livemodebooleantruefor a real key;falsein example data.namestringThe name an administrator gave the integration.
keyobjectThe key used for this request.
last4string 4 charsThe last four characters of the key used for this request.
teamsArray<string> ID prefixteam_…The teams this key reads today. Their details are in
GET /v1/teams.scopesArray<string>The key's scopes: the fixed read set in v1.0a.
Possible valuesteams:readcrm:readcalls:readmessages:readcalendar:read
Errors
curl 'https://api.totemstudio.ai/v1/me' \
-H "Authorization: Bearer $TOTEM_API_KEY"{
"object": "integration",
"id": "prn_m1NFIcoIU8smXfqR4ymgt6j07TfRF",
"livemode": false,
"name": "Example CRM sync",
"key": {
"last4": "Q7xZ"
},
"teams": [
"team_r9uYrIW4gSFJJ6hZQ9ip1UIpPaAD1CF7NR"
],
"scopes": [
"teams:read",
"crm:read",
"calls:read",
"messages:read",
"calendar:read"
]
}GET /
Lists every team this key reads, in one response that is never paged, including teams that are restricted for now (their other endpoints answer 403). Re-read it on every sync run: a team that is no longer listed has left the key, so delete its copy and its cursor.
Returns
Returns a list of Team objects.
objectstringAlways
list.dataArray<Team>Every team this key reads, restricted ones included.
has_morebooleanAlways
false: this list is never paged.next_cursornull NullableAlways
null: there is no next page.
Errors
- 429
quota_exceededDaily quota exceeded
curl 'https://api.totemstudio.ai/v1/teams' \
-H "Authorization: Bearer $TOTEM_API_KEY"{
"object": "list",
"data": [
{
"id": "team_r9uYrIW4gSFJJ6hZQ9ip1UIpPaAD1CF7NR",
"object": "team",
"livemode": false,
"name": "Example Dental",
"timezone": "America/New_York",
"default_country": "US"
}
],
"has_more": false,
"next_cursor": null
}GET /
Returns one team this key reads: its name, time zone and default country. A team the key does not read answers 404 resource_missing.
Path parameters
idstring Required ID prefixteam_…The team's public id.
Returns
Returns a Team object.
idstring ID prefixteam_…Public id of the record.
objectstringAlways
team.livemodebooleantruefor real data;falsein example data.namestring Nullable ≥ 1 charsThe team's name as it appears in Totem, or null when none is stored.
timezonestring ≥ 1 charsThe team's IANA time zone: its business-hours zone when that is valid, otherwise its default country's (Europe/Madrid when neither is set). Interpret the team's local times with it.
default_countrystring Nullable Pattern^[A-Z]{2}$The team's default country (ISO 3166-1 alpha-2), which Totem uses when someone types a phone number without a prefix; null when none is set. The API does not apply it:
Lead.phoneis validated without a default country, so a number stored without its country prefix readsphone_status: invalid.
Errors
- 403
team_state_restrictedTeam restricted - 403
sector_restrictedSector restricted - 404
resource_missingResource not found
curl 'https://api.totemstudio.ai/v1/teams/team_r9uYrIW4gSFJJ6hZQ9ip1UIpPaAD1CF7NR' \
-H "Authorization: Bearer $TOTEM_API_KEY"{
"id": "team_r9uYrIW4gSFJJ6hZQ9ip1UIpPaAD1CF7NR",
"object": "team",
"livemode": false,
"name": "Example Dental",
"timezone": "America/New_York",
"default_country": "US"
}GET /
Lists every member of the team in one response that is never paged and takes no limit or cursor. Members are not in the changes feed: read this list when you start syncing a team, again when an item names a member you do not know, and at least once a day. A member who leaves the team drops out of the list while older records keep naming its id, so keep a name you need from an earlier read.
Headers
Totem-Teamstring Conditional ID prefixteam_…The team to read, as a
team_…id. Omit it when the key reads one team; it is required when the key reads several (400 team_required). When you send it, it must name a team the key reads: a malformed id gets400 invalid_request, and a team outside the key gets404 team_not_accessible, as does a request without it once the key reads no team at all.
Returns
Returns a list of Member objects.
objectstringAlways
list.dataArray<Member>Every member of the team.
has_morebooleanAlways
false: this list is never paged.next_cursornull NullableAlways
null: there is no next page.
Errors
- 400
team_requiredTeam required - 403
team_state_restrictedTeam restricted - 403
sector_restrictedSector restricted - 404
team_not_accessibleTeam not accessible - 409
capture_not_readyTeam data is still being prepared - 429
quota_exceededDaily quota exceeded
curl 'https://api.totemstudio.ai/v1/members' \
-H "Authorization: Bearer $TOTEM_API_KEY" \
-H "Totem-Team: $TOTEM_TEAM_ID"{
"object": "list",
"data": [
{
"id": "mem_h548E7UiYhutHhucVrQCzkM0eaea0",
"object": "member",
"livemode": false,
"team": "team_r9uYrIW4gSFJJ6hZQ9ip1UIpPaAD1CF7NR",
"display_name": "Sam Lee"
}
],
"has_more": false,
"next_cursor": null
}GET /
Tells you whether the API is up; call it with GET, because the firewall in front of the API answers any other method, HEAD included, with a plain 404. It needs no key and takes no query string: any parameter, even a cache-buster, answers 400 invalid_request. The Totem-Release response header names the release that answered.
Returns
Returns a Health object.
objectstringAlways
health.statusstringAlways
ok: when the API is not available, the answer is an error instead.
Errors
- 400
invalid_requestInvalid request - 400
secret_key_in_browserSecret key sent from a browser - 500
internal_errorInternal error - 503
service_unavailableService unavailable
curl 'https://api.totemstudio.ai/v1/health'{
"object": "health",
"status": "ok"
}The integration that owns the key, with the teams the key reads.
Attributes
objectstringAlways
integration.idstring ID prefixprn_…Public id of the integration.
livemodebooleantruefor a real key;falsein example data.namestringThe name an administrator gave the integration.
keyobjectThe key used for this request.
last4string 4 charsThe last four characters of the key used for this request.
teamsArray<string> ID prefixteam_…The teams this key reads today. Their details are in
GET /v1/teams.scopesArray<string>The key's scopes: the fixed read set in v1.0a.
Possible valuesteams:readcrm:readcalls:readmessages:readcalendar:read
{
"object": "integration",
"id": "prn_m1NFIcoIU8smXfqR4ymgt6j07TfRF",
"livemode": false,
"name": "Example CRM sync",
"key": {
"last4": "Q7xZ"
},
"teams": [
"team_r9uYrIW4gSFJJ6hZQ9ip1UIpPaAD1CF7NR"
],
"scopes": [
"teams:read",
"crm:read",
"calls:read",
"messages:read",
"calendar:read"
]
}A team this key reads, with its time zone and default country.
Attributes
idstring ID prefixteam_…Public id of the record.
objectstringAlways
team.livemodebooleantruefor real data;falsein example data.namestring Nullable ≥ 1 charsThe team's name as it appears in Totem, or null when none is stored.
timezonestring ≥ 1 charsThe team's IANA time zone: its business-hours zone when that is valid, otherwise its default country's (Europe/Madrid when neither is set). Interpret the team's local times with it.
default_countrystring Nullable Pattern^[A-Z]{2}$The team's default country (ISO 3166-1 alpha-2), which Totem uses when someone types a phone number without a prefix; null when none is set. The API does not apply it:
Lead.phoneis validated without a default country, so a number stored without its country prefix readsphone_status: invalid.
{
"id": "team_r9uYrIW4gSFJJ6hZQ9ip1UIpPaAD1CF7NR",
"object": "team",
"livemode": false,
"name": "Example Dental",
"timezone": "America/New_York",
"default_country": "US"
}A team member, by display name only: Totem exports no email, phone or role.
Attributes
idstring ID prefixmem_…Public id of the record.
objectstringAlways
member.livemodebooleantruefor real data;falsein example data.teamstring ID prefixteam_…The team this record belongs to.
display_namestring Nullable ≥ 1 charsThe member's display name, or first and last name, or null when none is stored. Totem exports no email, phone or role.
{
"id": "mem_h548E7UiYhutHhucVrQCzkM0eaea0",
"object": "member",
"livemode": false,
"team": "team_r9uYrIW4gSFJJ6hZQ9ip1UIpPaAD1CF7NR",
"display_name": "Sam Lee"
}