Skip to content

Create a custom field

POST
/customer-fields
curl --request POST \
--url https://api.usesonora.com/v1/customer-fields \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "label": "example", "type": "string", "format": "currency", "options": [ "example" ], "multiple": true }'

Add a custom field to every customer, as Add column on the customers page does. Its key is made from the label — Renewal risk becomes renewal_risk, or renewal_risk_2 if an earlier field still owns that key — and the answer says which. Every customer starts without a value. A label another field already shows is 409 customer_field_exists. Send an Idempotency-Key to make a retry safe.

Requires the custom-fields:manage scope. API keys only.

Idempotency-Key
string
>= 1 characters <= 255 characters

1–255 printable characters. A retry with the same key and request answers with the first call’s result instead of acting twice.

Media typeapplication/json

A custom field to add to customers. Its key is made from the label.

object
label
required

How Sonora shows the field. No other field may show the same label, ignoring case; runs of spaces are kept as one.

string
>= 1 characters <= 100 characters
type
required

date holds YYYY-MM-DD; select one of options; user people in your workspace.

string
Allowed values: string number boolean date select user
format
Any of:
string
Allowed values: currency url email
options
Any of:
Array<string>
>= 1 items <= 50 items
multiple

user only: true lets the field hold several people. Left out, it holds one.

boolean

The field, created.

Media typeapplication/json

A custom field on customers.

object
key
required

The key in a customer’s customFields.

string
label
required
string
type
required

date is YYYY-MM-DD; datetime an ISO 8601 instant; select one of options (or several, with multiple); user a list of people.

string
Allowed values: string number boolean date datetime select user array object
format
required

How the value is meant: currency, percentage, email, url, phone, … Null when it’s plain.

string | null
options
required
Any of:
Array<string>
multiple
required

Whether the value is a list: a multi-select, or a user field holding several people.

boolean
Example
{
"type": "string"
}
Idempotent-Replayed
string

true when this answers a retry with an earlier call’s Idempotency-Key: the first call’s body, replayed.

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_field_exists: A custom field already has that label; details.key names it when it’s one the API shows.

idempotency_key_in_use: A request with this Idempotency-Key is still being processed. Retry once it has finished.

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"
}
}

idempotency_key_mismatch: The Idempotency-Key was used before with a different request.

invalid_fields: A field’s value can’t be saved, so nothing was; details.issues names each field and why.

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 custom-fields:manage scope. Create a key in Sonora under Settings → API and call it from your own code.