# Idempotency Network failures, timeouts, and retries are a reality of distributed systems. The Dinie API supports **idempotency keys** so you can safely resend `POST` requests without accidentally creating duplicate resources. ## What is Idempotency? An operation is idempotent if executing it multiple times produces the same result as executing it once. For example, `GET` and `DELETE` are naturally idempotent -- fetching or deleting the same resource twice has the same effect. But `POST` (creation) is not naturally idempotent -- sending it twice may create two resources. The `Idempotency-Key` header makes `POST` requests idempotent by associating the request with a unique key. If the same key is sent again, the API returns the cached response from the first request instead of processing a new one. ## Using the Idempotency-Key Header Include an `Idempotency-Key` header in `POST` requests that create resources: ```typescript Node.js const customer = await dinie.customers.create( { cpf: "123.456.789-00", name: "Joao Silva", email: "joao@example.com", }, { idempotencyKey: "partner-onboard-joao-2026-03-04" } ); ``` ```ruby Ruby customer = dinie.customers.create( cpf: "123.456.789-00", name: "Joao Silva", email: "joao@example.com", idempotency_key: "partner-onboard-joao-2026-03-04" ) ``` ```python Python customer = dinie.customers.create( cpf="123.456.789-00", name="Joao Silva", email="joao@example.com", idempotency_key="partner-onboard-joao-2026-03-04", ) ``` ```bash cURL curl -X POST https://sandbox.api.dinie.com.br/v3/customers \ -H "Authorization: Bearer dinie_at_..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: partner-onboard-joao-2026-03-04" \ -d '{ "cpf": "123.456.789-00", "name": "Joao Silva", "email": "joao@example.com" }' ``` ## Supported Operations Idempotency keys are supported on all `POST` requests that create resources: | Endpoint | Description | | --- | --- | | `POST /v3/customers` | Create a customer | | `POST /v3/customers/{id}/documents` | Upload a document | | `POST /v3/credit-offers/{id}/simulations` | Run a simulation | | `POST /v3/loans` | Create a loan | | `POST /v3/auth/credentials` | Create an API credential | | `POST /v3/webhooks/endpoints` | Create a webhook endpoint | | `POST /v3/webhooks/endpoints/{id}/secret/rotate` | Rotate webhook secret | > **Info:** `GET`, `PATCH`, and `DELETE` are naturally idempotent and do not require the header. You can safely resend these requests without any special handling. ## How It Works 1. You send a `POST` request with an `Idempotency-Key` header 2. The API processes the request and caches the response, indexed by `(partner_id, idempotency_key)` 3. If you send the same key again within 24 hours, the API returns the cached response without reprocessing 4. After 24 hours, the cached response expires and the key can be reused ## Cache Window Idempotency keys are cached for **24 hours**. After that period: - The key expires and the cached response is discarded - Sending the same key will process a new request - If you need to resend after 24 hours, use a new idempotency key ## Handling Collisions If you send the same idempotency key with a **different request body**, the API returns the cached response from the first request. It does not compare request bodies -- the key alone determines the cached response. > **Warning:** Always use unique idempotency keys for different operations. A good pattern is to combine a semantic prefix with a unique identifier: - `create-customer-{external_id}` - `create-loan-{offer_id}-{timestamp}` - `upload-doc-{customer_id}-{doc_type}` ## Generating Keys Choose a strategy that ensures uniqueness across your entire application: | Strategy | Example | When to use | | --- | --- | --- | | UUID v4 | `550e8400-e29b-41d4-a716-446655440000` | General purpose, always unique | | Business ID | `create-customer-partner-ref-123` | When you want natural deduplication | | Composite | `loan-{offer_id}-{installments}-{amount}` | When parameters define uniqueness | ## SDK Behavior The SDKs automatically generate a UUID as the idempotency key for **every `POST` request**, regardless of retry configuration. This ensures that POST requests never create duplicate resources, even in network failure scenarios. ### Automatic mode (default) The SDK generates a unique UUID for each POST call. You don't need to do anything: ```typescript const dinie = new Dinie({ clientId: process.env.DINIE_CLIENT_ID, clientSecret: process.env.DINIE_CLIENT_SECRET, }); // The SDK automatically generates an Idempotency-Key UUID for this request const customer = await dinie.customers.create({ cpf: "123.456.789-00", name: "Joao Silva", email: "joao@example.com", }); ``` ### Explicit mode Pass your own key when you need deterministic deduplication based on business logic. The explicit key overrides the automatically generated one: ```typescript // Use a key based on business identifiers for natural deduplication const customer = await dinie.customers.create( { cpf: "123.456.789-00", name: "Joao Silva", email: "joao@example.com", }, { idempotencyKey: "create-customer-partner-ref-123" } ); ``` Use explicit keys when: - The operation must be deduplicated based on business identifiers (not just per-request) - Different parts of the system may attempt the same operation - You need to correlate retries with the original operation ## Best Practices 1. **Always use idempotency keys** for loan creation (`POST /v3/loans`). This is a financial operation where duplicates are costly. 2. **Use deterministic keys** based on business identifiers when possible. This provides natural deduplication even across separate retry attempts. 3. **Store the idempotency key** alongside your internal record to correlate retries with the original operation. 4. **Do not reuse keys** for different operations, even after the 24-hour window.