Receive print job updates from BizPrint with webhooks
This page shows you how to receive webhooks from BizPrint: messages that BizPrint sends to your server when a station reports progress on a print job. It is for developers who create print jobs with the BizPrint Print API, for stations that run either the BizPrint desktop app or the BizPrint Android app.
Before you start
Section titled “Before you start”- Create an application that uses the REST API. See Get API keys for the BizPrint Print API. Applications that use the Legacy API cannot send webhooks.
- Have the application’s Public Key and Secret Key. Keep the Secret Key on your server only. Never put it in browser code, an app you hand out, or a support message.
- Have a web address on your server that can receive a JSON
POSTrequest from the internet, for examplehttps://example.com/bizprint/webhook. Use the exact address of your handler, not one that redirects.
What BizPrint sends
Section titled “What BizPrint sends”BizPrint sends each webhook as a POST request with a JSON body. Every body has these fields:
| Field | What it is |
|---|---|
type |
The event: test-connect or print-job-status-update. |
_id |
A unique ID for this event. If BizPrint sends the same event again, the _id stays the same. |
publicKey |
The Public Key of your application. |
time |
When the request was signed, in Unix seconds. |
hash |
The signature. See Check that a webhook came from BizPrint. |
test-connect
Section titled “test-connect”BizPrint sends test-connect to check that your address answers. This happens when you save a new Webhook URL and when you click Perform test connection in the BizPrint dashboard. The body has only the common fields:
{ "_id": "EVENT_ID", "publicKey": "YOUR_PUBLIC_KEY", "type": "test-connect", "time": 1767225600, "hash": "SIGNATURE"}Your handler must accept test-connect and answer it with success, even though there is nothing to do.
print-job-status-update
Section titled “print-job-status-update”BizPrint sends print-job-status-update when the station reports a new print job status for a job your application created. The body also has a job object with the job as it is when the webhook is sent: id, status, description, url, printOption, printerId, createdAt and updatedAt. These are the same fields you get when you look up a job with the Print API. See Check print job status with the BizPrint Print API.
{ "_id": "EVENT_ID", "publicKey": "YOUR_PUBLIC_KEY", "type": "print-job-status-update", "job": { "id": "YOUR_JOB_ID", "status": "done", "description": "Order 1001", "url": "https://example.com/receipts/1001.pdf", "printOption": {}, "printerId": "YOUR_PRINTER_ID", "createdAt": "2026-01-01T09:00:00.000Z", "updatedAt": "2026-01-01T09:00:05.000Z" }, "time": 1767258005, "hash": "SIGNATURE"}In a real webhook, job.id and job.printerId are numbers. The example uses placeholders.
The station reports these statuses, so these are the ones you receive:
processing: the station started the job.done: the station reported that it printed the job.failed: the station could not print the job.
You do not get a webhook for pending, connecting-to-printer or archived, because the station does not report those. If a station is offline and never picks the job up, no webhook arrives. To catch these jobs, look them up with the Print API. See Check print job status with the BizPrint Print API.
Set your webhook URL
Section titled “Set your webhook URL”- Deploy your webhook handler first, so it can answer straight away.
- Sign in to the BizPrint dashboard.
- Click Applications in the menu.
- Click your application.
- Type your address in Webhook URL.
- Click Update. BizPrint sends a
test-connectwebhook to the new address once, straight away. - Click Perform test connection under Webhook Info to check again at any time. The dashboard shows Successfully connected with webhook server when your handler answered with success.
For more about the test button and its messages, see Test the webhook connection for a BizPrint application.
Check that a webhook came from BizPrint
Section titled “Check that a webhook came from BizPrint”BizPrint signs each webhook with your application’s Secret Key, the same way you sign a POST request to the Print API. See Sign BizPrint Print API requests. To check a webhook:
- Take the parsed JSON body.
- Remove the
hashfield. Keep every other field, in the order it arrived. - Turn the rest back into compact JSON text.
- Add a colon and your Secret Key to the end of that text.
- Make a SHA-256 hash of the result, written as lowercase hexadecimal.
- Compare it with the
hashyou received. If they differ, ignore the request. - Check that
publicKeyis your application’s Public Key. - Check that
timeis recent. BizPrint signs every delivery attempt again, sotimeis always close to the moment it was sent. Choose a window that suits you, for example five minutes.
In Node.js, JSON.stringify on the parsed body gives the same text BizPrint signed. In other languages, make sure your JSON output has no extra spaces, keeps the field order, and does not escape / or non-English characters.
To check one webhook by hand while you develop, you can paste its body into the BizPrint signing tool. See Sign and check BizPrint Print API requests with the signing tool.
Example handler in Node.js
Section titled “Example handler in Node.js”This example uses Express. It checks the signature, saves the event, and answers straight away. Load your keys from your server’s environment, never from your code repository.
import crypto from 'node:crypto';import express from 'express';
// Set these on your server to YOUR_PUBLIC_KEY and YOUR_SECRET_KEY.const PUBLIC_KEY = process.env.BIZPRINT_PUBLIC_KEY;const SECRET_KEY = process.env.BIZPRINT_SECRET_KEY;const MAX_AGE_SECONDS = 300;
function isFromBizPrint(body) { const { hash, ...signed } = body; if (typeof hash !== 'string' || signed.publicKey !== PUBLIC_KEY) return false;
const expected = crypto .createHash('sha256') .update(`${JSON.stringify(signed)}:${SECRET_KEY}`) .digest('hex');
const received = Buffer.from(hash, 'hex'); const wanted = Buffer.from(expected, 'hex'); if (received.length !== wanted.length || !crypto.timingSafeEqual(received, wanted)) { return false; }
const age = Math.abs(Math.floor(Date.now() / 1000) - Number(signed.time)); return age <= MAX_AGE_SECONDS;}
const app = express();
app.post('/bizprint/webhook', express.json(), async (req, res) => { if (!isFromBizPrint(req.body)) { return res.status(401).end(); }
// Save the event quickly (for example, in your database), keyed by _id, // so a repeated delivery of the same event is stored only once. await saveEventOnce(req.body._id, req.body);
// Answer straight away. Do slow work later, from your saved events. res.status(200).json({ received: true });});
app.listen(3000);saveEventOnce stands for your own code that stores the event and skips an _id it has already stored.
If your check rejects real webhooks, for example because the handler uses the wrong Secret Key, BizPrint counts every delivery as failed, and webhooks can stop. Use the keys of the same application that creates your print jobs.
Answer quickly with success
Section titled “Answer quickly with success”- Answer with a 2xx status, such as
200. You can send{"received": true}as the body. Any other status, or no answer, counts as a failed delivery. - Answer fast. Save the event, answer, and then do the work, such as updating an order or sending an email.
- Expect repeats. If a delivery fails, BizPrint tries the same event again with the same
_id. Use_idso you handle each event once. - Expect more than one update per job. A job usually gets
processingand thendoneorfailed. A station can report the same status twice, and a reprint from the dashboard sends new updates for the same job. - Do not rely on the order. A repeated delivery can arrive after a newer update. Compare
job.updatedAt, or look the job up with the Print API when the order matters.
When BizPrint stops sending webhooks
Section titled “When BizPrint stops sending webhooks”If a webhook still fails after BizPrint’s last attempt, BizPrint marks the application’s webhook as failing and stops sending all print-job-status-update webhooks for that application. Updates from that moment on are not sent, and they are not sent later either.
The application page in the dashboard then shows Error connection to webhook server. under Webhook Info, with the error your server gave, if any.
Webhooks start again only when one of these happens:
- You save a different Webhook URL for the application.
- A
test-connectwebhook succeeds, for example after you click Perform test connection.
To recover:
- Fix your handler so it answers
test-connectwith a 2xx status. - Click Perform test connection on the application page in the dashboard.
- Check that the dashboard shows Successfully connected with webhook server.
- Look up the jobs you created while webhooks were stopped, to catch the updates you missed. See Check print job status with the BizPrint Print API.
For more help, see BizPrint webhook test connection fails.
Do not print twice because of a webhook
Section titled “Do not print twice because of a webhook”A failed update, or an update that never arrives, does not prove that nothing printed. Do not create a new print job automatically in response. Every new job prints again. Before anyone prints again:
- Look at the paper at the printer for that document.
- Check the job’s status in the BizPrint dashboard, or with the Print API.
- Let the station finish what it is printing, whatever status the job shows.
- Do nothing more while the job is still
pending,connecting-to-printerorprocessing. - Reprint the existing job from the dashboard only if it really did not print. The reprint goes to the printer the job was first sent to. See Reprint a print job from the BizPrint dashboard.
Related pages
Section titled “Related pages”- Check print job status with the BizPrint Print API
- Test the webhook connection for a BizPrint application
- Sign BizPrint Print API requests
- BizPrint webhook test connection fails
Need help? Contact BizPrint support at https://getbizprint.com/support/.