Node.js Integration
Integrate discovery, pairing, gateway authentication, and job delivery.
Install the framework-neutral packages and your chosen transport:
pnpm add @openprinter/protocol @openprinter/server wsCreate the OpenPrinter server
const openprinter = createOpenPrinterServer({
brand: { name: 'Acme Print Service' },
serverId: 'acme-print-v1',
serverVersion: '1.0.0',
pairingCodeStore,
credentialStore,
checkPairingRateLimit: ({ remoteAddress }) =>
limiter.check(remoteAddress),
onAgentConnected: ({ agent, session }) =>
sessions.register(agent.agentId, session),
onAgentDisconnected: ({ agent, session }) =>
sessions.removeIfCurrent(agent.agentId, session),
onPrintersChanged: ({ agent, printers }) =>
inventories.replace(agent.agentId, printers),
onJobReceived: ({ agent, message }) =>
jobs.markReceived(agent.agentId, message.payload.jobId),
});Add discovery and pairing
app.get(openprinter.paths.discovery, async (_request, response) => {
response.json(await openprinter.discover());
});
app.post(openprinter.paths.pairing, async (request, response) => {
response.json(
await openprinter.pair(request.body, {
remoteAddress: request.ip,
}),
);
});An authorized application workflow calls createPairingCode and
displays the result to the intended operator. Never include it in a
URL. Production stores must make consumption atomic with credential
registration and preserve an unconsumed grant if registration fails.
Upgrade the gateway
const wss = new WebSocketServer({ noServer: true });
httpServer.on('upgrade', (request, socket, head) => {
if (
new URL(request.url, publicOrigin).pathname !==
openprinter.paths.gateway
) {
socket.destroy();
return;
}
wss.handleUpgrade(request, socket, head, (webSocket) => {
openprinter.handleGatewayConnection(webSocket);
});
});The SDK sends the initial challenge immediately, verifies the stored Ed25519 public credential, and rejects all normal messages until authentication succeeds. The host does not parse a credential from the upgrade request.
Send a durable job
Persist the job first, resolve the agent session through your own
registry or backplane, then call sendJob. Keep the job queued if the
agent is offline or delivery fails. Treat received, submitted, and
failed as separate lifecycle events.
Production checklist
- serve discovery/pairing over HTTPS and the gateway over WSS
- use durable pairing and public credential stores
- authorize code generation and rate-limit redemption attempts
- revoke public credentials when access ends
- retain server jobs durably and implement idempotent retry
- provide cluster-aware live-session affinity and stale-route expiry
- bound request bodies, frames, callbacks, and network timeouts
- avoid logging pairing codes, keys, signatures, challenges, or documents