재시도 중복 방지 키 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")