# Idempotência

> Tente enviar e-mails de novo com segurança usando o cabeçalho Idempotency-Key. Quais endpoints o aceitam, formato e escopo da chave, a janela de reprodução de 24 horas e os erros.

Erros de rede e timeouts deixam você sem saber se um envio foi concluído. Uma chave de idempotência torna seguro tentar o envio de novo: se o Emailit já aceitou uma requisição com a mesma chave, ele retorna a resposta original em vez de enviar o e-mail outra vez. Esta página é a referência do cabeçalho `Idempotency-Key`. Para um passo a passo, consulte [Envios idempotentes](/pt/docs/email-api/idempotency/).

## Endpoints compatíveis

| Endpoint | |
| --- | --- |
| `POST /emails` | [Enviar um e-mail](/pt/docs/api-reference/emails/send/) |
| `POST /emails/{id}/forward` | [Encaminhar um e-mail](/pt/docs/api-reference/emails/forward/) |

Os outros endpoints ignoram o cabeçalho. Criar um domínio, uma chave de API, uma lista de contatos ou um contato já é seguro de repetir: uma segunda requisição com o mesmo nome ou e-mail retorna `409` e o objeto `existing` em vez de criar um duplicado.

## Enviar uma chave

Adicione um cabeçalho `Idempotency-Key` com um valor exclusivo do e-mail que você está enviando, como um UUID ou um ID do seu próprio sistema:

**cURL**

```bash
curl https://api.emailit.com/v2/emails \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-confirmation" \
  -d '{
    "from": "Acme <orders@acme.com>",
    "to": "ada@example.com",
    "subject": "Your order #1042",
    "html": "<p>Thanks for your order.</p>"
  }'
```

**Node.js**

```javascript
const response = await fetch('https://api.emailit.com/v2/emails', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.EMAILIT_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': `order-${order.id}-confirmation`,
  },
  body: JSON.stringify({
    from: 'Acme <orders@acme.com>',
    to: order.email,
    subject: `Your order #${order.id}`,
    html: '<p>Thanks for your order.</p>',
  }),
});
```

**Python**

```python
import os
import requests

response = requests.post(
    "https://api.emailit.com/v2/emails",
    headers={
        "Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}",
        "Idempotency-Key": f"order-{order['id']}-confirmation",
    },
    json={
        "from": "Acme <orders@acme.com>",
        "to": order["email"],
        "subject": f"Your order #{order['id']}",
        "html": "<p>Thanks for your order.</p>",
    },
    timeout=30,
)
```

Gere a chave uma vez por e-mail, antes da primeira tentativa, e envie a mesma chave em todas as novas tentativas desse e-mail.

## Como as chaves funcionam

| Regra | Detalhes |
| --- | --- |
| Formato | De 1 a 256 caracteres. Apenas letras, dígitos, hifens (`-`) e sublinhados (`_`). |
| Escopo | Por workspace. Chaves de workspaces diferentes nunca colidem, mas os dois endpoints compartilham um único namespace, então não reutilize a chave de um envio em um encaminhamento. |
| Validade | A resposta de uma requisição bem-sucedida é guardada por 24 horas depois de concluída. |
| Reproduções | Uma requisição com uma chave guardada retorna a resposta guardada com status `200`. Nenhum e-mail é enviado, nenhum crédito é usado e os limites de envio não são contabilizados. |
| Correspondência | Apenas a chave é comparada, não o corpo da requisição. Uma requisição diferente com uma chave já usada retorna a primeira resposta. |
| Falhas | Se uma requisição falhar com qualquer erro, nada é guardado e a chave é liberada, então você pode corrigir a requisição e tentar de novo com a mesma chave. |
| Concorrência | Enquanto uma requisição com uma chave ainda está em execução, outra requisição com a mesma chave retorna `409`. O bloqueio é liberado quando a primeira requisição termina e expira em no máximo 15 minutos. |

Uma requisição reproduzida ainda passa pela autenticação e pela verificação dos [limites de envio](/pt/docs/api-reference/rate-limits/) por segundo e diário, então pode retornar `401` ou `429`. Os encaminhamentos também contam para o limite de encaminhamentos por hora, mesmo quando a resposta é reproduzida.

## Erros

**400**

```json
{
  "error": "Invalid Idempotency-Key"
}
```

**409**

```json
{
  "error": "Idempotency key in progress",
  "message": "A request with this Idempotency-Key is already being processed. Retry shortly with the same key."
}
```

**503**

```json
{
  "error": "Idempotency unavailable",
  "message": "Unable to process Idempotency-Key right now. Retry the request with the same key."
}
```

| Status | `error` | Causa | O que fazer |
| --- | --- | --- | --- |
| `400` | `Invalid Idempotency-Key` | A chave está vazia, tem mais de 256 caracteres ou contém caracteres além de letras, dígitos, `-` e `_`. | Use um UUID ou outro valor seguro. |
| `409` | `Idempotency key in progress` | Uma requisição com a mesma chave ainda está sendo processada. | Aguarde um segundo e tente de novo com a mesma chave. Você recebe a resposta guardada assim que a primeira requisição terminar. |
| `503` | `Idempotency unavailable` | O Emailit não consegue verificar a chave agora. A requisição não foi processada. | Tente de novo com a mesma chave após um breve intervalo. |

O Emailit nunca envia uma requisição sem a verificação de idempotência: se a chave não puder ser verificada, a requisição falha com `503` em vez de arriscar um duplicado.

## Escolher boas chaves

- Derive a chave daquilo sobre o que você está notificando, como `order-1042-confirmation` ou `password-reset-<token-id>`, para que uma nova tentativa feita por outro worker ou depois de uma reinicialização use a mesma chave.
- Use um UUID novo apenas quando o e-mail não tiver um ID natural, e guarde-o com o job antes da primeira tentativa.
- Não reutilize uma chave para um e-mail diferente em menos de 24 horas. Você receberia a resposta do primeiro e-mail, e o segundo não seria enviado.

## Veja também

  - [Envios idempotentes](/pt/docs/email-api/idempotency/): Um guia para enviar com segurança em novas tentativas.
  - [Limites de requisições](/pt/docs/api-reference/rate-limits/): Aplique backoff e tente de novo, com código de exemplo.

---
Fonte: https://emailit.com/pt/docs/api-reference/idempotency/
