Skip to main content
Instead of polling for job status, you can provide a webhook_url when uploading a video or creating a job. Clipzy sends an HTTP POST to that URL when the job finishes.

Set a webhook URL

Supply webhook_url in either the upload request or the job creation request. You only need to provide it in one place.
curl -X POST http://localhost:8000/api/v1/jobs \
  -H "Content-Type: application/json" \
  -d '{
    "video_id": "vid_abc123def456",
    "config": {"quality": "high"},
    "webhook_url": "https://yourapp.com/webhooks/clipzy"
  }'
The webhook_url must be publicly reachable by the Clipzy servers. Localhost URLs will not work in production.

Webhook payload

When a job reaches a terminal state (completed, failed, or cancelled), Clipzy sends a POST request to your webhook_url with the following JSON body:
{
  "job_id": "job_xyz789abc123",
  "status": "completed",
  "progress_percent": 100,
  "output_video_url": "file:///storage/job_xyz789abc123/output.mp4",
  "processing_time_seconds": 900.0
}
FieldTypeDescription
job_idstringThe job that triggered this notification.
statusstringTerminal status: completed, failed, or cancelled.
progress_percentnumberFinal progress value (100 on completion).
output_video_urlstringURL of the rendered output. Present only when status is "completed".
processing_time_secondsnumberTotal wall-clock processing time in seconds.

Handle the webhook in your server

Your endpoint must:
  1. Return HTTP 200 quickly (before doing any heavy processing).
  2. Process the payload asynchronously if needed.
1

Create an endpoint

Expose a POST route at the path you registered as webhook_url.
2

Acknowledge receipt immediately

Return 200 OK as soon as you receive the request. Clipzy considers any non-2xx response a failure and will retry.
3

Process the payload

Read job_id and status from the body, then take the appropriate action (e.g. download the output video, update your database, notify a user).

Python Flask example

Python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/webhooks/clipzy", methods=["POST"])
def clipzy_webhook():
    payload = request.get_json()

    job_id = payload.get("job_id")
    status = payload.get("status")
    output_url = payload.get("output_video_url")

    # Acknowledge immediately — do heavy work asynchronously
    if status == "completed":
        # Queue a task to download/process output_url
        print(f"Job {job_id} completed. Output: {output_url}")
    elif status == "failed":
        print(f"Job {job_id} failed.")
    elif status == "cancelled":
        print(f"Job {job_id} was cancelled.")

    return jsonify({"received": True}), 200


if __name__ == "__main__":
    app.run(port=5000)

Retry behavior

If your endpoint is unreachable or returns a non-2xx status code, Clipzy retries the webhook with exponential backoff. After several consecutive failures, delivery is abandoned and no further retries are made.
To avoid missing notifications:
  • Ensure your endpoint is deployed and reachable before creating jobs.
  • Return 200 immediately, even if you haven’t finished processing the payload.
  • If you miss a webhook, you can always fetch the job result directly with GET /api/v1/jobs/{job_id}/result. See Track progress for details.
During local development, use a tunneling tool (such as ngrok or Cloudflare Tunnel) to expose your local server to the internet so Clipzy can reach it.