+++
title = "Retrying API Requests Safely"
weight = 81
updated = 2026-11-03

[extra]
nav_title = "Retrying safely"
weight = 32
+++

A network error can leave you not knowing whether a request went through. Send an `Idempotency-Key` header with a write, and you can retry it without doing the work twice.

These operations take one:

| Operation | A retry with the same key gets |
| --- | --- |
| [Create a cluster](@/docs/api/reference/clusters/index.md#create-cluster) | The same `cluster.provision` Action, not a second cluster. |
| [Delete a cluster](@/docs/api/reference/clusters/index.md#delete-cluster) | The same `cluster.deprovision` Action. |
| [Change a cluster's plan](@/docs/api/reference/clusters/index.md#change-cluster-plan) | The same `cluster.change_plan` Action. |
| [Create a credential](@/docs/api/reference/credentials/index.md#create-cluster-credential) | The same credential, with its secret. |

## Sending a key

```bash
curl -s https://api.bonsai.io/v1/clusters \
  -H "Authorization: Bearer $BONSAI_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8e2c6a1e-5b7d-4c43-9f0a-2d4b1c9e7f31" \
  -d '{"name": "my-search", "plan": "sandbox", "region": "aws-us-east-1"}'
```

The key can be any 1 to 255 printable ASCII characters; a random UUID is a good choice. Use a new key for each change you mean to make, and the same key when retrying it.

Keys belong to the token that sent them, and are kept for 24 hours. Replays count toward your [rate limit](@/docs/api/rate-limits/index.md).

## What a retry gets

- **The same key and the same request** get the original response back, with an `Idempotent-Replayed: true` header. The response is rebuilt from what the first request made, as that is now: a replayed create returns the Action in its current state.
- **The same key with a different request** is refused with [`422 idempotency_key_reused`](@/docs/api/errors/index.md#idempotency_key_reused).
- **A retry while the first request is still being handled** gets [`409 idempotency_key_in_use`](@/docs/api/errors/index.md#idempotency_key_in_use), with a `Retry-After` header.
- **A replay of something that's gone**, such as a credential that has since been revoked, gets [`409 idempotency_replay_unavailable`](@/docs/api/errors/index.md#idempotency_replay_unavailable). Use a new key if you mean to make a new one.
- **A request that fails** doesn't use up its key. If a create is refused for want of a payment method, add the card, and send the same request with the same key.

## Retrying without a key

Without a key, a retried write is a new request. A retried create can make a second cluster, and a retried delete, after the cluster is gone, gets [`422 cluster_terminated`](@/docs/api/errors/index.md#cluster_terminated) rather than the Action. The Action is still in the cluster's [Action list](@/docs/api/reference/actions/index.md#list-cluster-actions).
