APIMaster.ai

APIMaster 비동기 작업 웹훅

Seedance, 비디오 및 비동기 이미지 작업에 대한 서명된 완료 및 실패 알림을 재시도, 전송 기록 및 폴링 대체 기능과 함께 수신합니다.

APIMaster 비동기 작업 웹훅

비동기 생성에 대한 기본 알림 메커니즘으로 웹훅을 사용하고, 폴링은 대체 수단으로 유지하세요. APIMaster는 추적된 작업이 완료되거나 실패할 때 서명된 HTTPS POST를 전송합니다. 알림은 생성 제공자와 독립적이며 귀하의 APIMaster 작업 ID를 사용합니다.

지원 모델 및 엔드포인트

Seedance에는 네 가지 모델 모두가 포함됩니다: seedance-2.0, seedance-2.5, seedance-2.0-fast 및 seedance-2.0-mini. POST /v1/videos/generations 또는 호환되는 POST /v1/video/generations를 사용하세요.

비디오 작업 알림은 MiniMax-H3, Kling Omni / Motion Control, Grok Imagine Video 및 Sora도 지원합니다. 지원되는 GPT Image 2 / 2.5 및 Gemini 이미지 워크플로우는 /v1/images/generations/async 또는 지원되는 /v1/images/edits/async를 사용합니다. Midjourney v8.2 / Niji 7은 /v1/midjourney/generations를 사용합니다. 경로 가용성 및 생성 매개변수는 각 모델의 가이드를 따릅니다. 동기식 Seedream 및 Grok 이미지 생성, 채팅 스트리밍 및 Seedance 에셋 검토는 이 생성 웹훅 계약에 포함되지 않습니다.

모델 적격성은 GET /v1/webhook-capabilities?model=seedance-2.0-fast을 확인하세요. 지원되는 비동기 제출 엔드포인트를 사용하세요. 적격성이 모든 이미지 작업이나 모든 모델 별칭이 비동기 생성을 지원한다는 것을 의미하지는 않습니다.

엔드포인트 등록 및 확인

귀하의 API 키를 Authorization: Bearer YOUR_API_KEY에서 사용하세요. API 키는 해당 계정에 속한 엔드포인트와 이벤트를 관리할 수 있습니다. 서버에 안전하게 보관하세요.

curl --fail-with-body "https://apimaster.ai/v1/webhook-endpoints" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-server.example/webhooks/apimaster"}'

응답에는 endpoint.id, endpoint.key_id 및 signing_secret이 포함됩니다. 서명 비밀을 안전하게 저장하세요: 이는 한 번만 반환됩니다. 이는 귀하의 API 키와 별개이며 생성이나 다운로드에 대한 권한을 부여할 수 없습니다. URL은 포트 443에서 공개적으로 접근 가능한 HTTPS 엔드포인트여야 합니다. 개인 주소와 리디렉션은 거부됩니다. 계정당 최대 20개의 엔드포인트가 허용됩니다. URL은 변경 불가능하므로, 목적지를 변경할 때는 새 엔드포인트를 생성하고 확인하세요.

수신기를 구성한 후 소유권을 확인하세요:

curl --fail-with-body -X POST "https://apimaster.ai/v1/webhook-endpoints/whep_example/verify" \
  -H "Authorization: Bearer YOUR_API_KEY"

APIMaster는 data.challenge를 포함하는 서명된 webhook.endpoint_verification 이벤트를 전송합니다. 10초 이내에 {"challenge":"THE_RECEIVED_CHALLENGE"}와 함께 HTTP 200을 반환하세요. 확인되지 않았거나, 일시 중지되었거나, 다른 계정의 엔드포인트를 참조하는 생성 요청은 제출 전에 거부됩니다.

HTTP 요청의 전체 제한 시간은 DNS, 연결 및 TLS 설정을 포함하여 10초입니다. 요청을 보낸 후 8초 이내에 응답 헤더가 도착해야 합니다. 이벤트를 영구 저장한 뒤 즉시 응답하세요.

알림과 함께 작업 제출하기

curl --fail-with-body "https://apimaster.ai/v1/videos/generations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model":"seedance-2.5",
    "prompt":"A paper boat floating on a calm pond, slow camera movement.",
    "duration":4,
    "resolution":"480p",
    "aspect_ratio":"16:9",
    "notifications":{
      "webhook":{
        "endpoint_id":"whep_example",
        "events":["task.completed","task.failed"]
      }
    },
    "client_reference_id":"order_123"
  }'

네 가지 Seedance ID 중 하나로 모델 ID를 교체하면서 각 모델 자체의 지원 매개변수를 유지하세요. 일반적인 생성 응답에서 작업 ID를 저장하세요. client_reference_id은 최대 128바이트의 선택적 비즈니스 참조입니다. 이는 제출 idempotency 키가 아닙니다. notifications를 레거시 webhook 또는 callback_url 제공자 매개변수와 결합하지 마세요.

