Skip to main content

Error response formats

The API returns error bodies in three formats, depending on the endpoint. Your error handling needs to read all three.

Format 1: Flat field errors​

Used by deals (POST /deals/, POST /deals/update_or_create/).

{
"user_id": [
"Invalid pk \"999999\" - object does not exist."
],
"products": [
"Invalid pk \"999999\" - object does not exist."
]
}

Errors are at the root level, keyed by field name. All field errors come back in one response.

Format 2: Nested under errors​

Used by events (POST /events/).

{
"errors": {
"user_id": [
"Client user with ID '999999' does not exist"
],
"name": [
"This field is required."
]
}
}

Field errors are inside an errors object.

Format 3: Detail string​

Used when the record in the URL doesn't exist, for example GET /users/:id/ or POST /users-by-id/:user_custom_id/events/.

{
"detail": "No ClientUser matches the given query."
}

A single detail string, with status 404.

Read all three formats​

This function turns any of the three formats into one dictionary of errors by field:

def parse_api_error(response):
data = response.json()

if "detail" in data:
return {"_general": [data["detail"]]}

if "errors" in data:
return data["errors"]

return data

Validation order​

The API validates fields in a set order, and an early failure can hide later ones.

Events for a contact by custom ID: the contact is validated first​

POST /users-by-id/:user_custom_id/events/ checks the contact in the URL before anything else. If the contact doesn't exist, you get 404 and no errors about the request body, even if it is empty.

If you get a contact-not-found error, fix it first: more errors may show up once the contact exists.

Events by contact ID: all fields are validated at once​

POST /events/ returns every field error in one response, the contact included:

{
"errors": {
"name": [
"This field is required."
],
"user_id": [
"Client user with ID '999999' does not exist"
]
}
}

Deals: all fields are validated at once​

The deals endpoints validate all fields together and return every error in one response, so you can fix them all at once.