APIMaster.ai

APIMaster Webhook Tugas Asinkron

Terima notifikasi penyelesaian dan kegagalan yang ditandatangani untuk Seedance, tugas video dan gambar asinkron, dengan percobaan ulang, riwayat pengiriman, dan fallback polling.

Webhook tugas asinkron APIMaster

Gunakan webhook sebagai mekanisme notifikasi utama untuk generasi asinkron, dan pertahankan polling sebagai fallback. APIMaster mengirimkan POST HTTPS yang ditandatangani ketika tugas yang dilacak selesai atau gagal. Notifikasi bersifat independen dari penyedia generasi dan menggunakan ID tugas APIMaster Anda.

Model dan endpoint yang didukung

Seedance mencakup keempat model: seedance-2.0, seedance-2.5, seedance-2.0-fast, dan seedance-2.0-mini. Gunakan POST /v1/videos/generations atau POST /v1/video/generations yang kompatibel.

Notifikasi tugas video juga mendukung MiniMax-H3, Kling Omni / Motion Control, Grok Imagine Video, dan Sora. Alur kerja gambar GPT Image 2 / 2.5 dan Gemini yang didukung menggunakan /v1/images/generations/async atau /v1/images/edits/async yang didukung; Midjourney v8.2 / Niji 7 menggunakan /v1/midjourney/generations. Ketersediaan rute dan parameter generasi tetap mengikuti panduan masing-masing model. Generasi gambar Seedream dan Grok sinkron, streaming chat, dan tinjauan aset Seedance bukan bagian dari kontrak webhook generasi ini.

Periksa GET /v1/webhook-capabilities?model=seedance-2.0-fast untuk kelayakan model. Gunakan endpoint pengiriman asinkron yang didukung; kelayakan tidak berarti setiap operasi gambar atau setiap alias model mendukung generasi asinkron.

Daftarkan dan verifikasi sebuah endpoint

Gunakan kunci API Anda di Authorization: Bearer YOUR_API_KEY. Sebuah kunci API dapat mengelola endpoint dan peristiwa yang termasuk dalam akunnya. Simpan di server Anda.

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"}'

Respons berisi endpoint.id, endpoint.key_id, dan signing_secret. Simpan rahasia penandatanganan dengan aman: ini hanya dikembalikan sekali. Ini terpisah dari kunci API Anda dan tidak dapat mengotorisasi generasi atau unduhan. URL harus berupa endpoint HTTPS yang dapat dijangkau publik pada port 443. Alamat pribadi dan pengalihan ditolak. Hingga 20 endpoint diizinkan per akun; URL tidak dapat diubah, jadi buat dan verifikasi endpoint baru saat mengubah tujuan.

Setelah mengonfigurasi penerima Anda, verifikasi kepemilikan:

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

APIMaster mengirimkan peristiwa webhook.endpoint_verification yang ditandatangani berisi data.challenge. Kembalikan HTTP 200 dengan {"challenge":"THE_RECEIVED_CHALLENGE"} dalam 10 detik. Permintaan generasi yang merujuk ke endpoint yang belum diverifikasi, dijeda, atau milik akun lain akan ditolak sebelum pengiriman.

Batas waktu total permintaan HTTP adalah 10 detik, termasuk DNS, koneksi, dan TLS. Header respons harus diterima dalam 8 detik setelah permintaan dikirim. Simpan peristiwa secara persisten lalu segera kirim konfirmasi.

Kirim tugas dengan notifikasi

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"
  }'

Ganti ID model dengan salah satu dari empat ID Seedance sambil tetap mempertahankan parameter yang didukungnya sendiri. Simpan ID tugas dari respons pembuatan normal. client_reference_id adalah referensi bisnis opsional dengan panjang maksimal 128 byte; ini bukan kunci idempotensi pengiriman. Jangan gabungkan notifications dengan parameter penyedia lama webhook atau callback_url.

Untuk pengeditan gambar multipart yang didukung, kirim notifications sebagai bidang formulir string JSON dan client_reference_id sebagai bidang formulir terpisah:

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"

Tidak ada endpoint default seluruh akun dalam versi ini: rujuk sebuah endpoint di setiap permintaan tugas. Webhook dapat tiba sebelum respons pengiriman Anda. Simpan bahkan jika aplikasi Anda belum menyimpan ID tugas yang dikembalikan. Beberapa alur kerja gambar asinkron membungkus generasi hulu sinkron, sehingga pengiriman itu sendiri masih dapat memakan waktu.

Payload keberhasilan dan kegagalan

Notifikasi keberhasilan berisi ID tugas publik dan tautan video yang diautentikasi:

{
  "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
  }
}

Kegagalan menggunakan amplop yang sama dengan type: "task.failed", data.status: "failed", data.result: null, dan objek kesalahan:

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

