Skip to main content
Webhooks push events to your HTTPS endpoint as they happen, so you do not need to poll. Every request is signed with your endpoint secret following the Standard Webhooks specification, retried for about 27 hours if your endpoint fails, and visible in a delivery log you can replay from the dashboard.

Create an endpoint

In the dashboard, open Webhooks, choose Add endpoint, enter your URL and pick the events you want. Or call the API with a key that has the admin scope:
The response includes the signing secret, which starts with whsec_. It is shown once and never again, so store it in your secret manager now. If you lose it, delete the endpoint and create a new one. Each endpoint belongs to one mode, the mode of the key that created it (or of the dashboard test mode toggle). It receives only events of that mode. URLs must be https: for live endpoints, must not contain a username or password, and must resolve to a public address. The check runs when you create or change an endpoint and again before every send, so an address that later points at a private network is refused. A URL that fails answers 422 invalid_url.

Event types

Subscribe an endpoint only to the events you handle. See Printing PDFs for what each job state means.

Payload

Every request body is a JSON envelope:
id identifies the event and is the same on every retry and replay. timestamp is when the event happened and mode is live or test. For printjob.* events, data is the print job object as GET /v1/printjobs/{id} returns it (the example is shortened). For computer.* events, data holds the computer id with its name and state. For printer.* events, data holds the printer id and the computerId it belongs to, with the details of the change.

Headers

Verify signatures

Always verify the signature before you trust a request. The SDKs check the signature and reject timestamps more than 300 seconds from now, which stops replayed requests.
Verify the raw body exactly as received. Parsing and re-serialising the JSON changes the bytes and breaks the signature. In Express, read the body as text (as above) rather than through express.json().
Without the SDK, compute base64(HMAC-SHA256(key, "{webhook-id}.{webhook-timestamp}.{body}")), where key is the base64 decoded part of the secret after whsec_. Compare the result with each v1, entry of webhook-signature (the header can hold several, separated by spaces) using a constant time comparison, and reject timestamps more than 300 seconds from now.

Retries

Attempt 1 is sent immediately. A delivery succeeds when your endpoint answers with any 2xx status within 10 seconds. Anything else (another status, a timeout, a connection error) is a failure, and PrintEasy waits and tries again: Each wait varies by plus or minus 20 percent (jitter). If attempt 9 also fails, the delivery is marked failed. A delivery is pending before its first send, retrying between attempts, succeeded after a 2xx and failed when attempts run out. Respond quickly and do the real work afterwards, for example by putting the event on a queue. Redirects are not followed.

Auto-disable after 5 days of failures

PrintEasy records when an endpoint started failing and clears that mark on any success. An endpoint whose deliveries keep failing for 5 days is disabled with the reason Disabled automatically after 5 days of failed deliveries, and every organization owner gets an email. Fix your receiver, then re-enable the endpoint in the dashboard (or PATCH /v1/webhooks/{id} with {"enabled": true}). Events produced while the endpoint was disabled are not sent to it; use the event feed to catch up.

Replays and duplicates

The delivery log in the dashboard (and GET /v1/webhooks/{id}/deliveries) shows every attempt with its status code and the start of the response. Replay a delivery from the dashboard or with POST /v1/webhooks/deliveries/{id}/replay. A replay sends the same event again with the same webhook-id. Replays need an enabled endpoint. Delivery is at least once, so a request can arrive more than once, and events can arrive out of order. Store the webhook-id values you have handled and skip repeats. Use the job state in data to ignore an older state that arrives after a newer one. Delivery logs are kept for 30 days.

Test mode endpoints

An endpoint created with a test key, or while the dashboard is in test mode, receives only test events, and may use an http: URL (for example a tunnel to your laptop). Use it with the virtual printers in Test mode to exercise your receiver end to end.

Event feed alternative

If you cannot expose an endpoint, poll GET /v1/events. It returns the events of your key’s mode, a page at a time. Use dir=asc with after set to the nextCursor of your previous call to read new events in order. Make the first call without after (an empty after= is rejected with 400):
Then pass the nextCursor you got back as after on each later call:
The response has data, hasMore and nextCursor. When a page is empty, nextCursor is the after you sent, so you can keep polling with the same value. With dir=asc, an event shows up in the feed about 2 seconds after it happens. Keep after at the last event id you processed and poll again; do not skip ahead to a newer id, or you could miss an event that appears a moment later.