Request bodies
Every operation with a body reads it the same way. The reference of each operation shows the fields of its body.
The request as a whole
| Rule | Otherwise |
|---|---|
Content-Type: application/json; parameters such as charset are allowed |
415 unsupported_media_type |
| At most 10 MB, the same number in the API and in MCP | 413 body_too_large |
| JSON, in UTF-8, not empty | 400 invalid_json; detail says where it breaks |
The form of the body
The form is strict:
- The body is a JSON object.
- Every field belongs to the operation. An unknown field, nested ones included, is
unknown_field. - The JSON type is the type of the field, without coercion:
"5"is not a number, and1.5is not an integer. Otherwiseinvalid_type. nullis allowed only on a field that can be cleared. Otherwiseinvalid_type.- Every required field is present. Otherwise
required.
Every violation is one item of errors in a single 422 validation_failed. Nested fields are named by path, for example settings.tracking.opens; an error about the whole body has an empty field.
{
"field": "name",
"code": "invalid",
"message": "must not be empty"
}
The values
When the form is right, the operation checks the values: patterns, lengths, ranges, references to the node’s config. It also returns every violation at once, in one 422. A body with errors of both kinds gets the form errors first.
All field codes are on the errors page.
PATCH is a JSON merge patch
| In the body | Effect |
|---|---|
| The field is absent | The value does not change |
The field is null |
The value is cleared, on fields that can be empty |
| The field has a value | The value is replaced |
| The field is an object | It is merged field by field |
For example, this body for PATCH /api/v1/projects/{project_id} (update_project_settings) changes one tracking setting of a project and leaves the rest as it is:
{
"settings": {
"tracking": { "opens": false }
}
}
PUT /api/v1/projects/{project_id}/templates/{template_id} (update_template) is not a merge: it saves a new version of the template.
Order of checks
A request is checked in this order, and the first failure answers:
- The key:
401. - The rate limit:
429. - On a
POSTwithIdempotency-Key: the header (422), the body size (413), a key that is taken (422 idempotency_key_reused,409 idempotency_key_in_progress) or a replay of the stored answer. - The form of the body:
400,413,415,422. - Rights:
403. - Existence:
404. - State:
409. - Values:
422.
Another project’s resource for a project key is 404 before 403. The form of the body comes earlier still, but it is the same for any project_id and tells nothing about other projects. The right to issue a key with given scopes and expiry (403) is checked after the values, because only parsed values can be compared.