Skip to main content
A callback attaches a completion hook to one job. You pass callback.url when you create the job, and the moment that job reaches a terminal state Rendobar POSTs the result there. The body is byte-identical to the webhook envelope, so the same receiver code handles both. The correlation lives in the URL you chose, so the receiver stays stateless and never polls GET /jobs/{id}.

Attach a callback

Add a callback object to client.jobs.create(...). The only required field is url.
Terminal events (complete, failed, cancelled) always fire and cannot be filtered out, so a step waiting on a callback can never hang. callback.events only adds non-terminal pings on top. The one available today is "job.started", a progress signal sent when the job begins running.
Custom headers let the POST reach an authenticated endpoint with no receiver of your own. Framing headers and any X-Rendobar-* header are reserved. If you set one, the platform’s value wins.
Rendobar never returns callback.url or callback.headers in any API response. Both are secrets. GET /jobs/{id} reports only callback.status.

Resume a Cloudflare Workflow

Callbacks were built for this pattern. A Cloudflare Workflow dispatches a job and suspends until it finishes, with no polling in between. There are two shapes.

Shape A: receiver Worker with sendEvent

The Workflow’s own fetch handler is the receiver. The callback URL carries event.instanceId, the receiver route turns the POST into instance.sendEvent(...), and that resumes the suspended waitForEvent. This exact suspend and resume loop was verified end to end.

Shape B: no receiver Worker

Point callback.url straight at Cloudflare’s Workflows “send event” REST endpoint for the instance, and put your Cloudflare API token in callback.headers. Rendobar POSTs the job result directly to Cloudflare, so there is no shim to deploy. This is the zero-infrastructure option. The caller authenticates the callback itself through the header, so signing is usually unnecessary here.
The waiting Workflow is the same as Shape A. It calls waitForEvent({ type: "rb-job" }) and resumes when Cloudflare delivers the event.

Secure it

Callbacks are unsigned by default because the URL itself is the capability. Set callback.verify: true to sign the POST, then check it on your receiver. The signature is the same HMAC-SHA256 scheme as webhooks, over ${timestamp}.${body}, and the SDK ships the same verifier.
verifyCallback is the same function as verifyWebhook. Fetch the organization callback signing secret once and store it in your secret manager.
Rotate the secret with POST /orgs/current/callback-secret/rotate. Reach for signing when the callback lands on an endpoint you own and you want to prove the POST came from Rendobar. For Shape B, where you already authenticate to Cloudflare through callback.headers, signing usually adds nothing.

Watch delivery

Once a job carries a callback, GET /jobs/{id} reports its delivery state under callback.status. The dashboard job detail view shows the same status. Delivery is at-least-once, with retries and a dead-letter path, so the same event can arrive more than once. Deduplicate on the X-Rendobar-Delivery header, a whd_... id that is unique per delivery. Every POST carries these headers.

How it compares to org webhooks

Webhooks and callbacks carry the identical envelope and verify with the same code. The difference is scope. A webhook is one static URL registered in the dashboard that receives events for every job in the organization. A callback is a per-job URL, set at create time, that receives events for exactly one job. Webhooks fit a central event pipeline. Callbacks fit an orchestrator that dispatches a job and waits on that one job, such as the Cloudflare Workflow above.