가이드

배치 작업 라이프사이클

동기 vs 비동기, 작업 상태, 부분 결과, 그리고 Webhook

배치 엔드포인트(/batch/distill, /batch/extract)는 비동기입니다. 작업은 작은 상태 머신을 따라 이동합니다; 상태를 이해하면 폴링과 Webhook 중 무엇을 선택할지, 부분 실패를 어떻게 다룰지 결정하는 데 도움이 됩니다.

동기 vs 비동기

동기 (/distill, /extract)비동기 (/batch/distill, /batch/extract)
요청당 URL1최대 100
응답HTTP 본문에 전체 결과Job ID; 결과는 별도 조회
지연 시간한 번 요청, 한 번 대기제출 → 폴링 또는 Webhook → 가져오기
적합한 곳실시간 UX, 에이전트 도구, 임시 조회스케줄 작업, RAG ingestion, 모니터링
실패 모드잘못된 URL 하나가 호출 전체를 실패시킴잘못된 URL 하나가 그 행만 실패, 작업은 계속
동시성 비용호출당 한 슬롯배치 전체에 한 슬롯

판단이 안 설 때: 단일 URL → 동기; 여러 URL이거나 급하지 않으면 → 비동기.

작업 상태

Status의미
PENDING작업 수락, 큐에 대기
PROCESSING적어도 하나의 URL이 처리 중
COMPLETED모든 URL이 종료 상태(성공 또는 실패) 도달
FAILED작업 수준의 치명적 오류(드묾 —— 보통 URL 하나만 실패하지 작업 전체가 실패하지는 않음)
CANCELLEDDELETE를 통한 사용자 주도 취소

URL 실패는 작업을 실패시키지 않습니다. results[]의 각 항목이 자체 status를 갖습니다: PENDING, PROCESSING, SUCCEEDED, 또는 FAILED. 모든 행이 종료 상태에 도달하면 작업이 COMPLETED로 이동합니다.

폴링 vs Webhook

작업 크기권장이유
< 10 URL5–10초마다 폴링Webhook 오버헤드가 배선 비용 대비 가치 없음
10–100 URLWebhook5분짜리 작업에서 폴링이 약 60회 왕복을 소모
> 100 URL(여러 배치)Webhook각 배치가 완료 시 한 번씩 발사

페이로드 형태, 서명 검증(HMAC-SHA256), 재시도 동작은 Webhook을 참고하세요.

부분 결과

GET /batch/distill/{id}는 작업이 아직 PROCESSING인 동안에도 동작합니다 —— 그때까지 끝난 만큼 받게 됩니다. 행이 완료되는 대로 스트리밍하는 대시보드에 유용합니다.

import httpx, time

API = "https://openapi.thunderbit.com/openapi/v1"
H = {"Authorization": "Bearer YOUR_API_KEY"}

job = httpx.post(f"{API}/batch/distill", headers=H,
                 json={"urls": urls}).json()
batch_id = job["data"]["id"]

while True:
    body = httpx.get(f"{API}/batch/distill/{batch_id}", headers=H).json()["data"]
    fresh = [r for r in body["results"] if r["status"] == "SUCCEEDED"]
    yield_to_dashboard(fresh)
    if body["status"] in ("COMPLETED", "FAILED", "CANCELLED"):
        break
    time.sleep(5)

취소

DELETE /batch/distill/{id}(또는 /batch/extract/{id})는 PENDING 또는 PROCESSING 작업에서만 동작합니다. 작업이 종료 상태에 진입하면 그대로 머무릅니다. 취소된 작업에서 이미 처리된 URL은 여전히 과금 대상이며, 아직 끝나지 않은 in-flight URL은 과금되지 않습니다.