Chapter 6. Script API Reference
The script API is the second entrance besides the declarative
“template + data” model: build print content programmatically as a
sequence of verbs (initialize → load data → add elements one by
one → print) without template files. The feature surface references
the Lodop print control; naming and units are WxPrint’s own
conventions (snake_case, millimeters).
Submission endpoint: POST /api/script (a one-shot HTTP submission;
WS carries no script sessions). Scripts are compiled into an
in-memory template object on the server and flow through the same
render pipeline as declarative templates — one core, two entrances.
{ "script": [
["init", { "task_name": "Delivery note" }],
["loadURL", { "url": "https://erp.example.com/api/order/SO-1024" }],
["pagesize", { "width_mm": 210, "height_mm": 297 }],
["add_text", { "x": 20, "y": 15, "w": 80, "h": 8, "text": "{{title}}",
"font": { "size_pt": 16, "weight": 700 } }],
["add_barcode", { "x": 20, "y": 30, "w": 60, "h": 10,
"symbology": "code128", "content": "{{order_no}}" }],
["newpage", {}],
["add_html", { "x": 0, "y": 0, "w": 210, "h": 297,
"html": "<h1>Details</h1><table>{% for it in items %}<tr><td>{{it.name}}</td></tr>{% endfor %}</table>" }],
["print", { "printer": "HP-LaserJet-M1005", "copies": 2 }]
] }
- Each verb =
[name, parameter object]; fields in Section 6.3.
- The response matches
/api/print (job_id/total_pages); replacing
the trailing print verb with preview yields a preview job, and
with saveas a file stream.
- The three load verbs may be called several times and merge in order
(later values win); the top-level
data field (Section 4.5) also
works, with verbs taking precedence.
- Units are millimeters (floating point); element fields are fully
isomorphic with template elements (Chapter 7).
6.2 Verb overview
| Verb |
Purpose |
Lodop equivalent |
init |
Task naming |
PRINT_INIT |
loadData / loadJSON / loadURL |
Data loading (server-side) |
— (WxPrint’s own) |
pagesize |
Page size and paper semantics |
SET_PRINT_PAGESIZE |
add_text |
Text element |
ADD_PRINT_TEXT |
add_html |
HTML fragment element (Twig syntax) |
ADD_PRINT_HTM |
add_table |
Table element |
ADD_PRINT_TABLE |
add_barcode / add_qrcode |
Barcode / QR code |
ADD_PRINT_BARCODE/QRCODE |
add_image / add_rect / add_line / add_chart |
Image / rectangle / line / chart |
ADD_PRINT_IMAGE/RECT/LINE |
set_style / set_stylea |
Default style / per-element override |
SET_PRINT_STYLE(A) |
newpage |
Force a page break |
NEWPAGE |
print / preview / saveas |
Output |
PRINT / PRINT_PREVIEW / SAVEAS |
6.3 Verb-by-verb parameters
init
| Parameter |
Type |
Description |
task_name |
string |
Task name (shown in the system print queue) |
pagesize
| Parameter |
Type |
Default |
Description |
width_mm / height_mm |
number |
— |
Page width/height; height_mm: 0 = fit content height (common for labels) |
orientation |
string |
portrait |
portrait / landscape |
continuous |
bool |
false |
Continuous feeding (gap-free pages, waybill/receipt rolls) |
loadData / loadJSON / loadURL
| Verb |
Parameters |
Description |
loadData |
{data: {…}} |
Inline data; array = batch |
loadJSON |
{json: "…"} or {path: "…"} |
JSON text; path is a server-side file (restricted to ~/.wxprint/data/ by default) |
loadURL |
{url, headers?, timeout_s?} |
Fetched at run time (headers pass auth through) |
add_text
| Parameter |
Type |
Default |
Description |
x, y, w, h |
number |
— |
Element box (mm) |
text |
string |
— |
Content with {{variables}} and filters (Section 7.6), \n line breaks |
font.family |
string |
"" |
Font family; empty = system default stack; alternates list allowed, e.g. "Noto Sans CJK SC, SimHei" |
font.size_pt |
number |
10 |
Font size (points) |
font.weight |
int |
400 |
Weight (700 = bold) |
font.italic / font.underline |
bool |
false |
Italic / underline |
font.color |
string |
"#000000" |
Foreground (#rrggbb) |
align / valign |
string |
left / top |
In-box alignment (left/center/right; top/middle/bottom) |
origin |
string |
top-left |
y semantics: top-left box top / baseline first-line baseline (fits grid lines) |
overflow |
string |
shrink |
Overlong handling: shrink auto font-shrink / clip / wrap |
rotate |
number |
0 |
Rotation (degrees, clockwise around the box center) |
scope |
string |
body |
page-header/page-footer (every page) / first-page/last-page |
id |
string |
— |
Element identifier (anchor/reference) |
add_html
| Parameter |
Type |
Description |
x, y, w, h |
number |
Element box (mm) |
html |
string |
Accepts Twig syntax directly ({{ }}/{% for %}/filters, rendered server-side before layout) |
base_url |
string |
Base for resolving relative assets (optional) |
add_table
| Parameter |
Type |
Default |
Description |
x, y, w |
number |
— |
Table position and total width (mm) |
columns |
array |
— |
[{header, key, width, align}]: label / data key / width fraction (sum = 1) / alignment |
rows |
string |
— |
Array variable binding, e.g. "{{items}}"; cells support variables and filters |
row_height_mm |
number |
6 |
Row height |
header_rows |
int |
1 |
Header row count |
grid |
object |
— |
{stroke_mm, color} grid lines |
font |
object |
— |
Table font (as add_text’s font) |
| zebra |
|
|
odd_color/even_color alternating row backgrounds |
add_barcode / add_qrcode
| Parameter |
Type |
Description |
symbology |
string |
Barcode symbology: code128 / ean13 / ean8 / code39 / itf14 / upca |
content |
string |
Content (variables allowed) |
w, h (barcode) / size (QR) |
number |
Target physical size (mm); module widths snap to device pixels |
show_text / text_size_pt |
bool / number |
Human-readable text under the barcode |
ec_level (QR) |
string |
Error correction L(7%) / M(15%) / Q(25%) / H(30%) |
quiet_zone_mm (QR) |
number |
Quiet-zone margin |
add_image / add_rect / add_line / add_chart
| Verb |
Key parameters |
add_image |
src (asset path / http(s) / data: URL), fit (contain / stretch) |
add_rect |
stroke_mm border, fill color, corner_mm rounding, border color |
add_line |
stroke_mm, color, dash (e.g. [2,1] dashed) |
add_chart |
kind (13 types: bar/hbar/line/pie/funnel/gauge/radar/scatter/histogram/candlestick/parallel/polar_bar/theme_river), categories/series bindings, show_legend/title/theme |
set_style / set_stylea
| Verb |
Parameters |
Description |
set_style |
style fields (font/align/overflow, …) |
Becomes the default for subsequent elements |
set_stylea |
{id: "…", …style fields} |
Per-element override by id (or index) |
print / preview / saveas
| Verb |
Parameters |
Description |
print |
{printer?, copies?, copies_per_record?, collate?, pages?, task_name?} |
As REST /api/print |
preview |
— |
As REST preview: true |
saveas |
{format: "pdf"|"png"|"zip"} |
As REST /api/saveas |
6.4 Complete examples
curl (delivery note: URL data + text + barcode + footer page numbers + a second-page HTML table):
curl -s -X POST http://127.0.0.1:8899/api/script \
-H "Content-Type: application/json" -d '{
"script": [
["init", {"task_name": "Delivery note"}],
["loadURL", {"url": "https://erp.example.com/api/order/SO-1024"}],
["pagesize", {"width_mm": 210, "height_mm": 297}],
["add_text", {"id": "title", "x": 20, "y": 15, "w": 80, "h": 8,
"text": "{{title}}", "font": {"size_pt": 16, "weight": 700}}],
["add_barcode", {"x": 20, "y": 30, "w": 60, "h": 10,
"symbology": "code128", "content": "{{order_no}}"}],
["add_text", {"id": "footer", "x": 20, "y": 285, "w": 60, "h": 5,
"text": "Page {{page}} of {{pages}}", "scope": "page-footer",
"font": {"size_pt": 8}}],
["newpage", {}],
["add_html", {"x": 0, "y": 0, "w": 210, "h": 297,
"html": "<table border=\"1\" cellpadding=\"4\">{% for it in items %}<tr><td>{{it.name}}</td><td>{{it.qty}}</td></tr>{% endfor %}</table>"}],
["print", {"printer": "HP-LaserJet-M1005", "copies": 2}]
]}'
JS SDK (equivalent chained form):
const doc = wp.document();
doc.init("Delivery note")
.loadURL("https://erp.example.com/api/order/SO-1024")
.pagesize(210, 297)
.addText({ id: "title", x: 20, y: 15, w: 80, h: 8, text: "{{title}}",
font: { size_pt: 16, weight: 700 } })
.addBarcode({ x: 20, y: 30, w: 60, h: 10,
symbology: "code128", content: "{{order_no}}" })
.addText({ id: "footer", x: 20, y: 285, w: 60, h: 5,
text: "Page {{page}} of {{pages}}", scope: "page-footer",
font: { size_pt: 8 } })
.newpage()
.addHtml({ x: 0, y: 0, w: 210, h: 297,
html: '<table border="1" cellpadding="4">{% for it in items %}<tr><td>{{it.name}}</td></tr>{% endfor %}</table>' });
await doc.print({ printer: "HP-LaserJet-M1005", copies: 2 });
6.5 When to use the script API
| Scenario |
Recommendation |
| Fixed layout, long-term reuse (waybills/invoices/labels) |
Declarative template (made in the designer) referenced by id |
| Layout assembled dynamically by business code (columns/elements varying by document type) |
Script API |
| Programmatic building inside a web page |
The SDK’s wp.document() chained builder |
| Manual migration from Lodop code |
Rewrite item by item against the verb matrix in lodop-parity.md (coordinates convert directly from 0.1mm to mm) |