API reference

API overview

Every browser SDK method: connecting and authorising, printers, printing, preview, scanning and jobs — with signatures, parameters, return values and examples.

Last updated

This is the complete list of interfaces available to a web page. All methods are promise-based and throw structured errors (code / message / retryable) — see error codes.

This is all a web page can do

Desktop-only privileged capabilities (writing settings, the job content viewer, service migration transactions…) are not a web API and can never be called from a page. A page has exactly what is listed here.

Endpoints and creation

ItemValue
Default endpointws://127.0.0.1:17888/ws
Protocolprintlink.v1 (the wire field v is always 1)
Browser SDKhttp://127.0.0.1:17888/sdk/printlink.js (global PrintLink)
npm package@printlink/sdk
Health checkGET /healthz
HTTP interfacePOST /rpc (same port, see HTTP interface)
Scan page downloadGET /api/v1/scans/{scanId}/pages/{index}
import { PrintLinkClient } from '@printlink/sdk';

const client = new PrintLinkClient({
  appName: 'My business app',         // shown in the pairing prompt and site list
  channel: 'erp',                     // optional: distinguish apps on one machine
  endpoint: 'ws://127.0.0.1:17888/ws',// optional, this is the default
  requestTimeoutMs: 30_000,           // optional per-request timeout
});

Connecting and authorising

detect() → connect() → ensureAuthorized() → calls … → close()
MethodReturnsNotes
PrintLinkClient.detect(options?)DetectResultStatic, no instance needed: installed / reachable / version / reason
connect()HelloResultConnects: agentVersion / protocolVersion / platform / features
ensureAuthorized(permissions?)AuthStatusResultReturns if authorised, otherwise pairs. Also accepts { requestedPermissions, waitForDecision, timeoutMs, signal }
authStatus()AuthStatusResultCurrent authorisation state and granted permissions
pair(permissions?)AuthPairResultExplicitly start pairing (opens the local prompt)
revoke()voidRevoke this site's own token
onConnectionStateChange(listener)unsubscribeTransport / authorisation / ready snapshot
onAuthDecisionChanged(handler)unsubscribeThe user accepted or refused pairing
onServiceMigrated(handler)unsubscribeThe service port changed
close()voidDisconnect and clear subscriptions — always call this

ensureAuthorized({ waitForDecision: true }) waits for the user's decision instead of failing immediately with PAIRING_PENDING, which suits a "click print, then wait for approval" interaction.

features is a capability list (e.g. scanner.v1) — use it for feature detection rather than comparing version numbers.

Printers and profiles

MethodReturnsNotes
listPrinters(){ devices, queues }Queues with live status, plus physical device grouping
defaultPrinter()string | nullThe OS default printer's queueId
getCapabilities(queueId, refresh?)PrinterCapabilitiesPaper, duplex, colour, copies, trays, media, resolutions
printerStatus(queueId)PrinterStatusSnapshotImmediate status
onPrinterStatusChanged(handler)unsubscribeStatus change events
setPreferredPrinter(queueId | null)PrinterListResultSet or clear the preferred printer
openPrinterSettings(queueId){ opened }Open the OS printer settings
listProfiles(queueId?)profile summariesList profiles
getProfile(id)profile summaryOne profile
createProfileFromNative(queueId, name)profile summaryCapture the printer's current native config
renameProfile(id, name)profile summaryRename
setDefaultProfile(id)profile summaryMake it the printer's default
setProfileStandard(id, options)profile summaryWrite cross-platform standard options
deleteProfile(id)voidDelete

Details in printers & profiles.

Uploading and printing

MethodReturnsNotes
uploadAsset(bytes, mime)AssetRefUpload a PDF or image; chunked with SHA-256 verification
validate(params)JobValidateResultPre-flight: requested → effective + warnings, no side effects
compose({ queueId })PrintJobBuilderThe chained builder, below
print(params)JobPrintResultSilent print; returns a jobId immediately
printAndWait(params, options?)JobStatusEventDataSubmit and wait for the terminal state; options.onStatus receives intermediate states, timeoutMs defaults to 120 s

JobPrintParams

interface JobPrintParams {
  queueId: string;
  source: PrintSource;       // { items: SourceItem[] }, 1..=50
  options?: PrintOptions;    // see the print options page
  profileId?: string;        // omitted = printer default; '' = explicitly none
  profileMode?: 'default' | 'explicit' | 'none';
  title?: string;            // shown in the console job list
  idempotencyKey?: string;   // 1..128 visible ASCII; a repeat runs once
  channel?: string;          // ^[a-z][a-z0-9_-]*$, up to 64 characters
}

PrintSource / SourceItem

type SourceItem =
  | { type: 'image'; asset?: AssetRef; remote?: { url: string }; pageLayout?: PageLayout }
  | { type: 'pdf'; asset: AssetRef; pageRange?: string }
  | { type: 'html'; asset?: AssetRef; remote?: { url: string }; pageRange?: string }
  | { type: 'document'; document: PrintDocument; data?: unknown };

asset and remote are mutually exclusive (both or neither is INVALID_REQUEST). remote accepts public addresses only — see content sources.

