Skip to content
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.

Webhook endpoints are configured per team in the dashboard, under Webhooks:

  1. Register your endpoint’s publicly accessible HTTPS URL.
  2. Select the events you want delivered to it.
  3. Copy the signing secret generated for the endpoint. You will use it to verify deliveries.
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.

{
"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

Set up an HTTPS endpoint function that:

  • Handles POST requests with a JSON payload.
  • Verifies the request was sent by Edit Square, using the X-Webhook-Signature header and your endpoint’s signing secret.
  • Quickly returns a 2xx status 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.

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.

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.

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.