지원되는 멀티파트 이미지 편집의 경우, notifications을 JSON 문자열 폼 필드로, client_reference_id을 별도의 폼 필드로 전송하세요:

curl --fail-with-body "https://apimaster.ai/v1/images/edits/async" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "model=gpt-image-2" \
  -F "prompt=Turn the reference into a watercolor illustration" \
  -F "image=@reference.png" \
  -F 'notifications={"webhook":{"endpoint_id":"whep_example","events":["task.completed","task.failed"]}}' \
  -F "client_reference_id=image_order_123"

이 버전에는 계정 전체의 기본 엔드포인트가 없습니다: 각 작업 요청에서 엔드포인트를 참조하세요. 웹훅은 귀하의 제출 응답보다 먼저 도착할 수 있습니다. 애플리케이션이 반환된 작업 ID를 아직 저장하지 않았더라도 이를 지속적으로 보관하세요. 일부 이미지 비동기 워크플로우는 동기식 업스트림 생성을 래핑하므로, 제출 자체는 여전히 시간이 걸릴 수 있습니다.

성공 및 실패 페이로드

성공 알림에는 공개 작업 ID와 인증된 비디오 링크가 포함됩니다:

{
  "id":"evt_example",
  "type":"task.completed",
  "api_version":"2026-10-03",
  "created_at":1791014400,
  "data":{
    "task_id":"task_example",
    "model":"seedance-2.5",
    "kind":"video",
    "status":"completed",
    "client_reference_id":"order_123",
    "completed_at":1791014400,
    "task_url":"https://apimaster.ai/v1/videos/task_example",
    "result":{
      "outputs":[{
        "output_id":"0",
        "type":"video",
        "url":"https://apimaster.ai/v1/videos/task_example/content",
        "authentication":"bearer",
        "expires_at":null
      }]
    },
    "error":null
  }
}

실패는 동일한 봉투에 type: "task.failed", data.status: "failed", data.result: null 및 오류 객체를 포함하여 사용합니다:

{
  "code":"generation_failed",
  "message":"The generation task failed. Query the task for details."
}

제공자가 확인한 실패와 게이트웨이 작업 시간 초과 모두 실패 이벤트를 생성할 수 있습니다. 작업이 수락되기 전에 거부된 생성 요청은 작업 이벤트를 생성하지 않습니다. 알림 전송 실패는 생성 상태를 변경하거나 생성을 다시 실행하지 않습니다. 이벤트는 청구 조정이 완료되었음을 확인하지 않습니다.

이미지의 경우, kind는 image이며, outputs은 사용 가능한 모든 이미지 출력을 포함합니다. Midjourney 하위 작업 이벤트는 batch_id을 포함합니다. 또한 batch.completed에 구독하여 모든 하위 작업이 완료된 후 한 번의 배치 요약을 받을 수 있습니다. 그 상태는 completed, partial_failure 또는 failed이며, data.summary에 개수가 표시됩니다. 배치 완료가 항상 모든 하위 작업이 성공했음을 의미하지는 않습니다.

작업 계정에 속하는 API 키로 출력 URL을 다운로드하세요. 생성된 미디어를 즉시 저장하세요. expires_at: null는 보장된 만료 시간이 제공되지 않는다는 의미이며, 영구 저장소가 아닙니다. 나중에 다운로드 시 HTTP 410을 반환할 수 있습니다. 이벤트를 재생해도 미디어 가용성이 연장되지 않습니다.

콜백 인증 및 즉시 확인

각 POST 요청은 다음을 포함합니다:

X-APIMaster-Event-ID: evt_example
X-APIMaster-Delivery-ID: dlv_example
X-APIMaster-Timestamp: 1791014400
X-APIMaster-Signature: v1=<hex-hmac>,kid=<key-id>

타임스탬프, 리터럴 점(.) 및 원시 요청 본문 바이트에 대해 엔드포인트의 서명 비밀키를 사용하여 HMAC-SHA256을 검증하세요. 상수 시간 비교를 사용하고, 최대 5분의 시계 오차를 허용하며, Event-ID 헤더가 본문 ID와 일치하는지 확인하세요. 재시도는 동일한 이벤트 ID와 본문을 유지하지만 새로운 전송 ID, 타임스탬프 및 서명을 받습니다.

다음 Python 수신기는 Flask와 SQLite를 사용합니다. 이벤트를 확인하기 전에 원자적으로 저장합니다. 애플리케이션 워커는 저장된 행을 소비하고, 파일을 다운로드하며, 비즈니스 로직을 별도로 실행해야 합니다.

import hashlib, hmac, json, os, sqlite3, time
from flask import Flask, request, jsonify, abort

