Skip to content

Add an account team member

PUT
/customers/{customerId}/account-team/{email}
curl --request PUT \
--url https://api.usesonora.com/v1/customers/example/account-team/example \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "role": "example" }'

Put someone in your workspace on the customer’s account team, or change their role there. Adding a member who is already on the team changes nothing. The owner is always on the team, so naming them is 409 account_team_owner.

Requires the customers:write scope. API keys only.

customerId
required
string

The customer’s Sonora id — or, with idType, its id in another system, or its domain.

email
required
string

The person’s email address, URL-encoded: tess%40yourco.com.

idType
string

How id names the account: sonora (the default; Sonora’s customer id), salesforce, hubspot, domain, or custom_field:<key>. So GET /customers/001Ab…?idType=salesforce finds a customer by its Salesforce Account id.

Media typeapplication/json

The member’s role, if any. The body may be left out.

object
role
Any of:
string
>= 1 characters <= 255 characters
Examplegenerated
{
"role": "example"
}

The customer, with its account team.

Media typeapplication/json

A customer account, with its account team and the fields edits have taken over.

object
id
required
string
name
required
string
websiteUrl
required
string | null
emailDomains
required

Domains whose email addresses belong to this customer.

Array<string>
arr
required

Annual recurring revenue.

number | null
stage
required
string | null
tier
required
string | null
owner
required
Any of:

A person on your team.

object
name
required
string | null
email
required

Null for a name typed in by hand or synced without a user.

string | null
renewalDate
required
Any of:
string format: date
contractStartDate
required
Any of:
string format: date
contractLengthDays
required
Any of:
integer
summary
required

Sonora’s running summary of the account.

string | null
customFields
required

Your workspace’s custom fields, by key — only fields visible in Sonora.

object
key
additional properties

As the field’s type says (GET /customer-fields). A user field is a list of people: [{ name, email }].

externalIds
required
Array<object>

The record’s id in another system.

object
source
required

The system the id is from: salesforce, hubspot, zendesk, intercom, …

string
id
required
string
health
required
Any of:

The customer’s health, as the customers page shows it.

object
state
required

The state’s key on your workspace’s health scale — by default thriving, healthy, emerging_concerns or at_risk — or no_data when nothing could be scored.

string
label
required

The state as Sonora shows it: Thriving, At Risk, …

string
score
required

0–10, higher is healthier. Null when there is nothing to score (no_data).

number | null
atRisk
required

Whether your scale counts this state as at risk.

boolean
computedAt
required
string format: date-time
ecsat
required
Any of:

ECSAT: satisfaction Sonora estimates from what the customer says, averaged over recent touchpoints.

object
score
required

The average estimated satisfaction of the customer’s scored calls, emails and tickets, 0–10, to one decimal.

number
windowDays
required

The days back the average covers.

number
Allowed value: 90
enrichments

Only with ?include=enrichments: the latest value of each enrichment that has one, in GET /enrichment-configs order.

Array<object>

A record’s latest value of one enrichment.

object
configId
required

The enrichment’s id (GET /enrichment-configs/{configId}).

string
title
required
string
outputType
required

What the value is: short_text/long_text a string, number a number, score 1–10 (10 strongest), boolean, date YYYY-MM-DD, email, url, or select one of options (a list of them with multiple).

string
Allowed values: short_text long_text number score boolean date email url select
value
required

As outputType says. Null when there wasn’t enough to go on, for any outputType.

reason
required

Why the AI gave this value, when it said.

string | null
computedAt
required
string format: date-time
engagementsCount
required

Calls, emails, meetings and tickets Sonora has seen.

integer
lastEngagementAt
required
Any of:
string format: date-time
archivedAt
required
Any of:
string format: date-time
createdAt
required
string format: date-time
updatedAt
required

Moves on any change to the record, including Sonora’s own bookkeeping (engagement counts), so a sync may see a customer again with no field you read changed.

string format: date-time
links
required
object
self
required

This resource’s canonical URL on the API host.

string
accountTeam
required

The account team beyond the owner, with each member’s role where the CRM gives one.

Array<object>
object
name
required
string | null
email
required

Null for a name typed in by hand or synced without a user.

string | null
role
required
string | null
overriddenFields
required

Fields an edit — in Sonora or through this API — has taken over from sync: your CRM’s changes to them are held back until someone resumes sync on the field in Sonora. Standard fields by name (arr, owner), custom fields as customFields.<key>.

Array<string>
Example
{
"ecsat": {
"windowDays": 90
},
"enrichments": [
{
"outputType": "short_text"
}
]
}
ETag
string

A fingerprint of the fields PATCH can change. Send it back as If-Match to update only if none of them has changed since.

invalid_json: The request body is not valid JSON.

invalid_request: A parameter or body field is missing, malformed or unknown; details.issues names each.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

unauthorized: The Authorization header is missing, or the key is invalid, revoked or expired.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

insufficient_scope: The key or token lacks the scope this endpoint needs, and details.required names it; or an OAuth access token called an endpoint only an API key can.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

customer_not_found: No customer matches the id (and idType) in the path.

person_not_found: No one in your workspace has the email the path names.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

account_team_owner: The person owns the customer, and the owner is always on its account team. Change the owner first.

customer_archived: The customer is archived; unarchive it before changing it.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

payload_too_large: The request body is too large; details.maxBytes gives the limit.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

rate_limited: Too many requests for this key; retry after Retry-After seconds.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

internal_error: Something went wrong on Sonora’s side. Retry, and quote requestId if it persists.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

Try it

Try it runs the reference's read endpoints, and this one changes data, so it needs an API key with the customers:write scope. Create a key in Sonora under Settings → API and call it from your own code.