> ## 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.

# 멱등성

> idempotencyKey로 중복 제출을 제거합니다. 단건과 배치는 중복을 다르게 처리합니다.

`idempotencyKey`는 호출자가 선택적으로 넣는 문자열로, 제출을 중복 제거 대상으로 만듭니다. 같은 키로
두 번 보내면 두 번째 제출은 새 작업을 큐에 넣지 않고 첫 제출이 만든 태스크로 연결됩니다.

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

생략하면 **중복 제거가 없습니다**. 제출할 때마다 새 태스크가 생깁니다. 일회성 질의에는 괜찮은
선택이지만, cron이나 재시도하는 워커가 두 번 제출할 수 있는 작업에는 맞지 않습니다.

<Tip>
  좋은 키는 시도가 아니라 작업 자체에서 결정적으로 만들어집니다. 작업 단위를 정의하는 식별자를
  `"{jobId}:{promptId}:{engine}"`처럼 조합하면 재시도가 자연스럽게 같은 키를 재현합니다.
</Tip>

## 단건과 배치는 의도적으로 다릅니다

두 엔드포인트가 달라지는 유일한 지점이고, 자주 헷갈리는 부분입니다.

<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>

단건 엔드포인트는 명시적 생성 의미를 유지합니다. 태스크 생성을 요청했는데 이미 존재한다면
충돌이고, 호출자가 알아야 합니다.

배치 엔드포인트는 **중복을 성공으로 흡수합니다**. 배치 호출자는 보통 재시작 후 작업 전체를 다시
제출하는 워커이고, 키 하나가 이미 큐에 있다는 이유로 500개짜리 배치를 실패로 뒤집으면 멱등 키를
쓰는 의미가 없어집니다. 돌려받는 `results[i].task`는 *기존* 태스크이므로 태스크 매핑은 그대로
유지됩니다.

## 결과를 제출과 짝짓기

서로 독립적인 두 가지 핸들이 있고, 둘 다 필요합니다.

<ResponseField name="results[].index" type="integer">
  입력 배열과 위치상 1:1로 대응합니다. 배치 응답을 보낸 태스크와 맞춰 볼 때 씁니다.
</ResponseField>

<ResponseField name="task.idempotencyKey" type="string">
  보낸 값 그대로 돌아옵니다. 몇 분 뒤 순서 없이 도착하고 원래 배열을 참조하지 않는 *webhook*을
  맞춰 볼 때 씁니다.
</ResponseField>

<Note>
  `idempotencyKey`를 보내지 않았다면 이 필드는 `null`로 반환되지 않고 태스크 객체에서
  **생략**됩니다. 내부적으로는 태스크 자체 uuid를 키로 쓰며, 이는 구조상 고유하므로 중복 제거가
  일어나지 않습니다.
</Note>

## 키 수명

영구 보존되는 태스크의 키는 완료, 실패, 24시간 공개 폴링 기간이 지난 뒤에도 예약된 상태로
남습니다. 폴링이 404를 반환해도 키는 풀리지 않습니다. 한 제출의 전송 재시도에는 같은 키를 쓰고,
별도 실행에는 새 실행 키(예: `:r1` 접미사 추가)를 쓰세요. UUID 형식일 필요는 없습니다. 영구 보존이
켜지기 전에 이미 레거시 이력으로 옮겨진 기록은 소급해서 키를 예약하지 않습니다.
