Generated from Postwind commit a19b2e4 OpenAPI 0.1.0 synced

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, and 1.5 is not an integer. Otherwise invalid_type.
  • null is allowed only on a field that can be cleared. Otherwise invalid_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:

  1. The key: 401.
  2. The rate limit: 429.
  3. On a POST with Idempotency-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.
  4. The form of the body: 400, 413, 415, 422.
  5. Rights: 403.
  6. Existence: 404.
  7. State: 409.
  8. 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.