Skip to content
getbizprint.com

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.

  • 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 POST request from the internet, for example https://example.com/bizprint/webhook. Use the exact address of your handler, not one that redirects.

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.

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.

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.

  1. Deploy your webhook handler first, so it can answer straight away.
  2. Sign in to the BizPrint dashboard.
  3. Click Applications in the menu.
  4. Click your application.
  5. Type your address in Webhook URL.
  6. Click Update. BizPrint sends a test-connect webhook to the new address once, straight away.
  7. 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.

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:

  1. Take the parsed JSON body.
  2. Remove the hash field. Keep every other field, in the order it arrived.
  3. Turn the rest back into compact JSON text.
  4. Add a colon and your Secret Key to the end of that text.
  5. Make a SHA-256 hash of the result, written as lowercase hexadecimal.
  6. Compare it with the hash you received. If they differ, ignore the request.
  7. Check that publicKey is your application’s Public Key.
  8. Check that time is recent. BizPrint signs every delivery attempt again, so time is 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.

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 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 _id so you handle each event once.
  • Expect more than one update per job. A job usually gets processing and then done or failed. 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.

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-connect webhook succeeds, for example after you click Perform test connection.

To recover:

  1. Fix your handler so it answers test-connect with a 2xx status.
  2. Click Perform test connection on the application page in the dashboard.
  3. Check that the dashboard shows Successfully connected with webhook server.
  4. 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.

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:

  1. Look at the paper at the printer for that document.
  2. Check the job’s status in the BizPrint dashboard, or with the Print API.
  3. Let the station finish what it is printing, whatever status the job shows.
  4. Do nothing more while the job is still pending, connecting-to-printer or processing.
  5. 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.

Need help? Contact BizPrint support at https://getbizprint.com/support/.