> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracklysms.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Idempotency

> Safely retry supported write requests with an Idempotency-Key so a dropped connection does not duplicate work.

Network calls fail in ambiguous ways: a request times out, but the client cannot know whether the server processed it. To retry safely, send an **`Idempotency-Key`** header. Trackly remembers the first successful result for that key and replays it on an exact retry, so protected work runs **at most once**.

```
Idempotency-Key: <your-unique-key>
```

## Where it applies

Idempotency is supported on selected write endpoints, including:

* [Create child account](/api-reference/v2/accounts/create-child) — `POST /v2/accounts/children`
* [Send message](/api-reference/v2/messages/send-single) — `POST /v2/send`
* [Create Number Request](/api-reference/v2/number-requests/create-request) — `POST /v2/number-requests`
* [Update Number Request](/api-reference/v2/number-requests/update-request) — `PATCH /v2/number-requests/{request_id}`
* [Update International Requirements](/api-reference/v2/number-requests/update-requirements) — `PATCH /v2/number-requests/{request_id}/international-requirements`
* [Correct Resource Request](/api-reference/v2/number-requests/correct-request) — `POST /v2/number-requests/{request_id}/correction`

If you omit the header, the request runs normally with no idempotency protection.

For each variable-resource Number Request mutation above, the replay fingerprint includes the concrete path as well as the body and query. Within that operation, an exact retry to the same request id replays, while the same key and payload sent to another request id returns `409 idempotency_conflict`. Existing idempotent endpoints retain their established body-and-query fingerprint behavior.

## How it behaves

<ResponseField name="Same key, same request">
  The first successful (`2xx`) response is cached for **24 hours** and returned **verbatim** — same body, same status code — on every retry. The handler does not run again.
</ResponseField>

<ResponseField name="Same key, different request">
  Reusing a key with a **different** request body or query returns `409 idempotency_conflict`. Path-bound operations also conflict when the concrete resource path changes. An idempotency key must identify one exact operation.
</ResponseField>

<ResponseField name="Retry while the first is still running">
  If a retry arrives before the original finishes, it returns `409 idempotency_in_progress` with a `Retry-After: 5` header. Wait and retry.
</ResponseField>

<ResponseField name="The first attempt failed">
  A non-`2xx` result **releases the key** — you can immediately reuse the same key to retry. This differs from providers that bind a key on first receipt; after fixing a `400`, the same key can be retried with the corrected request.
</ResponseField>

## Choosing a key

* Use a value unique to the operation — a UUID, or a deterministic ID from your own system (e.g. `create-child:loc_west`).
* Keys are **≤255 characters, printable ASCII**. Longer or non-printable keys return `400 idempotency_key_too_long` / `idempotency_key_invalid`.

<Note>
  **Test and live keys are isolated.** The idempotency namespace is separated by mode, so a [sandbox](/api-reference/v2/sandbox) key and a live key can use the same `Idempotency-Key` value without ever colliding.
</Note>

## Example

Retrying a child creation with the same key returns the original child, not a second account:

```bash cURL theme={null}
curl -X POST https://api.tracklysms.com/api/v2/accounts/children \
  -H "X-Api-Key: trk_your_parent_key" \
  -H "Idempotency-Key: create-child-loc-west-0001" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme West", "externalIds": {"locationId": "loc_west"}, "paidIntent": true}'
```

Run it twice with the same `Idempotency-Key` and you get the same `201` response both times — one child is created.

<Note>
  Idempotency protects against **duplicate requests**, while `externalIds.locationId` uniqueness protects against **duplicate businesses** created by different requests. Together they make child provisioning safe to retry from anywhere.
</Note>
