Webhooks

Receive HTTP POST callbacks when your job status changes. Configure globally in account settings or per-request via the webhook_url parameter.

Configuration

Add webhook_url to any generation or analysis request:
{
  "prompt": "a sunset over mountains",
  "model": "Flux1schnell",
  "width": 768,
  "height": 768,
  "steps": 4,
  "guidance": 1,
  "seed": -1,
  "webhook_url": "https://your-server.com/webhooks/modelbeam"
}
Requirements: The webhook URL must use HTTPS.

Security Headers

Every webhook request includes these headers for verification:
HeaderDescription
X-ModelBeam-SignatureHMAC-SHA256 signature: sha256=<hex>
X-ModelBeam-TimestampUnix timestamp when the webhook was sent
X-ModelBeam-EventEvent type: job.processing, job.completed, or job.failed
X-ModelBeam-Delivery-IdUnique delivery UUID (use for idempotency)

Signature Verification

Verify webhook authenticity by computing the HMAC-SHA256 signature:
import hmac
import hashlib
import time

def verify_webhook(payload_body, signature_header, timestamp_header, secret):
    # Reject old timestamps (prevent replay attacks)
    if abs(time.time() - int(timestamp_header)) > 300:  # 5 minutes
        return False

    # Compute expected signature
    message = f"{timestamp_header}.{payload_body}"
    expected = "sha256=" + hmac.new(
        secret.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected, signature_header)

Webhook Payloads

All payloads share a common envelope:
{
  "event": "job.completed",
  "delivery_id": "550e8400-e29b-41d4-a716-446655440001",
  "timestamp": "2024-01-15T10:30:45.000Z",
  "data": { ... }
}

job.processing

Sent when the job starts processing:
{
  "event": "job.processing",
  "delivery_id": "550e8400-e29b-41d4-a716-446655440001",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "job_request_id": "123e4567-e89b-12d3-a456-426614174000",
    "status": "processing",
    "previous_status": "pending",
    "job_type": "txt2img",
    "started_at": "2024-01-15T10:30:00.000Z"
  }
}

job.completed

Sent when the job finishes successfully:
{
  "event": "job.completed",
  "delivery_id": "550e8400-e29b-41d4-a716-446655440002",
  "timestamp": "2024-01-15T10:30:45.000Z",
  "data": {
    "job_request_id": "123e4567-e89b-12d3-a456-426614174000",
    "status": "done",
    "previous_status": "processing",
    "job_type": "txt2img",
    "completed_at": "2024-01-15T10:30:45.000Z",
    "result_url": "https://storage.modelbeam.ai/...",
    "processing_time_ms": 4500
  }
}

job.failed

Sent when the job encounters an error:
{
  "event": "job.failed",
  "delivery_id": "550e8400-e29b-41d4-a716-446655440003",
  "timestamp": "2024-01-15T10:30:45.000Z",
  "data": {
    "job_request_id": "123e4567-e89b-12d3-a456-426614174000",
    "status": "error",
    "previous_status": "processing",
    "job_type": "txt2img",
    "failed_at": "2024-01-15T10:30:45.000Z",
    "error_code": "model_unavailable",
    "error_message": "The requested model is currently unavailable"
  }
}

Error Codes

CodeDescription
WORKER_TIMEOUTWorker timed out processing the job
PROCESSING_ERRORError during inference processing
AGE_RESTRICTEDContent flagged as age-restricted
CONTEXT_LENGTH_EXCEEDEDInput exceeds model context length
INVALID_INPUTInvalid input parameters
UNKNOWN_ERRORUnclassified error

Retry Policy

  • ModelBeam retries failed webhook deliveries with exponential backoff
  • Up to 10 attempts over approximately 24 hours
  • Webhooks are auto-disabled after 10 consecutive failures

Requirements

  • Respond with a 2xx status code within 10 seconds
  • No HTTP redirects
  • HTTPS only