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

# Idempotency Keys and User IDs

> Why idempotency keys matter, what to implement, and how to generate player identifiers.

ZBD handles real-value transactions for games. Every such request carries an **idempotency key** — if the same request arrives again with the same key, ZBD returns the original result instead of creating a second payment. The key is generated by the client, once per purchase intent, and reused on every retry of that intent rather than regenerated each attempt.
Player identifiers deserve the same care, though ZBD imposes no format on them: how you generate the player IDs you send us is your call. We recommend time-ordered, random IDs (UUIDv7) — unique across services, sortable, unguessable, and free of personal data.
This page explains why both matter and what to implement.

## Why idempotency keys

An **idempotency key** is a unique string the client sends with a request so that a retry can't create a second payment.
Without one, a request that fails after the payment goes through but before the client hears back is indistinguishable from one that never landed — so the client retries, and the player is charged twice.
The cost of getting it wrong: duplicate charges, refund and chargeback fees, support tickets, store-rating damage, and duplicated in-game currency that breaks the game economy.

## Idempotency key: requirements

* **Format:** UUIDv4 (122 random bits) or equivalent; max 255 chars. Sent as the `Idempotency-Key` HTTP header.
* **One key per purchase intent.** Generate it when the player confirms the purchase, persist it locally, and reuse it on every retry until a final response arrives.
* **New intent = new key.** Buying a second gem pack is a new purchase and gets a new key.
* **Never derive keys** from timestamps alone, counters, or player ID + item ID — two legitimate identical purchases would collide.
* **Send one on every state-changing request:** payments, refunds, payouts, and in-game reward grants.

## Player ID generation (recommended)

Player IDs are generated on your side and sent to ZBD with each request. ZBD accepts whatever format you use — the guidance here is what we'd suggest if the choice is still open.
A good player ID combines a **timestamp** (creation date-time) with **cryptographically secure randomness**. The time component keeps IDs sortable and index-friendly; the random component guarantees uniqueness across servers and makes IDs unguessable.
**Suggested standard: UUIDv7 (RFC 9562)**

| Part | Bits | Purpose |
| - | - | - |
| Unix timestamp (ms) | 48 | Time-ordered; efficient DB inserts |
| Version + variant | 6 | Standard format |
| Random (CSPRNG) | 74 | Uniqueness, unguessability |

Example: `0192a4f3-7c1e-7b2a-9f4d-3e8c1a6b5d20`
Optionally add a readable type prefix for logs and support: `usr_0192a4f37c1e7b2a9f4d3e8c1a6b5d20`.
**Recommendations**

* **Generate server-side** with a CSPRNG (e.g. `crypto.randomUUID` grade sources), rather than `Math.random()` or sequential counters.
* **Keep personal data out of the ID** — no email, username, device ID, or game account handle. IDs appear in logs, URLs, and receipts.
* **Treat IDs as immutable and never reused**, even after account deletion.
* **An ID is an identifier, not a secret.** Don't use it as an auth token or password substitute; authorize every request separately.
* **Avoid exposing raw sequential DB keys** externally — they leak player counts and enable enumeration.

## Do / Don't

| Do | Don't |
| - | - |
| Send an idempotency key on every payment, refund, and reward grant | Rely on the client "only clicking once" |
| Reuse the same key for every retry of one purchase | Generate a fresh key per retry |
| Use UUIDv7 (timestamp + CSPRNG random) for player IDs | Use auto-increment IDs or `Math.random()` |
| Keep player IDs free of personal data | Embed emails, handles, or device IDs |
| Treat IDs as public identifiers | Treat IDs as secrets or auth tokens |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.