# Idempotency

Idempotency lets you retry a request (after a timeout or network blip) without
it being processed twice. The Public API provides it in two forms, depending on
the endpoint.

## Usage reporting — idempotency key required

**Usage reporting** (the Meters endpoint) **requires** an
`x-api-idempotency-key` header on every submission. A missing key is rejected
with `400`.

```bash
curl -X POST https://api.ledgerbee.com/api/v1/meters/report \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-api-idempotency-key: 3f9c1e2a-7b54-4e10-9a2b-8d1f6c0e4a77" \
  -d '{ ... }'
```

- Reuse the **same** key when retrying the **same** submission — the duplicate
  is acknowledged with `status: "duplicate"` instead of being recorded twice.
- Use a **fresh** key for each new submission. A UUID is a good key.
- Keys are scoped per tenant, so two callers can never collide on the same
  key value.

Endpoints that require the key mark the header parameter as required in the
**[API Reference](/api)**.

## Naturally idempotent endpoints

Some endpoints are idempotent by design through their identifiers rather than
a header — for example, **customer provisioning** upserts by
`customer.customerNumber`, so re-sending the same provision request resolves to
the same customer instead of creating a duplicate. The endpoint descriptions in
the **[API Reference](/api)** call this out where it applies.

## Everything else

Other mutating endpoints do **not** currently dedupe retried requests — an
`x-api-idempotency-key` header sent to them is ignored. Design retry logic
accordingly: on a timeout where the outcome is unknown, read back (e.g. list
recently created resources) before re-creating.