PrintJobBuilder (what compose() returns)

MethodNotes
.paper('auto' | name | PageSize) / .pageSize(w, h, unit?)The job's paper, set once
.copies(n) .orientation(v) .duplex(v) .color(bool) .borderless(bool) .quality(v) .mediaType(v) .tray(v) .collate(bool) .reverseOrder(bool)Correspond to options.*
.pageLayout('auto' | 'actual' | 'fill')Job-wide preset; no custom
.margins(v) .outputPageRange(v) .options(patch)Margins, output page range, bulk patch
.profile(id) .compatibility(mode)Reference a profile; compatibility mode
.title(t) .idempotencyKey(k)Title and idempotency key
.addPdf(src) → .pageRange(r)One PDF
.addImage(src) → .imageLayout(layout)One image, with its own layout
.addHtml(src) → .pageRange(r)One web page
.addDocument(doc) → .data(d)One template with its data
.add(item)A ready-made wire item (e.g. a Hiprint conversion)
.validate() .preview() .print() .printAndWait() .toParams()Submit

The types reject invalid combinations: .addImage(x).pageRange(), .addPdf(x).imageLayout() and a job-level .pageLayout({ mode: 'custom' }) are all compile errors.

Preview

MethodReturnsNotes
preview(params)PreviewOpenResultOpens the preview window; same parameters as print()
previewUpdate({ previewSessionId, ... })PreviewOpenResultUpdate the preview
previewGetPage(sessionId, pageIndex)PreviewGetPageResultRasterise one page (trusted local UI only)
previewPrint(sessionId)JobPrintResultPrint the same artefact shown
previewClose(sessionId)voidClose the session
interface PreviewOpenResult {
  previewSessionId: string;
  pageCount: number;
  artifactSha256: string;
  warnings: PrintWarning[];
  windowShown: boolean;
  source: SourceSummary;    // which output pages each item covers
}

interface PreviewUpdateParams {
  previewSessionId: string;
  source?: PrintSource;                 // full replacement
  options?: PrintOptions;               // full replacement
  pageLayout?: PreviewPageLayoutUpdate; // targeted update
  queueId?: string;
  profileId?: string;
  profileMode?: 'default' | 'explicit' | 'none';
}

type PreviewPageLayoutUpdate =
  | { scope: 'all'; layout: PageLayoutPreset }
  | { scope: 'image'; itemIndex: number; layout: PageLayout };

Details in preview.

Jobs

MethodReturnsNotes
getJob(jobId)PrintJobDetails (only jobs from this site)
listJobs(limit?)PrintJob[]Job list
cancelJob(jobId)PrintJobCancel a job
onJobStatus(handler)unsubscribeJob status transitions
onDuplicateSuppressed(handler)unsubscribeAn idempotency key suppressed a repeat
getDiagnostics()diagnostics summarySanitised system information

Scanning

scanner.read and scan.run are not granted by default.

MethodNotes
scannerList(refresh?)List scanners
scannerGet(scannerId)One scanner
scannerCapabilities(scannerId, refresh?)Source × resolution × colour × format × size
scannerStatus(scannerId)Immediate status
scanValidate(scannerId, options, compatibility?)Side-effect-free validation
scanStart(params)Create the job (may enter awaiting-consent)
scan(params, options?)Start and wait for the terminal state
scanStatus(scanId) / scanList(limit?)Query
scanCancel(scanId)Cancel
scanGetPage(scanId, index, maxWidthPx?, pdfPage?)A single small page
fetchScanPage(scanId, index, ticket?)Fetch the page as a Blob
onScanStatus(handler) / onScanPageReady(handler) / onScannerListChanged(handler)Events

Details in scan.

Data models

type PageLayoutPreset =
  | { mode: 'auto' }      // scale to fit the printable area, centred, no cropping
  | { mode: 'actual' }    // 1:1, centred, cropped where it overflows
  | { mode: 'fill' };     // scale up to cover, cropping the overflow

type PageLayout =
  | PageLayoutPreset
  | {
      mode: 'custom';
      horizontal?: 'left' | 'center' | 'right';
      vertical?: 'top' | 'center' | 'bottom';
      size?: { widthMm?: number; heightMm?: number };   // exclusive with scalePercent
      scalePercent?: number;                             // (0, 1000]
      offset?: { xMm?: number; yMm?: number };
      rotate?: 0 | 90 | 180 | 270;
      flipHorizontal?: boolean;
      flipVertical?: boolean;
    };

interface AssetRef { id: string; sha256: string; mime: string; size: number }

interface PreviewGetPageResult {
  pageIndex: number;
  widthPx: number;
  heightPx: number;
  pngBase64: string;
  origin: { itemIndex: number; kind: string; itemPageIndex: number };
  pageLayout: PageLayout;          // the layout actually used, always present
  layout?: PageLayoutGeometry;     // millimetre geometry
}

Capability resolution is mandatory

Before rendering, every job goes through capability resolution: requested values are resolved against the printer's real capabilities into effective values, and anything unsatisfiable is downgraded with structured warnings. validate() gives you the same result before submitting.

Next steps

On this page