Dashboard

Webhooks

Configure a webhook URL to receive signed HTTP POST notifications when jobs complete or fail. One webhook URL per account, configured at the tenant level. Use webhooks instead of polling to build responsive integrations.

Supported Events

U-Gen sends webhooks for two events:job.completedjob.failedBoth events are delivered automatically whenever a webhook URL is configured. There is no per-event subscription — you receive both.

Configure Webhook

Set or update your webhook URL and signing secret. Replaces any existing configuration.

PUT/api/v1/tenants/me/webhook

One webhook URL per account. Calling PUT replaces the previous configuration.

If webhook_secret is omitted, deliveries are sent unsigned (no X-UGen-Signature header).

Generate a secret with: openssl rand -hex 32 (produces a 64-character hex string).

Body

ParameterType
webhook_urlREQ
string (URL)
webhook_secret
string

Request Example

curl -X PUT https://api.u-gen.ai/api/v1/tenants/me/webhook \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_url": "https://example.com/webhooks/u-gen",
    "webhook_secret": "a7b3c9d2e1f4a8b5c6d7e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1"
  }'

Get Webhook Config

Retrieve the current webhook configuration. The secret is not returned.

GET/api/v1/tenants/me/webhook

webhook_configured is true if a URL is set, false otherwise.

The webhook_secret is never returned in the response for security.

Request Example

curl -X GET https://api.u-gen.ai/api/v1/tenants/me/webhook \
  -H "X-API-Key: YOUR_API_KEY"

Remove Webhook

Remove your webhook configuration. You will stop receiving notifications.

DELETE/api/v1/tenants/me/webhook

Clears both the URL and secret. Any in-flight retries will continue but no new deliveries will be sent.

Request Example

curl -X DELETE https://api.u-gen.ai/api/v1/tenants/me/webhook \
  -H "X-API-Key: YOUR_API_KEY"

Per-Job Override

You can override the tenant webhook URL on a per-job basis by passing webhook_url in the POST /api/v1/jobs request body. The job-level URL takes precedence over the tenant-level configuration. The tenant's signing secret is used for both.

Delivery Format

When a job completes or fails, U-Gen sends a POST request to your configured URL with the following payload and headers.

Request Headers

HeaderDescription
Content-TypeAlways application/json
X-UGen-TimestampISO 8601 timestamp of when the delivery was sent
X-UGen-SignatureHMAC-SHA256 hex signature (only if a signing secret is configured)
User-AgentUGen-Webhook/1.0

Payload Fields

FieldTypeDescription
eventstringjob.completed or job.failed
job_idstring (UUID)The job identifier
statusstringcompleted or failed
final_video_urlstring | nullDownload URL for the final video (null on failure)
thumbnail_urlstring | nullThumbnail image URL (null on failure)
credits_consumednumberCredits consumed by the job (0 on failure)
error_messagestring | nullError description (null on success)
timestampstringISO 8601 timestamp of when the event occurred

Example: job.completed

{
  "event": "job.completed",
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "final_video_url": "https://storage.u-gen.ai/videos/550e8400/final.mp4",
  "thumbnail_url": "https://storage.u-gen.ai/videos/550e8400/thumbnail.jpg",
  "credits_consumed": 131.0,
  "error_message": null,
  "timestamp": "2026-04-10T18:30:45.123456+00:00"
}

Example: job.failed

{
  "event": "job.failed",
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "failed",
  "final_video_url": null,
  "thumbnail_url": null,
  "credits_consumed": 0.0,
  "error_message": "Segment generation failed: Video timeout after 300s",
  "timestamp": "2026-04-10T18:30:45.123456+00:00"
}

Signature Verification

If you configured a signing secret, verify the X-UGen-Signature header to ensure the request is authentic. The signature is computed as: HMAC-SHA256(secret, timestamp + "." + body) where the body is the raw minified JSON (no spaces).

Node.js

const crypto = require('crypto');

function verifyWebhook(rawBody, headers, secret) {
  const timestamp = headers['x-ugen-timestamp'];
  const signature = headers['x-ugen-signature'];
  const message = timestamp + '.' + rawBody;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature),
  );
}

Python

import hashlib, hmac

def verify_webhook(raw_body: str, headers: dict, secret: str) -> bool:
    timestamp = headers["x-ugen-timestamp"]
    signature = headers["x-ugen-signature"]
    message = f"{timestamp}.{raw_body}"
    expected = hmac.new(
        secret.encode(), message.encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Retry Behavior

If your endpoint returns a non-2xx status code or is unreachable, U-Gen retries the delivery up to 3 times with exponential backoff.

AttemptDelay BeforeTimeout
1stImmediate10 seconds
2nd1 second10 seconds
3rd (final)4 seconds10 seconds

After 3 failed attempts, the delivery is abandoned. No delivery log is stored — failed webhooks are only visible in server logs. Delivery is fire-and-forget and does not affect the job status.

Idempotency

Your endpoint may receive the same event more than once if a network issue caused an ambiguous response. Use the job_id and event fields to deduplicate deliveries on your side.