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

# Using Idempotency Keys to Safely Retry Log Batches

> Use the Idempotency-Key header to retry log batches safely — Peeng deduplicates on your behalf within a 24-hour window, preventing duplicate entries.

Idempotency means you can send the same log batch to Peeng more than once and be guaranteed that the logs are only stored a single time. This matters whenever you retry a request after a network timeout or a dropped connection, because without idempotency you can't tell whether the original request landed — and blindly resending creates duplicate log entries. Peeng solves this with the `Idempotency-Key` request header: attach a unique key per batch, and Peeng uses it to deduplicate for up to 24 hours.

<Info>
  Both the JavaScript and Python SDKs generate and attach an `Idempotency-Key` automatically for every batch they flush, reusing the same key on every retry of that batch. You only need this page if you are calling the HTTP API directly and building your own retry logic.
</Info>

## Setting the header

Pass any UUID (or sufficiently unique string) as the `Idempotency-Key` header on `POST /v1/logs`. Generate a fresh key for each new batch, then reuse that exact key for every retry of the same batch.

```bash theme={null}
curl -X POST https://api.peeng.dev/v1/logs \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Idempotency-Key: 5b3f9e2a-6c1d-4e8a-9f2b-1a3c5d7e9f0b" \
  -d '{ "logs": [...] }'
```

## How it works

Peeng scopes each key to your project and remembers it for **24 hours**. Here is what happens in each scenario:

| Scenario                                                                 | What Peeng does                                                   | What you should do                                                     |
| ------------------------------------------------------------------------ | ----------------------------------------------------------------- | ---------------------------------------------------------------------- |
| **First request** with a new key                                         | Persists the batch normally and caches the result against the key | Nothing special — proceed as normal                                    |
| **Retry with the same key** (e.g. after a timeout or dropped connection) | Returns the original cached result without re-inserting any logs  | Retry freely — no duplicates will be created                           |
| **Retry while the first request is still in flight**                     | Returns `409 Conflict` — the key is already being processed       | Back off and retry later; do **not** treat this as a permanent failure |

The `409` case is the one scenario worth handling explicitly in custom retry code. It is a transient condition — the in-flight request will finish shortly — so a short backoff followed by a retry is the right response.

## Without a key

The `Idempotency-Key` header is optional. Omitting it is perfectly safe for one-off fire-and-forget calls where you will never retry. However, if your retry logic resends a batch after a timeout (when you do not know whether the original request succeeded), you risk creating duplicate log entries because Peeng has no basis for deduplication.

<Tip>
  Always set `Idempotency-Key` on any request that might be retried. Generate one UUID per batch, hold onto it for the lifetime of that batch's retry loop, and discard it once the batch succeeds or you give up.
</Tip>
