Open with AI
Webhooks
Listen for events on your webhook endpoint so your integration can react as renders progress, without polling.
After you register a webhook endpoint, Edit Square POSTs a JSON payload to
it when a render changes state. Receiving webhook events is the right way to
respond to asynchronous work such as a render completing or failing,
especially at volume.
Set up your endpoint
Section titled “Set up your endpoint”Webhook endpoints are configured per team in the dashboard, under Webhooks:
- Register your endpoint’s publicly accessible HTTPS URL.
- Select the events you want delivered to it.
- Copy the signing secret generated for the endpoint. You will use it to verify deliveries.
Events
Section titled “Events”| Event | Sent when |
|---|---|
render.status_changed |
A render’s status changes, including both complete and failed. |
render.complete |
A render finished successfully. |
render.failed |
A render stopped with an error. |
Only subscribe to the events your integration requires. An endpoint
subscribed to both render.status_changed and render.complete receives
two deliveries when a render completes, one for each event.
The event payload
Section titled “The event payload”{ "id": "hook_jn8x…", "event": "render.complete", "data": { "id": "rend_jh716ctpaqbye9aw64tgkqwtks7gvx7g", "name": "Example render name", "status": "complete", "project": { "id": "proj_jd71dcg…", "team": "team_jn7fw41…" }, "output": { "master": "https://…" } }, "timestamp": 1748875986000}data is the render, in the same shape
GET /v1/renders/{id} returns.
Every delivery also carries these headers:
| Header | Value |
|---|---|
X-Webhook-Signature |
sha256=<hex>, an HMAC-SHA256 of the raw body, keyed with the endpoint’s secret. |
X-Webhook-ID |
The delivery ID. The same across retries of one delivery. |
X-Webhook-Timestamp |
Milliseconds since the epoch, matching timestamp in the body. |
User-Agent |
EditSquare-Webhooks/1.0 |
Create a handler
Section titled “Create a handler”Set up an HTTPS endpoint function that:
- Handles
POSTrequests with a JSON payload. - Verifies the request was sent by Edit Square, using the
X-Webhook-Signatureheader and your endpoint’s signing secret. - Quickly returns a
2xxstatus code before any long-running logic. For example, respond first and then download the render’s output, rather than holding the connection open while you download it.
Verify deliveries
Section titled “Verify deliveries”Without verification, anyone who discovers your URL can POST fake events to
it. Always verify that a delivery came from Edit Square before acting on it.
Compute an HMAC-SHA256 over the raw request body, the exact bytes before
any JSON parsing, keyed with your endpoint’s signing secret, and compare it to
the X-Webhook-Signature header in constant time:
import { createHmac, timingSafeEqual } from 'node:crypto';
function isFromEditSquare(rawBody, header, secret) { const expected = `sha256=${createHmac('sha256', secret).update(rawBody).digest('hex')}`; const a = Buffer.from(header ?? ''); const b = Buffer.from(expected); return a.length === b.length && timingSafeEqual(a, b);}Reject any request that does not match.
If you are using a web framework, make sure it does not parse or reformat the request body before you read it. The signature is computed over the raw bytes, and any change to them causes verification to fail.
Delivery behaviour
Section titled “Delivery behaviour”Retries
Section titled “Retries”A delivery is attempted up to five times: the first attempt, then four retries with exponential backoff starting at one second. Each attempt times out after 15 seconds, which is why your handler must respond quickly.
Duplicate deliveries
Section titled “Duplicate deliveries”Because retries exist, your endpoint can receive the same event more than
once. X-Webhook-ID is the same across retries of one delivery, so log the
IDs you have processed and skip any you have already seen.