+++
title = "API Requests and Responses"
weight = 79
updated = 2026-11-03

[extra]
nav_title = "Requests and responses"
weight = 27
+++

The conventions every operation of the Bonsai API v1 follows: bodies, times, IDs, pagination, and values that can grow.

## Bodies

Request and response bodies are JSON. Send `Content-Type: application/json` with a body.

A body with a field the operation doesn't take is refused with a [`400 invalid_parameter`](@/docs/api/errors/index.md#invalid_parameter) naming the field, so a typo is never silently ignored. A body that isn't JSON is a [`400 invalid_json`](@/docs/api/errors/index.md#invalid_json), and a missing or empty one, where the operation needs one, is a [`400 body_required`](@/docs/api/errors/index.md#body_required).

Errors have their own content type, `application/problem+json`. See [Errors](@/docs/api/errors/index.md).

## Times

Times are RFC 3339 in UTC, like `2026-10-26T14:03:00Z`. A time that hasn't happened yet, such as a running Action's `finished_at`, is `null`.

## IDs and names

A cluster's `id` is its slug, such as `my-search-4823919`. It never changes and is never reused. A cluster's `name` is a label: it can change, and two clusters can share it. Use the `id` to refer to a cluster in paths.

A credential's `id` is its slug too, such as `scc-a8Kd`, and never changes.

Action IDs are `act_` followed by 16 random characters, such as `act_3k9x0q2m7v1c8b4n`. They're opaque, in no order: don't sort by them or parse them.

Plans, regions, spaces and releases have readable IDs, such as `aws-us-east-1` for a region or `opensearch-3.8.0` for a release.

### References to other resources

A resource points to another one with a small object holding its `id` and `name`:

```json
"account": { "id": "acme", "name": "Acme" }
```

Fetch the other resource by its `id` for the rest of it.

## Pagination

Lists return a page of results in `data` and a `next_cursor`:

```json
{
  "data": [ ... ],
  "next_cursor": "eyJpZCI6MTIzfQ"
}
```

To get the next page, send `next_cursor` back as `cursor`. `next_cursor` is `null` on the last page. `limit` sets the page size, from 1 to 100, and defaults to 25.

```bash
curl "https://api.bonsai.io/v1/clusters?limit=100&cursor=eyJpZCI6MTIzfQ" \
  -H "Authorization: Bearer $BONSAI_TOKEN"
```

Treat the cursor as opaque: don't build or change one yourself. Each list's order is on its reference page.

## Values that can grow

Some fields take one of a set of values that can grow: cluster states, Action types and states, credential access types, error codes, and a few more. The [API reference](@/docs/api/reference/_index.md) marks each of these as an open set. New values are added without a new version, so:

- Handle a value you don't know. For an error code, fall back on the HTTP status. For an Action's `error.code`, treat it like `action_failed`.
- Ignore response fields you don't know. New fields are added the same way.

See [Versioning](@/docs/api/versioning/index.md) for what can and can't change within v1.

## Nulls and empty lists

A field with no value is usually there as `null`, and a number that isn't known yet is `null`, not `0`. The few fields that are left out instead, like a problem's `action_url`, say so in the reference. A cluster that has never had its stats polled, for example, has `null` stats.

An empty list means there's nothing to list. When the store behind usage, metrics or top queries doesn't answer, the API says so with a [`503 metrics_unavailable`](@/docs/api/errors/index.md#metrics_unavailable) instead of an empty list.
