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

# Idempotência

> Deduplique envios com idempotencyKey e saiba que o envio individual e o lote tratam duplicatas de formas diferentes.

`idempotencyKey` é uma string opcional fornecida por quem chama que torna um envio deduplicável. Envie a mesma chave
duas vezes e o segundo envio aponta para a tarefa criada pelo primeiro, sem enfileirar trabalho novo.

```json theme={null}
{
  "taskType": "GEMINI",
  "idempotencyKey": "job-42:prompt-7:gemini",
  "payload": { "prompt": "best wireless earbuds 2026" }
}
```

Sem ela, **não há deduplicação**: cada envio cria uma tarefa nova. É uma escolha válida para consultas avulsas e a
escolha errada para qualquer coisa que um cron ou um worker com novas tentativas possa enviar duas vezes.

<Tip>
  Uma boa chave é derivada de forma determinística do próprio trabalho, não da tentativa. Ao compor os identificadores
  que definem a unidade de trabalho, como `"{jobId}:{promptId}:{engine}"`, uma nova tentativa reproduz naturalmente a mesma chave.
</Tip>

## Individual e lote diferem de propósito

É o único ponto em que os dois endpoints divergem, e costuma confundir.

<CodeGroup>
  ```json Single — duplicate is an error theme={null}
  POST /v1/async/task
  → 409 Conflict

  {
    "success": false,
    "error": {
      "code": "RESOURCE_ALREADY_EXISTS",
      "message": "Task already exists.",
      "timestamp": "2026-07-09T04:12:00.000Z"
    }
  }
  ```

  ```json Batch — duplicate is a success theme={null}
  POST /v1/async/task/batch
  → 200 OK

  {
    "success": true,
    "summary": { "total": 1, "succeeded": 1, "failed": 0 },
    "results": [
      {
        "success": true,
        "index": 0,
        "task": { "id": "8f2c1e40-...", "status": "QUEUED", "...": "..." }
      }
    ]
  }
  ```
</CodeGroup>

O endpoint individual mantém a semântica de criação explícita: você pediu para criar uma tarefa, a tarefa já existe,
isso é um conflito e você precisa saber.

O endpoint de lote **absorve duplicatas como sucesso**. Quem chama costuma ser um worker que reenvia um job inteiro
depois de reiniciar, e marcar como falho um lote de 500 itens porque uma chave já estava na fila anularia o propósito
das chaves de idempotência. O `results[i].task` devolvido é a tarefa *existente*, então seu mapeamento de tarefas
continua funcionando.

## Relacionando resultados aos envios

São dois identificadores independentes, e você quer os dois:

<ResponseField name="results[].index" type="integer">
  Corresponde 1:1 por posição ao seu array de entrada. Use-o para relacionar a resposta do lote às tarefas enviadas.
</ResponseField>

<ResponseField name="task.idempotencyKey" type="string">
  Devolvida sem alterações. Use-a para relacionar o *webhook*, que chega minutos depois, fora de ordem e sem
  referência ao seu array original.
</ResponseField>

<Note>
  Se você não informou `idempotencyKey`, o campo é **omitido** do objeto da tarefa em vez de retornar `null`.
  Internamente a tarefa usa seu próprio uuid como chave, que é único por construção e por isso nunca deduplica.
</Note>

## Vida útil da chave

As chaves de tarefas com retenção permanente continuam reservadas depois da conclusão, da falha e da janela pública de
polling de 24 horas. Um 404 no polling não libera a chave. Use a mesma chave nas novas tentativas de transporte de um
envio e uma nova chave de execução (por exemplo, com o sufixo `:r1`) para uma execução separada. O formato UUID não é
obrigatório. Registros que já tinham sido movidos para o histórico legado antes de a retenção permanente ser ativada
não reservam chaves retroativamente.