Baik kegagalan yang dikonfirmasi penyedia maupun waktu tunggu tugas gateway dapat menghasilkan peristiwa kegagalan. Permintaan pembuatan yang ditolak sebelum tugas diterima tidak menghasilkan peristiwa tugas. Kegagalan pengiriman notifikasi tidak mengubah status generasi atau menjalankan ulang generasi. Peristiwa tidak mengonfirmasi bahwa rekonsiliasi penagihan telah selesai.

Untuk gambar, kind adalah image dan outputs berisi semua keluaran gambar yang tersedia. Peristiwa tugas anak Midjourney mencakup batch_id; Anda juga dapat berlangganan batch.completed untuk menerima satu ringkasan batch setelah semua anak selesai. Statusnya adalah completed, partial_failure, atau failed, dengan jumlah di data.summary. Penyelesaian batch tidak selalu berarti setiap anak berhasil.

Unduh URL keluaran dengan kunci API milik akun tugas tersebut. Simpan media yang dihasilkan segera. expires_at: null berarti tidak ada waktu kedaluwarsa yang dijamin disediakan, bukan penyimpanan permanen; unduhan nanti dapat mengembalikan HTTP 410. Memutar ulang peristiwa tidak memperpanjang ketersediaan media.

Autentikasi callback dan konfirmasi segera

Setiap POST membawa:

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>

Verifikasi HMAC-SHA256 atas timestamp, sebuah titik literal dan byte tubuh permintaan mentah menggunakan rahasia tanda tangan endpoint. Gunakan perbandingan waktu-konstan, izinkan maksimal lima menit selisih waktu, dan periksa bahwa header Event-ID cocok dengan ID di tubuh. Percobaan ulang mempertahankan ID event dan tubuh yang sama tetapi menerima ID pengiriman, timestamp, dan tanda tangan baru.

Penerima Python berikut menggunakan Flask dan SQLite. Ia menyimpan event secara atomik sebelum mengonfirmasinya. Worker aplikasi Anda harus mengonsumsi baris yang disimpan, mengunduh file, dan menjalankan logika bisnis secara terpisah.

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

Kembalikan status 2xx apa pun dalam 10 detik untuk event generasi. Konfirmasi setelah penyimpanan tahan lama, tanpa menunggu unduhan media. Pengiriman adalah setidaknya sekali: duplikat event dimungkinkan, terutama jika konfirmasi hilang, jadi deduplikasi berdasarkan id. Tidak ada jaminan urutan antar tugas.

Percobaan ulang, riwayat pengiriman, dan pemutaran ulang

APIMaster mencoba ulang kegagalan jaringan, waktu habis konfirmasi, dan respons non-2xx hingga 72 jam dari pembuatan event. Penundaan awal adalah 1, 2, 5, 15 dan 30 menit, lalu 1, 2, 4 dan 8 jam, diikuti interval 12 jam, dengan jitter hingga 20%. Header Retry-After yang valid pada 429/503 dihormati dalam jendela percobaan ulang. Pengalihan tidak diikuti. HTTP 410 menjeda endpoint; respons 4xx lainnya dicoba ulang untuk mengizinkan perbaikan konfigurasi.

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"

Status mencakup pending, in_flight, retrying, delivered, paused dan exhausted. Catatan event dan percobaan disimpan selama 30 hari. Pemutaran ulang mempertahankan ID event dan payload asli dan membuka jendela pengiriman baru 72 jam; ia tidak menghasilkan ulang media atau menagih lagi. Hingga lima pemutaran ulang manual per event per hari UTC diizinkan. Event yang saat ini disewa untuk pengiriman tidak dapat diputar ulang hingga percobaan itu berakhir atau sewaannya habis.

Jeda atau lanjutkan endpoint dengan PATCH /v1/webhook-endpoints/{id} dan {"enabled":false} atau {"enabled":true}. Melanjutkan akan melanjutkan event yang dijeda yang batas waktu aslinya belum lewat. Putar rahasia dengan POST /v1/webhook-endpoints/{id}/rotate-secret; simpan rahasia dan kid baru, dan pertahankan pasangan sebelumnya untuk periode transisi 24 jam yang dikembalikan.

Cadangan polling

Untuk tugas tanpa event terminal yang diterima, kueri /v1/videos/{task_id} atau kueri tugas-gambar yang didokumentasikan model setiap 60–120 detik. Gunakan API tugas sebagai sumber kebenaran dan periksa riwayat pengiriman jika generasi telah selesai tetapi notifikasi hilang. Webhook yang hilang bukan alasan untuk mengirim ulang permintaan generasi yang dapat ditagih. Downtime endpoint yang persisten dapat menghabiskan percobaan ulang otomatis; pulihkan penerima dan putar ulang event yang disimpan.