# Idempotência

Falhas de rede, timeouts e retries são uma realidade de sistemas distribuídos. A API Dinie suporta **chaves de idempotência** para que você possa reenviar requisições `POST` com segurança sem criar recursos duplicados acidentalmente.

## O que é Idempotência?

Uma operação é idempotente se executá-la múltiplas vezes produz o mesmo resultado que executá-la uma única vez. Por exemplo, `GET` e `DELETE` são naturalmente idempotentes -- buscar ou deletar o mesmo recurso duas vezes tem o mesmo efeito. Mas `POST` (criação) não é naturalmente idempotente -- enviar duas vezes pode criar dois recursos.

O header `Idempotency-Key` torna requisições `POST` idempotentes ao associar a requisição a uma chave única. Se a mesma chave for enviada novamente, a API retorna a resposta em cache da primeira requisição em vez de processar uma nova.

## Usando o Header Idempotency-Key

Inclua um header `Idempotency-Key` em requisições `POST` que criam recursos:

```typescript Node.js
const customer = await dinie.customers.create(
  {
    cpf: "123.456.789-00",
    external_id: "partner-ref-123",
    email: "joao@example.com",
    phone: "+5511999999999",
    cnpj: "12.345.678/0001-90",
  },
  { idempotencyKey: "partner-onboard-joao-2026-03-04" }
);
```

```ruby Ruby
customer = dinie.customers.create(
  cpf: "123.456.789-00",
  external_id: "partner-ref-123",
  email: "joao@example.com",
  phone: "+5511999999999",
  cnpj: "12.345.678/0001-90",
  idempotency_key: "partner-onboard-joao-2026-03-04"
)
```

```python Python
customer = dinie.customers.create(
    cpf="123.456.789-00",
    external_id="partner-ref-123",
    email="joao@example.com",
    phone="+5511999999999",
    cnpj="12.345.678/0001-90",
    idempotency_key="partner-onboard-joao-2026-03-04",
)
```

```bash cURL
curl -X POST https://api-dev.dinietech.io/api/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",
    "external_id": "partner-ref-123",
    "email": "joao@example.com",
    "phone": "+5511999999999",
    "cnpj": "12.345.678/0001-90"
  }'
```

## Operações Suportadas

Chaves de idempotência são suportadas em todas as requisições `POST` que criam recursos:

| Endpoint | Descrição |
|  --- | --- |
| `POST /customers` | Criar um cliente |
| `POST /customers/{id}/kyc-attachments` | Upload de documento |
| `POST /credit-offers/{id}/simulations` | Executar uma simulação |
| `POST /loans` | Criar um empréstimo |
| `POST /auth/credentials` | Criar uma credencial de API |
| `POST /webhooks/endpoints` | Criar um endpoint de webhook |
| `POST /webhooks/endpoints/{id}/rotate-secret` | Rotacionar secret do webhook |


> **Info:** `GET`, `PATCH` e `DELETE` são naturalmente idempotentes e não requerem o header. Você pode reenviar essas requisições com segurança sem nenhum tratamento especial.


## Como Funciona

1. Você envia uma requisição `POST` com um header `Idempotency-Key`
2. A API processa a requisição e armazena a resposta em cache, indexada por `(partner_id, idempotency_key)`
3. Se você enviar a mesma chave novamente dentro de 24 horas, a API retorna a resposta em cache sem reprocessar
4. Após 24 horas, a resposta em cache expira e a chave pode ser reutilizada


## Janela de Cache

Chaves de idempotência ficam em cache por **24 horas**. Após esse período:

- A chave expira e a resposta em cache é descartada
- Enviar a mesma chave vai processar uma nova requisição
- Se precisar reenviar após 24 horas, use uma nova chave de idempotência


## Lidando com Colisões

Se você enviar a mesma chave de idempotência com um **corpo de requisição diferente**, a API retorna a resposta em cache da primeira requisição. Ela não compara os corpos das requisições -- a chave sozinha determina a resposta em cache.

> **Warning:** Sempre use chaves de idempotência únicas para operações diferentes. Um bom padrão é combinar um prefixo semântico com um identificador único:
- `create-customer-{external_id}`
- `create-loan-{offer_id}-{timestamp}`
- `upload-doc-{customer_id}-{doc_type}`



## Gerando Chaves

Escolha uma estratégia que garanta unicidade em toda a sua aplicação:

| Estratégia | Exemplo | Quando usar |
|  --- | --- | --- |
| UUID v4 | `550e8400-e29b-41d4-a716-446655440000` | Uso geral, sempre único |
| ID de negócio | `create-customer-partner-ref-123` | Quando você quer deduplicação natural |
| Composta | `loan-{offer_id}-{installments}-{amount}` | Quando os parâmetros definem a unicidade |


## Comportamento dos SDKs

Os SDKs geram automaticamente um UUID como chave de idempotência para **toda requisição `POST`**, independentemente da configuração de retries. Isso garante que requisições POST nunca criem recursos duplicados, mesmo em cenários de falha de rede.

### Modo automático (padrão)

O SDK gera um UUID único para cada chamada POST. Você não precisa fazer nada:

```typescript
const dinie = new Dinie({
  clientId: process.env.DINIE_CLIENT_ID,
  clientSecret: process.env.DINIE_CLIENT_SECRET,
});

// O SDK gera automaticamente um Idempotency-Key UUID para esta requisição
const customer = await dinie.customers.create({
  cpf: "123.456.789-00",
  external_id: "partner-ref-123",
  email: "joao@example.com",
  phone: "+5511999999999",
  cnpj: "12.345.678/0001-90",
});
```

### Modo explícito

Passe sua própria chave quando precisar de deduplicação determinística baseada na lógica de negócio. A chave explícita sobrescreve a gerada automaticamente:

```typescript
// Use uma chave baseada em identificadores de negócio para deduplicação natural
const customer = await dinie.customers.create(
  {
    cpf: "123.456.789-00",
    external_id: "partner-ref-123",
    email: "joao@example.com",
    phone: "+5511999999999",
    cnpj: "12.345.678/0001-90",
  },
  { idempotencyKey: "create-customer-partner-ref-123" }
);
```

Use chaves explícitas quando:

- A operação deve ser deduplicada com base em identificadores de negócio (não apenas por requisição)
- Diferentes partes do sistema podem tentar a mesma operação
- Você precisa correlacionar retries com a operação original


## Boas Práticas

1. **Sempre use chaves de idempotência** para criação de empréstimos (`POST /loans`). Esta é uma operação financeira onde duplicatas são custosas.
2. **Use chaves determinísticas** baseadas em identificadores de negócio quando possível. Isso proporciona deduplicação natural mesmo entre tentativas de retry separadas.
3. **Armazene a chave de idempotência** junto com seu registro interno para correlacionar retries com a operação original.
4. **Não reutilize chaves** para operações diferentes, mesmo após a janela de 24 horas.