Skip to main content
Instead of polling GET /generations/{id}, you can pass webhook_url when you create a generation. Codzen then sends the finished generation to that URL in a POST request.
webhook_url must be an HTTPS URL. It is set per generation; there is no account-wide webhook to register.

When webhooks are sent

A webhook is sent only once the generation reaches a terminal state: succeeded or failed. There is no webhook for queued or processing. The request body is the finished generation, exactly as GET /generations/{id} returns it:
The webhook reference has the same payload as a schema.

Delivery and retries

  • Answer with any 2xx status to confirm the delivery. Any other status, a timeout or a connection error counts as a failure.
  • Failed deliveries are retried with exponential backoff for 24 hours, then dropped. A failed delivery never changes the generation; you can still read it with GET /generations/{id}.
  • Delivery is at least once. The same webhook can arrive more than once. Every retry carries the same webhook-id header, so store the IDs you have handled and skip a webhook whose ID you have already seen.
  • Order is not guaranteed across generations. Use each generation’s id and status, not arrival order.
Answer quickly: verify the signature, record the webhook, return 200, and do slow work such as downloading outputs afterwards.

Verify the signature

Webhooks follow the Standard Webhooks specification. Every webhook carries three headers: Each signature is an HMAC-SHA256 of the string <webhook-id>.<webhook-timestamp>.<body>, keyed with your webhook signing secret. The secret looks like whsec_<base64>; the key is the base64-decoded part after whsec_. Your account has one webhook signing secret, which you can view and rotate in the console. To verify a webhook:
  1. Read the raw request body as bytes, before any JSON parsing. Re-serialized JSON will not match the signature.
  2. Reject the webhook if webhook-timestamp is more than 5 minutes from your clock, so that a captured request cannot be replayed later.
  3. Compute the HMAC-SHA256 of <webhook-id>.<webhook-timestamp>.<body> and base64-encode it.
  4. Accept the webhook if any v1 signature in webhook-signature matches, compared in constant time.
These functions do all four steps with no dependencies. Each returns the parsed generation, or throws (raises) if the webhook is not valid.
Use them in your webhook handler. Keep the secret in an environment variable, and make sure your framework hands you the raw body:
Any Standard Webhooks library verifies Codzen webhooks too: pass it your whsec_… secret, the raw body and the three headers.

Rotate the webhook signing secret

You can rotate the webhook signing secret in the console at any time. Rotation creates a new secret right away, and the old one stays valid for 24 hours. During those 24 hours, every webhook’s webhook-signature carries two signatures, one made with each secret, separated by a space. To rotate without dropping webhooks:
  1. Rotate the secret in the console and copy the new one.
  2. Deploy the new secret to your webhook handler within 24 hours. Because each webhook is signed with both secrets meanwhile, the handler accepts webhooks with either the old or the new secret, and the examples above need no change.
  3. After 24 hours, webhooks carry only the new signature.
If you think your webhook signing secret has leaked, rotate it and deploy the new one at once: the old one keeps signing webhooks for 24 hours.