app = Flask(__name__)
# During key rotation, configure both active and previous kid/secret pairs.
SECRETS = json.loads(os.environ["APIMASTER_WEBHOOK_SECRETS_JSON"])
DB_PATH = os.environ.get("WEBHOOK_DB_PATH", "webhook-events.sqlite3")
with sqlite3.connect(DB_PATH) as db:
    db.execute("CREATE TABLE IF NOT EXISTS events (id TEXT PRIMARY KEY, body BLOB NOT NULL)")

@app.post("/webhooks/apimaster")
def receive():
    raw = request.get_data()
    try:
        timestamp = request.headers["X-APIMaster-Timestamp"]
        if abs(time.time() - int(timestamp)) > 300:
            abort(401)
        fields = dict(part.split("=", 1) for part in
                      request.headers["X-APIMaster-Signature"].split(","))
        secret = SECRETS[fields["kid"]]
        expected = hmac.new(secret.encode(), timestamp.encode() + b"." + raw,
                            hashlib.sha256).hexdigest()
        if not hmac.compare_digest(expected, fields["v1"]):
            abort(401)
        event = json.loads(raw)
        if event["id"] != request.headers["X-APIMaster-Event-ID"]:
            abort(401)
    except (KeyError, ValueError, TypeError):
        abort(401)
    if event["type"] == "webhook.endpoint_verification":
        return jsonify(challenge=event["data"]["challenge"])
    with sqlite3.connect(DB_PATH) as db:
        db.execute("INSERT OR IGNORE INTO events(id, body) VALUES (?, ?)",
                   (event["id"], raw))
    return "", 204

생성 이벤트에 대해 10초 이내에 2xx 상태를 반환하세요. 미디어 다운로드를 기다리지 않고 내구성 있는 저장 후 확인하세요. 전송은 최소 한 번 이상입니다: 확인 응답이 손실되는 경우 특히 중복 이벤트가 가능하므로, id로 중복 제거를 수행하세요. 작업 간 순서 보장은 없습니다.

재시도, 전송 기록 및 재생

APIMaster는 이벤트 생성 시점부터 최대 72시간 동안 네트워크 장애, 확인 응답 시간 초과 및 비-2xx 응답에 대해 재시도합니다. 초기 지연은 1, 2, 5, 15, 30분, 그 다음 1, 2, 4, 8시간, 이후 12시간 간격으로 진행되며 최대 20% 지터가 적용됩니다. 재시도 창 내에서 429/503 응답에 대한 유효한 Retry-After이 존중됩니다. 리디렉션은 따르지 않습니다. HTTP 410은 엔드포인트를 일시 중지시키며, 다른 4xx 응답은 구성 수정을 허용하기 위해 재시도됩니다.

curl --fail-with-body "https://apimaster.ai/v1/webhook-events?task_id=task_example" \
  -H "Authorization: Bearer YOUR_API_KEY"

curl --fail-with-body "https://apimaster.ai/v1/webhook-events/evt_example/deliveries" \
  -H "Authorization: Bearer YOUR_API_KEY"

curl --fail-with-body -X POST "https://apimaster.ai/v1/webhook-events/evt_example/redeliver" \
  -H "Authorization: Bearer YOUR_API_KEY"

상태에는 pending, in_flight, retrying, delivered, paused 및 exhausted가 포함됩니다. 이벤트 및 시도 기록은 30일 동안 보관됩니다. 재생은 원본 이벤트 ID와 페이로드를 보존하고 새로운 72시간 전송 창을 엽니다; 미디어를 재생성하거나 다시 청구하지 않습니다. UTC 기준 하루당 이벤트별 최대 5회의 수동 재생이 허용됩니다. 현재 전송을 위해 임대된 이벤트는 해당 시도가 종료되거나 임대가 만료될 때까지 재생할 수 없습니다.

PATCH /v1/webhook-endpoints/{id} 및 {"enabled":false} 또는 {"enabled":true}로 엔드포인트를 일시 중지하거나 재개하세요. 재개는 원래 마감 기한이 지나지 않은 일시 중지된 이벤트를 계속합니다. POST /v1/webhook-endpoints/{id}/rotate-secret로 비밀키를 순환하세요; 새로운 비밀키와 kid를 저장하고, 반환된 24시간 전환 기간 동안 이전 쌍을 유지하세요.

폴링 폴백

수신된 최종 이벤트가 없는 작업의 경우, /v1/videos/{task_id} 또는 모델 문서화된 이미지 작업 쿼리를 60~120초마다 조회하세요. 작업 API를 진실의 원천으로 사용하고, 생성이 완료되었지만 알림이 누락된 경우 전송 기록을 확인하세요. 웹훅 누락은 청구 가능한 생성 요청을 재제출하는 이유가 아닙니다. 지속적인 엔드포인트 다운타임은 자동 재시도를 소진시킬 수 있습니다; 수신기를 복원하고 보관된 이벤트를 재생하세요.