+++
title = "API Quickstart"
weight = 77
updated = 2026-11-03

[extra]
nav_title = "Quickstart"
weight = 20
+++

This walks through the life of a cluster with the Bonsai API v1: pick a plan and a region, create the cluster, wait for it, connect to it, and delete it. It uses `curl` and `jq`.

## 1. Create a token

In the dashboard, open your account's settings, then the **API Tokens** tab, and create a token with these [scopes](@/docs/api/authentication/index.md#scopes):

- `account:read`, to list plans and regions.
- `clusters:read` and `clusters:write`, to create, watch and delete the cluster.
- `credentials:read`, to get the cluster's URL.

`clusters:write` needs the Admin role on the account. Copy the token when it's shown, since it's shown only once, and put it in an environment variable:

```bash
export BONSAI_TOKEN=bonsai_<key>_<secret>
```

Check that it works:

```bash
curl -s https://api.bonsai.io/v1/token -H "Authorization: Bearer $BONSAI_TOKEN" | jq
```

```json
{
  "key": "1a2b3c4d5e6f7a8b",
  "name": null,
  "account": { "id": "acme", "name": "Acme" },
  "scopes": ["account:read", "clusters:read", "clusters:write", "credentials:read"],
  "expires_at": null,
  "created_at": "2026-10-26T14:00:00Z"
}
```

## 2. Pick a plan and a region

Plans differ by account. List the ones yours can use:

```bash
curl -s https://api.bonsai.io/v1/plans -H "Authorization: Bearer $BONSAI_TOKEN" \
  | jq '.data[] | {id, name, price_in_cents, regions}'
```

Each plan lists the regions it can be created in, and its `offers` list the releases available in each region. [`GET /v1/regions`](@/docs/api/reference/catalog/index.md#list-regions) lists the regions themselves. See the [Plan object](@/docs/api/reference/catalog/index.md#plan-object) for every field.

## 3. Create the cluster

```bash
curl -s -i https://api.bonsai.io/v1/clusters \
  -H "Authorization: Bearer $BONSAI_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name": "my-search", "plan": "sandbox", "region": "aws-us-east-1"}'
```

`name`, `plan` and `region` are required. Add `release` to choose the engine and version, from the plan's `offers` for that region; without it, you get the first one offered. Accounts with private spaces can add `space`.

The `Idempotency-Key` header makes the request safe to retry: if the connection drops before you see the answer, send the same request with the same key, and you get the same Action back instead of a second cluster. See [Retrying safely](@/docs/api/retrying-safely/index.md).

Creating a cluster takes a few seconds, so the API answers `202 Accepted` with an Action, plus a `Location` header pointing at it:

```
HTTP/2 202
location: https://api.bonsai.io/v1/actions/act_3k9x0q2m7v1c8b4n
retry-after: 5
```

```json
{
  "id": "act_3k9x0q2m7v1c8b4n",
  "type": "cluster.provision",
  "state": "new",
  "subject": { "type": "cluster", "id": "my-search-4823919" },
  "created_at": "2026-10-26T14:03:00Z",
  "finished_at": null,
  "error": null,
  "result": null,
  "steps": []
}
```

The cluster's ID is in `subject.id`.

A paid plan needs a payment method on the account, unless the account is billed by invoice. Without one, the create is refused at once with [`422 payment_method_required`](@/docs/api/errors/index.md#payment_method_required), and the error's `action_url` is a page where a card can be added. Nothing is created, and the same request with the same `Idempotency-Key` works once the card is in.

## 4. Wait for it

Poll the Action until its `state` is `success` or `error`, waiting the number of seconds in its `Retry-After` header between polls:

```bash
curl -s https://api.bonsai.io/v1/actions/act_3k9x0q2m7v1c8b4n \
  -H "Authorization: Bearer $BONSAI_TOKEN" | jq '{state, result, error}'
```

```json
{
  "state": "success",
  "result": { "cluster": "my-search-4823919", "credential": "scc-a8Kd" },
  "error": null
}
```

On success, `result` names the new cluster and its first credential. If the build fails, `state` is `error`, `error.code` says why, and Bonsai stops billing for the cluster. See [Actions](@/docs/api/actions/index.md).

## 5. Connect to it

A credential holds the username and password for the cluster. Get the first one, with its URL:

```bash
curl -s https://api.bonsai.io/v1/clusters/my-search-4823919/credentials/scc-a8Kd \
  -H "Authorization: Bearer $BONSAI_TOKEN" | jq -r .url
```

```
https://<username>:<password>@my-search-4823919.us-east-1.bonsaisearch.net
```

That URL includes the password, so keep it out of logs and source control. Use it as your Elasticsearch or OpenSearch client's URL, or check the cluster with:

```bash
curl "https://<username>:<password>@my-search-4823919.us-east-1.bonsaisearch.net"
```

To give an app its own credential, with read-only access for example, [create one](@/docs/api/reference/credentials/index.md#create-cluster-credential) with `POST /v1/clusters/{cluster_id}/credentials`. That needs the `credentials:write` scope.

## 6. Delete it

Deleting a cluster takes its current name as a confirmation:

```bash
curl -s -X DELETE "https://api.bonsai.io/v1/clusters/my-search-4823919?name=my-search" \
  -H "Authorization: Bearer $BONSAI_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
```

A missing `name` is a [`400 name_confirmation_required`](@/docs/api/errors/index.md#name_confirmation_required), and a different one is a [`422 name_mismatch`](@/docs/api/errors/index.md#name_mismatch). Like the create, a delete answers `202` with an Action, of type `cluster.deprovision`, that you can poll.

Deleting a cluster deletes its data, and can't be undone.

## Next steps

- [Actions](@/docs/api/actions/index.md): polling, failures, and the Actions Bonsai starts on its own.
- [Retrying safely](@/docs/api/retrying-safely/index.md): idempotency keys.
- [Errors](@/docs/api/errors/index.md): every error code, and what to do about it.
- [API reference](@/docs/api/reference/_index.md): every operation, parameter and field.
