Skip to main content
A webhook is an HTTPS request SudoMock sends to your server the moment a job reaches its final state, so your app reacts to a finished render instead of asking for it.

Why use webhooks

Every delivery is a signed JSON body your application can act on:
  • Publish a product image the second its render lands
  • Alert on a failed render while the order is still open
  • Keep your own record of every job the account ran
  • Drive a queue of PSD uploads from one route instead of many status calls
A delivery your server missed can be sent again later, one delivery at a time or every failed delivery for an endpoint at once. See Replay a single delivery.

How to receive webhooks

1

Create an endpoint in your app

Add a route that accepts POST requests and answers 200 once the body is safely stored.
app/api/sudomock/route.js
Any status other than 2xx, and any timeout, counts as a failed delivery.
For local work, put your development server behind a public HTTPS URL with a tunnel such as ngrok or the port forwarding built into your editor, then register that URL: https://example123.ngrok.io/api/sudomock.
2

Register the endpoint

  1. Open Dashboard, Webhooks
  2. Add your public HTTPS URL
  3. Pick the events you want, or leave the selection empty for all of them
  4. Copy the signing secret before you close the dialog
The secret is prefixed whsec_ and is shown in full only when it is created and when it is rotated. Every later read masks it as whsec_****<last4>.
Endpoints can also be managed from your own backend. See Create a new webhook endpoint.
3

Send a test event

Send a test delivery from the panel, or call Send a test event. It travels the same signed path as a real one, so verification that passes here passes in production.A finished render arrives in this shape:
Every event is listed in Events, and every field of the body in The payload.
4

Verify the signature, then handle the event

Check the signature before you act on the body, then branch on event.
app/api/sudomock/route.js
Verifying signatures carries the full verification function in Node.js and Python.
5

Move the endpoint to production

Deploy the handler, then register the production URL the same way. Each endpoint has its own secret, so the development one can stay registered beside it.

Events

Leave event_types empty to subscribe to every event, including ones added later. A failed upload is delivered as render.failed, so subscribe to render.failed if you ingest PSDs.

The payload

Every delivery opens with the same envelope. A render, an upload, a video and a photo mockup render carry the fields below. The three photo_mockup.* creation events carry the mockup’s own fields instead, and Photo mockups covers them.
string
The event that fired, spelled exactly as in the table above.
string
The job this event belongs to. It is the id you pass to GET /api/v1/jobs/{job_id}, and half of the idempotency key.
string
The job family behind the event, for example render, upload or video. An endpoint subscribed to everything can filter on it without parsing the event name.
succeeded | failed | ready | rejected
The final state the job reached. It matches the second half of the event name.
string | null
The finished file for a render or a video, and the new mockup_uuid for upload.succeeded. It is null on a failure, and it can be null on a delivery that was replayed.
object | null
null on success. On a failure it carries the same structured error the API returns, with error_code and message. See Errors.
string
ISO 8601 timestamp of the moment the event was created.
The body arrives as a POST with Content-Type: application/json, and two more headers travel with it, X-SudoMock-Signature and X-SudoMock-Timestamp. Verifying signatures shows what to compute from them.

FAQ

Failed deliveries are retried automatically. Every attempt is logged with the HTTP status your server returned, the attempt count and the last error, and you can send one again yourself once the server is back.From the panel:
  1. Open Dashboard, Webhooks
  2. Open the endpoint
  3. Open the delivery you want to send again
  4. Replay it
From your own backend, call Replay a single delivery, or Replay all failed deliveries for the whole endpoint.
Treat job_id plus the event name as the delivery’s idempotency key, persist it before applying side effects, and return a 2xx response only after processing succeeds. A replayed delivery can arrive with result_url set to null; fetch the result by polling GET /api/v1/jobs/{job_id} when that happens.
No. GET /api/v1/jobs/{job_id} stays the source of truth for a job, and a webhook is the notification that saves you from asking on a timer.
The delivery and event feeds page with an opaque cursor. Make the first request without cursor. When another page exists, the response carries X-Webhook-Next-Cursor, and you send that exact value as the next request’s cursor. When the header is absent, the list is complete. Pagination covers the other list endpoints.
Endpoints created before the photo_mockup names were introduced are pinned to the earlier spelling of the same five events: 2d_mockup.ready, 2d_mockup.rejected, 2d_mockup.failed, 2d_render.succeeded and 2d_render.failed, with kind spelled 2d_create or 2d_render. They keep receiving them unchanged. The endpoint’s event_naming field reads legacy or current and says which spelling it receives; Create a new webhook endpoint covers how a new endpoint is pinned. Either spelling is accepted in event_types. Move an existing endpoint with PATCH { "event_naming": "current" } once your handler reads the new names.

Verifying signatures

Node.js and Python you can paste into your handler.

Webhook endpoints

Create, update, rotate and test an endpoint from your backend.

Webhook deliveries

Read every attempt, and replay the ones that failed.

Watch deliveries from the panel

Success rate, delivery log and the account-wide event feed.