재시도 중복 방지 키 V5 (beta)

연결이 끊겨 다시 보내도 수집이 두 번 돌거나 크레딧이 두 번 빠지지 않게 합니다.

수집 시작 요청의 응답이 오는 도중 연결이 끊기면 프로그램은 실패로 보고 같은 요청을 다시 보냅니다. 이때 같은 수집이 두 번 돌고 크레딧이 두 번 빠질 수 있습니다. Idempotency-Key 헤더로 "이 요청은 아까 그 요청의 재전송"임을 알리면 서버가 새로 시작하지 않고 첫 응답을 돌려줍니다.

요청 한 번마다 새 키

키는 1~255자 문자열입니다. UUID 를 권장합니다($(uuidgen)). 응답은 (계정, 키) 짝으로 24시간 보관합니다.

키를 고정값으로 쓰지 마세요. 키는 요청 한 번(같은 수집 의도)마다 새로 만들고, 연결이 끊겨 같은 요청을 다시 보낼 때만 같은 키를 씁니다. 모든 요청에 같은 문자열을 넣으면 두 번째 수집부터 시작되지 않고 첫 응답이 되풀이되거나(같은 내용) 422 IDEMPOTENCY_KEY_REUSED(다른 내용)를 받습니다.

필수인 곳 6개

무엇을 새로 만들거나 크레딧을 쓰는 POST 는 키가 필수입니다. 없으면 400 IDEMPOTENCY_KEY_REQUIRED입니다.

그 밖의 요청(설정·주기 고치기, 지우기, 조회, preview·copy_settings·cancel·notifications/test)은 두 번 보내도 결과가 같거나 무엇도 만들지 않아 필수가 아닙니다. 보내면 같은 규칙으로 지킵니다. 가이드의 쓰기 예시에는 모두 키를 넣어 두었습니다.

경로이유
POST /v5/api/bots/{bot_id}/collections수집 시작 — 크레딧
POST /v5/api/plans/{plan_id}/run주기 지금 돌리기 — 크레딧
POST /v5/api/collections/bulk여러 봇 수집 — 크레딧
POST /v5/api/collections/bulk_jobs대량 수집 접수 — 두 번이면 접수가 둘, 크레딧
POST /v5/api/bots/{bot_id}/plans주기 만들기 — 두 번이면 주기가 둘
POST /v5/api/datasets/{dataset_id}/retry재수집 — 수집을 다시 돌림
요청 예시
curl -X POST 'https://www.hashscraper.com/v5/api/bots/8f3a7c1e9b5d24f6/collections' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
  "inputs": {
    "param1": "sneakers"
  }
}'
응답 예시 400
{
  "result": "error",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "code": "IDEMPOTENCY_KEY_REQUIRED",
  "message": "Idempotency-Key header is required.",
  "elapsed_sec": 0.0011,
  "details": {
    "hint": "Send a unique `Idempotency-Key` header (1-255 characters, e.g. a UUID) per request; reuse it only to retry the same request."
  }
}

동작

경우응답
처음 보는 키그대로 처리하고 응답을 24시간 보관합니다.
같은 키 · 같은 내용(경로·본문)으로 다시 옴새로 시작하지 않고 보관한 첫 응답을 그대로 돌려줍니다. 헤더 Idempotent-Replayed: true.
같은 키인데 내용이 다름422 IDEMPOTENCY_KEY_REUSED — 키를 고정값으로 쓰는 실수를 알립니다.
첫 요청이 아직 처리 중409 REQUEST_IN_PROGRESS — 잠시 뒤 같은 키로 다시 보내세요.
첫 요청이 4xx 로 끝남(입력 오류·크레딧 부족 등)오류 응답도 보관해 같은 키에 같은 오류를 돌려줍니다. 입력을 고치거나 크레딧을 충전한 뒤에는 새 키로 보내세요.
첫 요청이 5xx(서버 오류)로 끝남보관하지 않습니다. 같은 키로 다시 보내면 새로 처리합니다. 단 수집을 이미 맡긴 뒤에 난 오류라면 그 응답을 보관해 수집을 또 시작하지 않습니다.
응답 예시 200
{
  "result": "success",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "elapsed_sec": 0.0123,
  "data": {
    "id": 239758028,
    "bot": {
      "id": "8f3a7c1e9b5d24f6",
      "name": "Sample shopping bot"
    },
    "status": "running",
    "data_count": 0,
    "union": false,
    "trigger": "api",
    "credits_used": 0,
    "created_at": "2026-10-04T09:00:02+09:00",
    "updated_at": "2026-10-04T09:00:02+09:00",
    "plan": null,
    "inputs": {
      "param1": {
        "name": "Keyword",
        "value": "sneakers"
      }
    },
    "started_at": "2026-10-04T09:00:02+09:00",
    "elapsed_sec": 3,
    "saved_to_settings": true,
    "plans_affected": []
  }
}
응답 예시 422
{
  "result": "error",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "code": "IDEMPOTENCY_KEY_REUSED",
  "message": "Idempotency-Key was already used with a different request.",
  "elapsed_sec": 0.0011
}
응답 예시 409
{
  "result": "error",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "code": "REQUEST_IN_PROGRESS",
  "message": "The first request with this Idempotency-Key is still in progress.",
  "elapsed_sec": 0.0011
}

다시 보내는 코드 예시

키는 함수 안에서 한 번만 만들고, 재시도 반복문 안에서는 그 키를 그대로 씁니다.

Python 예시
import time
import uuid
import requests

BASE = "https://www.hashscraper.com/v5/api"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}


def start_collection(bot_id, inputs):
    # 이 수집 요청 한 번에 쓸 키 — 요청마다 새로 만들고, 재시도에서만 같은 키를 다시 쓴다
    key = str(uuid.uuid4())
    for attempt in range(5):
        try:
            res = requests.post(
                f"{BASE}/bots/{bot_id}/collections",
                headers={**HEADERS, "Idempotency-Key": key},
                json={"inputs": inputs},
                timeout=30,
            )
        except requests.exceptions.RequestException:
            time.sleep(2 ** attempt)  # 응답을 못 받았다 — 같은 키로 다시 보낸다
            continue
        body = res.json()
        if res.status_code == 409 and body.get("code") == "REQUEST_IN_PROGRESS":
            time.sleep(2)  # 첫 요청이 아직 처리 중 — 잠시 뒤 같은 키로
            continue
        return body
    raise RuntimeError("could not confirm the request")

함께 보면 좋은 가이드