Skip to main content

TidyBox API and MCP reference

Overview

TidyBox exposes the same label-generation engine that powers the website in two ways:

  • MCP (Model Context Protocol) for AI assistants such as Claude Desktop, Claude Code and Codex. Your assistant calls the tools listed below from a normal chat.
  • REST (https://tidybox.eu/api/v1/...) for your own scripts and systems.

Both are available on the Business plan (and to administrators). Every REST route maps to exactly one MCP tool, so whatever your assistant can do, your code can do too.

Tokens

  1. Open your profile and create an API token (up to 10 active tokens per account). The token is shown once - copy it immediately.
  2. For MCP, add https://tidybox.eu/mcp/<token> as a custom connector.
  3. For REST, send the token in the Authorization: Bearer <token> header.

Tokens stop working as soon as the account leaves the Business plan. Revoke a token from the profile at any time.

Never put the token in a URL, in a chat message or in a shared log. Download links returned by the API are signed and time-limited and open without any token.

Conventions

  • Base URL: https://tidybox.eu. All responses are JSON with Content-Type: application/json.
  • Every response carries ok (true or false). Errors carry error (a machine code from the Errors table) and usually a human message.
  • POST bodies are JSON objects. Numbers and booleans must be real JSON types, not strings.
  • GET parameters go in the query string; integers, numbers and booleans (true, false, 1, 0) are converted by the server.
  • Rate limit: 10 POST and 60 GET requests per minute, per IP and per account. Over the limit you get HTTP 429 rate_limit.
  • Quota: unique codes are deducted from the account's monthly allowance and purchased packs. Copies, sheets, re-exports and the numbered flag never cost codes.

Concepts

Collections and batches

CollectionBatch
What it isA named set of codes that belong together (one storage unit, one customer, one move).Independent codes with no container (collection_id stays empty).
NumbersAlways printed (box 01, 02, ...). numbered=false is rejected with numbers_required.Optional. numbered=true (default) prints a number in a white cut-out in the centre of the QR; false centres the QR with no badge.
Size2 to 1024 unique codes.1 to 1024 unique codes per print batch (the Business plan caps a batch at 1000); up to 100 per synchronous create_batch call.
SerialTB-DDMMYY-NNN, printed on A4 sheets (serial-A, serial-B, ...) and returned by every call. Keep it in your records.No serial. The printed numbers are the stable identity.
OutputsA4 PDF, thermal roll PDF, PNG ZIP.A4 PDF, thermal roll PDF, PNG ZIP.

A4 layouts

A4 sheets use standard self-adhesive label paper. unique codes per sheet = cells / copies.

idGridCells per sheetLabel size, mmDefault copiesMax sheets
sc3 x 41263.5 x 721 in the catalogue; the API and the website default sc to 210
mv3 x 51570 x 50.8310
mid3 x 72163.5 x 38.1110
mini4 x 104052.5 x 29.7110
xl2 x 48105 x 74110
mix2 x 472 unique over 4 sheets105 x 741, fixed4, fixed

copies (1 to 3) is how many identical stickers each code gets, for example one per side of a box. Copies multiply stickers and pages, never the code cost. GET /api/v1/print-layouts returns the catalogue with paper references.

Thermal roll labels

Pass media=roll with a roll_preset. Roll output is monochrome (black on white), the number sits in a round white cut-out in the centre of the QR, and the collection serial is not printed on the label. If the label is wider than it is tall, the artwork is rotated 90 degrees inside the PDF; the physical page size is not swapped.

roll_presetWidth x height, mmNotes
shipping-100-150100 x 150Portrait
square-100-100100 x 100Portrait
label-100-90100 x 90Landscape
wide-100-50100 x 50Landscape
brother-ql-6262 x continuousBrother QL continuous tape; height is measured from the content
dymo-89-3689 x 36Dymo address label, landscape
dymo-54-10154 x 101Dymo shipping label, portrait
mini-50-3050 x 30Minimal: QR and number only, no header or logo
mini-40-3040 x 30Minimal: QR and number only
custom20 to 120 x 20 to 300Pass custom_width_mm and custom_height_mm (up to three decimals)

Roll creation needs count (2 to 1024 unique codes for collections, 1 to 1024 for batches). Do not pass layout or sheets with media=roll. Quote first: the quote returns the measured content size and fails with label_too_small when the QR and margins cannot fit.

Copies, sheets and numbering

  • copies: 1 to 3 stickers per unique code. Default 2 for sc, otherwise the layout default (1 for roll).
  • sheets: 1 to 10 A4 sheets for a print collection. Unique codes are derived from layout x copies x sheets; do not pass count for A4 collections.
  • Print batches derive pages from count x copies; do not pass sheets.
  • Collections are always numbered. Batches accept numbered=false. A batch that contains codes later moved into a collection must be re-exported with numbers (numbers_required).

Brands, branding and white-label

A brand is a saved set of scan-page settings (public name, logo, welcome text, "Buy more" link) plus an optional sticker design. Brands are created in the profile; the API only selects one by brand_id.

  • branding=true applies the brand's scan page to every QR of the run live: editing the brand later updates all its linked scan pages. Print collections default to true (account default brand); batches and ZIP collections default to false.
  • white_label=true prints the brand's own frame colour, header text and footer logo on the sticker instead of the TidyBox artwork. The design is frozen at creation and costs one purchased white-label code per unique code (packs of 100 for EUR 20). Default false. Optional wl_spec (bg, header_text, header_color, logo) overrides the design for one run.
  • Results echo brand_id, branding_applied, branding_binding_id and brand_version_at_issue (the version frozen for this run, not the brand's live version).

Colour

  • A4 sheets are always in colour: each code gets its collection colour and a numbered badge.
  • Roll labels are always monochrome.
  • colored=false exists only for ZIP collections (create_collection, POST /api/v1/collections): the PNG codes are then black on white.

Serials and polling

Creation calls return immediately. Code generation and PDF rendering happen in the background:

  1. Poll the status of the collection or export until done / status=ready.
  2. Open the returned pdf_url, zip_url or download_url. These links are signed, expire (PDF exports after 7 days) and need no Authorization header.
  3. Keep collection_id, batch_id and serial in your own records.

MCP

Connecting

ClientHow
Claude DesktopSettings > Connectors > Add custom connector > paste https://tidybox.eu/mcp/<token>
Claude Codeclaude mcp add --transport http tidybox https://tidybox.eu/mcp/<token>
Codex and other clientsRemote MCP server over HTTP (JSON-RPC, stateless POST) at https://tidybox.eu/mcp with Authorization: Bearer <token>, or the /mcp/<token> form

The server implements initialize, tools/list and tools/call. The server instructions tell the assistant which tool to pick; you only describe what you need.

Tools

ToolPurposeKey argumentsReturns
list_print_layoutsCatalogue of A4 layouts and roll presets.media (a4, roll, all)layouts, roll_presets, custom_bounds
quote_print_collectionCost and sticker count of a print collection before creating it.layout, copies, sheets or media=roll, roll_preset, count; white_label, brand_idunique, stickers, blanks, pages, wl_available, wl_cost
create_print_collectionOne numbered print collection (A4 or roll) with a PDF.as quote plus name, branding, white_label, wl_spec, brand_idcollection_id, serial, unique, print
create_print_collection_bulkUp to 100 identical print collections in one call.quantity, name_prefix, same print optionscollections[] with collection_id, serial, name
collection_statusProgress of any collection; returns the signed pdf_url or zip_url when ready.collection_idgenerated, total, done, export_status, pdf_url, zip_url
list_collectionsCollections owned by the token account, newest first.limit, offsetcollections[]
create_collectionOne ZIP collection of PNG codes (no paper layout).count, name, colored, brand_id, branding, white_labelcollection_id, serial, total
create_collections_bulkUp to 200 ZIP collections in one call.quantity, count, name_prefix, coloredcollections[]
export_collectionFree re-export of an existing collection as A4, roll or PNG ZIP.collection_id, format (pdf, png-zip), media, layout, roll_preset, copies, design_hashexport_id, status, download_url when ready
export_statusInspect an export, a collection or a batch without creating anything. Pass exactly one of export_id, collection_id, batch_id.one idstatus, download_url, last_spec, design_groups
quote_print_batchCost and pages of a print batch.count, media, layout or roll_preset, copies, numberedunique, pages, quota_cost, wl_cost
create_print_batchIndependent codes plus a printable PDF (A4 or roll), numbered or plain.as quote plus batch_name, prefix, brand_id, branding, white_label, wl_specbatch_id, export_id, status, download_url when ready
export_batchFree re-export of an existing batch.batch_id, format, media, layout, roll_preset, copies, numbered, design_hashexport_id, status, download_url when ready
create_batchUp to 100 codes immediately, PNG ZIP, no paper layout.count, prefix, batch_name, style_json, accent_color, numbereduids[], batch_id, zip_url
create_codeOne code immediately.name, style_jsoncode, url, png_url
list_brandsThe account's brand library.include_archivedbrands[], default_brand_id, ready

Typical conversations

  • "Make 30 numbered stickers for unit A12 on SC paper, two per box": quote_print_collection then create_print_collection (layout=sc, copies=2, sheets=5), poll collection_status, open pdf_url.
  • "Print 40 labels on my Brother QL-700": list_print_layouts(media=roll), then create_print_collection with media=roll, roll_preset=brother-ql-62, count=40.
  • "I need 200 plain QR labels without numbers, 100 x 50": create_print_batch with count=200, media=roll, roll_preset=wide-100-50, numbered=false.
  • "Re-print collection 512 on MID paper": export_collection(collection_id=512, format=pdf, media=a4, layout=mid), poll export_status(export_id).
  • "Ten identical sets for ten new tenants": create_print_collection_bulk(quantity=10, name_prefix="Tenant").

REST

Conventions

Each route below lists its parameters, an example request and the shape of the response. Parameters marked body are JSON fields of a POST; parameters marked query belong to a GET query string. Ids in the path ({id}, {export_id}) always win over the same field in the body.

Status codes: 200 for reads and quotes, 201 for synchronous creation (/batches, /codes), 202 when work continues in the background (collections, print batches, exports). Errors use the codes in the Errors table.

# Every example assumes
export TB_TOKEN="paste-your-token-here"
export TB="https://tidybox.eu/api/v1"

GET /api/v1/print-layouts

A4 layouts and roll presets.

NameTypeRequiredDescription
mediastring (query)noa4 (default), roll or all
curl -H "Authorization: Bearer $TB_TOKEN" "$TB/print-layouts?media=all"
{
  "ok": true,
  "layouts": [{"id": "sc", "cols": 3, "rows": 4, "cells": 12, "default_copies": 1, "max_sheets": 10, "paper_refs": [{"key": "print.paper.avery_l7164", "url": "https://..."}]}],
  "roll_presets": [{"id": "brother-ql-62", "width_mm": 62, "height_mm": null, "composition": "portrait", "omitted_elements": ["serial"]}],
  "custom_bounds": {"min_width_mm": 20, "max_width_mm": 120, "min_height_mm": 20, "max_height_mm": 300}
}

GET /api/v1/print-quote

Quote a print collection. Nothing is created or charged.

NameTypeRequiredDescription
mediastring (query)noa4 (default) or roll
layoutstring (query)noA4 layout id, default sc
copiesinteger (query)no1 to 3
sheetsinteger (query)no1 to 10 (A4)
roll_presetstring (query)rollPreset id or custom
custom_width_mm, custom_height_mmnumber (query)customLabel size in mm
countinteger (query)roll2 to 1024 unique codes
white_labelboolean (query)noEchoed back; the quote always includes the white-label balance
brand_idinteger (query)noOwn brand id
curl -H "Authorization: Bearer $TB_TOKEN" "$TB/print-quote?layout=mid&copies=1&sheets=2"
{"ok": true, "layout_id": "mid", "copies": 1, "sheets": 2, "unique": 42, "stickers": 42, "blanks": 0, "pages": 2, "price_cents": 420, "wl_available": 0, "wl_unlimited": false, "wl_configured": false, "wl_cost": 42}

POST /api/v1/print-collections

Create one print collection. Codes are generated and the PDF is rendered in the background.

NameTypeRequiredDescription
namestring (body)noShown in the dashboard, max 200 characters
mediastring (body)noa4 (default) or roll
layoutstring (body)nosc, mv, mid, mini, xl, mix
copiesinteger (body)no1 to 3
sheetsinteger (body)no1 to 10, A4 only
roll_preset, custom_width_mm, custom_height_mm, countsee quote (body)rollRoll options
brand_idinteger (body)noOwn brand; omitted = account default brand
brandingboolean (body)noDefault true
white_labelboolean (body)noDefault false
wl_specobject (body)nobg, header_text, header_color, logo
webhook_urlstring (body)noReserved; validated, not called yet
curl -X POST -H "Authorization: Bearer $TB_TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "Unit A12", "layout": "sc", "copies": 2, "sheets": 3}' "$TB/print-collections"
{"ok": true, "created": true, "collection_id": 512, "serial": "TB-161026-007", "unique": 18, "status": "generating", "print": {"layout": "sc", "copies": 2, "sheets": 3}, "branding": true, "white_label": false, "brand_id": 4, "branding_applied": true, "branding_binding_id": 91, "brand_version_at_issue": 3}

Roll example:

curl -X POST -H "Authorization: Bearer $TB_TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "Shelf labels", "media": "roll", "roll_preset": "brother-ql-62", "count": 40}' "$TB/print-collections"

POST /api/v1/print-collections/bulk

Up to 100 identical print collections in one call. The quota for the whole bulk is checked first; a shortfall creates nothing.

NameTypeRequiredDescription
quantityinteger (body)yes1 to 100
name_prefixstring (body)yesNames become <prefix> 001, <prefix> 002, ...
print optionsas above (body)noSame layout, copies, sheets or roll options for every collection
{"ok": true, "collections": [{"collection_id": 513, "serial": "TB-161026-008", "name": "Tenant 001"}], "quantity": 10, "created": 10, "unique_per": 6, "status": "generating", "print": {"layout": "sc", "copies": 2, "sheets": 1}}

GET /api/v1/print-collections/{id}

Progress of a print collection. Polling a stalled generation restarts it.

curl -H "Authorization: Bearer $TB_TOKEN" "$TB/print-collections/512"
{"ok": true, "collection_id": 512, "serial": "TB-161026-007", "generated": 18, "total": 18, "done": true, "status": "ready", "print": {"layout": "sc", "copies": 2, "sheets": 3, "unique": 18}, "export_status": "ready", "export_id": "3f1c...", "pdf_url": "https://tidybox.eu/php/label-export-http.php?...", "pdf_expires_at": "2026-10-23T09:00:00+00:00", "zip_url": "https://tidybox.eu/php/download-batch.php?..."}

done means the codes exist. Wait for export_status=ready and pdf_url before downloading. Roll collections add media, roll_preset, width_mm, height_mm and composition to print.

GET /api/v1/brands

The account's brand library (read-only). Brands are managed in the profile.

NameTypeRequiredDescription
include_archivedboolean (query)noDefault true
{"ok": true, "ready": true, "default_brand_id": 4, "brands": [{"id": 4, "internal_name": "Main brand", "status": "active", "is_default": true, "version": 3, "linked_qr_count": 240, "scan": {"brand_name": "Acme Storage", "ready": true}, "wl": {"ready": false}}]}

GET /api/v1/print-batch-quote

Quote a print batch of independent codes. Nothing is created.

NameTypeRequiredDescription
countinteger (query)yes1 to 1024 unique codes
mediastring (query)noa4 (default) or roll
layoutstring (query)noA4 layout id, default sc
roll_preset, custom_width_mm, custom_height_mmsee above (query)rollRoll options
copiesinteger (query)no1 to 3, default 1
numberedboolean (query)noDefault true
white_label, brand_id, brandingsee above (query)noBrand options
curl -H "Authorization: Bearer $TB_TOKEN" "$TB/print-batch-quote?count=200&media=roll&roll_preset=wide-100-50&numbered=false"
{"ok": true, "unique": 200, "quota_cost": 200, "wl_cost": 0, "print": {"media": "roll", "roll_preset": "wide-100-50", "copies": 1, "numbered": false, "width_mm": 100, "height_mm": 50, "composition": "landscape", "pages": 200}, "plan": "business", "batch_cap": 1000}

POST /api/v1/print-batches

Create independent codes and queue their PDF.

NameTypeRequiredDescription
countinteger (body)yes1 to 1024
batch_namestring (body)noDashboard name, max 200
prefixstring (body)noCode names <prefix>-001, ... (independent from printed numbers)
media, layout, roll_preset, custom_width_mm, custom_height_mm, copies, numberedas quote (body)noPrint options
brand_id, branding, white_label, wl_specas above (body)noBrand options; branding defaults to false for batches
curl -X POST -H "Authorization: Bearer $TB_TOKEN" -H "Content-Type: application/json" \
  -d '{"count": 200, "batch_name": "Plain labels", "media": "roll", "roll_preset": "wide-100-50", "numbered": false}' "$TB/print-batches"
{"ok": true, "created": true, "batch_id": 88, "unique": 200, "print": {"media": "roll", "roll_preset": "wide-100-50", "numbered": false, "copies": 1}, "quota_cost": 200, "wl_cost": 0, "status": "queued", "export_id": "9a7b...", "status_url": "https://tidybox.eu/php/export-status.php?export=..."}

If the response has created: true with status: "export_failed" and no export_id, the codes already exist: do not create the batch again. Call POST /api/v1/print-batches/{id}/exports with the same print options instead.

GET /api/v1/print-batches/{id}

Inspect a batch without creating anything: counts, whether numbers are required, the last print specification and the last ready export.

{"ok": true, "batch_id": 88, "name": "Plain labels", "unique": 200, "total": 200, "generated": 200, "generation_done": true, "numbers_required": false, "last_spec": {"media": "roll", "roll_preset": "wide-100-50", "numbered": false}, "last_export": {"export_id": "9a7b...", "status": "ready", "download_url": "https://tidybox.eu/php/label-export-http.php?..."}, "original_zip_url": "https://tidybox.eu/php/download-batch.php?..."}

POST /api/v1/print-batches/{id}/exports

Re-export an existing batch as PDF (A4 or roll) or PNG ZIP. Free: no codes are spent.

NameTypeRequiredDescription
formatstring (body)yespdf or png-zip
mediastring (body)pdfa4 (default) or roll
layout, roll_preset, custom_width_mm, custom_height_mm, copiesas above (body)noPrint options (omit all for png-zip)
numberedboolean (body)noDefault true; false re-renders plain centred labels
design_hashstring (body)noOnly after mixed_brand_export: one of the returned groups[].design_hash
curl -X POST -H "Authorization: Bearer $TB_TOKEN" -H "Content-Type: application/json" \
  -d '{"format": "pdf", "media": "a4", "layout": "mini", "numbered": true}' "$TB/print-batches/88/exports"
{"ok": true, "export_id": "c0de...", "batch_id": 88, "status": "queued", "unique": 200, "copies": 1, "pages": 5, "quota_cost": 0, "wl_cost": 0, "status_url": "https://tidybox.eu/php/export-status.php?export=...", "media": "a4", "layout": "mini", "numbered": true}

POST /api/v1/batches

Create up to 100 codes synchronously and get a PNG ZIP link. For printable sheets use /print-batches.

NameTypeRequiredDescription
countinteger (body)yes1 to 100
prefixstring (body)noCode name prefix
batch_namestring (body)noDashboard name
style_jsonstring (body)noQR style as a JSON string, for example {"fgColor":"#062028","bgColor":"#ffffff"}
accent_colorstring (body)no#rrggbb accent for the scan pages
numberedboolean (body)noOmit for the historical plain PNG; true prints numbers
brand_id, branding, white_label, wl_specas above (body)noBrand options
curl -X POST -H "Authorization: Bearer $TB_TOKEN" -H "Content-Type: application/json" \
  -d '{"count": 25, "prefix": "DOC"}' "$TB/batches"
{"ok": true, "uids": ["k3Fz9qLm", "..."], "batch_id": 89, "white_label": false, "zip_url": "https://tidybox.eu/php/download-batch.php?...", "brand_id": null, "branding_applied": false}

POST /api/v1/codes

Create a single code immediately.

NameTypeRequiredDescription
namestring (body)noStored as <name>-001
style_jsonstring (body)noQR style as a JSON string
{"ok": true, "code": "k3Fz9qLm", "url": "https://tidybox.eu/k3Fz9qLm", "png_url": "https://tidybox.eu/php/label-export-http.php?..."}

GET /api/v1/collections

Collections owned by the account, newest first.

NameTypeRequiredDescription
limitinteger (query)no1 to 100, default 20
offsetinteger (query)noDefault 0
{"ok": true, "collections": [{"collection_id": 512, "serial": "TB-161026-007", "name": "Unit A12", "total": 18, "generated": 18, "created_at": "2026-10-16 09:00:00", "white_label": false, "brand_id": 4, "branding_applied": true}]}

POST /api/v1/collections

Create a ZIP collection of PNG codes (no paper layout).

NameTypeRequiredDescription
countinteger (body)yes2 to 1024
namestring (body)yesCollection name
coloredboolean (body)noDefault true; false renders black on white
numberedboolean (body)noOnly true is accepted
brand_id, branding, white_label, wl_specas above (body)noBrand options; branding defaults to false
curl -X POST -H "Authorization: Bearer $TB_TOKEN" -H "Content-Type: application/json" \
  -d '{"count": 50, "name": "Archive boxes", "colored": false}' "$TB/collections"
{"ok": true, "collection_id": 514, "serial": "TB-161026-009", "total": 50, "white_label": false, "brand_id": null, "branding_applied": false}

POST /api/v1/collections/bulk

Up to 200 ZIP collections with the same code count.

NameTypeRequiredDescription
quantityinteger (body)yes1 to 200
countinteger (body)yes2 to 1024 codes per collection
name_prefixstring (body)yesNames become <prefix> 001, ...
colored, brand_id, branding, white_label, wl_specas above (body)noOptions
{"ok": true, "collections": [{"collection_id": 515, "serial": "TB-161026-010", "name": "Warehouse 001"}], "white_label": false}

GET /api/v1/collections/{id}

Status of any collection (ZIP or print). Same payload as GET /api/v1/print-collections/{id}; for ZIP collections zip_url appears once done is true.

GET /api/v1/collections/{id}/exports

Inspect a collection before exporting: code counts, generation_done, legacy_incomplete, design_groups (saved sticker designs present) and the last ready PDF export. Nothing is restarted.

{"ok": true, "collection_id": 512, "name": "Unit A12", "unique": 18, "total": 18, "generated": 18, "generation_done": true, "legacy_incomplete": false, "generation_busy": false, "creation_spec": {"media": "a4", "layout": "sc", "copies": 2}, "design_groups": [{"design_hash": "none", "white_label": false, "brand_id": 4, "count": 18}], "last_spec": {"media": "a4", "layout": "sc", "copies": 2}, "last_export": {"export_id": "3f1c...", "status": "ready", "download_url": "https://..."}}

POST /api/v1/collections/{id}/exports

Re-export an existing collection. Free: no codes or white-label codes are spent. Every box is re-printed with the sticker design saved when it was issued.

NameTypeRequiredDescription
formatstring (body)yespdf or png-zip
mediastring (body)pdfa4 or roll
layout, roll_preset, custom_width_mm, custom_height_mm, copiesas above (body)noPrint options (omit all for png-zip)
design_hashstring (body)noOnly after mixed_brand_export
confirm_existing, expected_uniqueboolean, integer (body)legacyOnly for a legacy_incomplete collection, after the user confirmed the current code count
curl -X POST -H "Authorization: Bearer $TB_TOKEN" -H "Content-Type: application/json" \
  -d '{"format": "pdf", "media": "roll", "roll_preset": "dymo-54-101"}' "$TB/collections/512/exports"
{"ok": true, "export_id": "77aa...", "collection_id": 512, "status": "queued", "unique": 18, "copies": 1, "pages": 18, "quota_cost": 0, "wl_cost": 0, "status_url": "https://...", "media": "roll", "roll_preset": "dymo-54-101", "width_mm": 54, "height_mm": 101, "composition": "portrait"}

GET /api/v1/exports/{export_id}

Poll an export. export_id is the 32-character id from an export response.

curl -H "Authorization: Bearer $TB_TOKEN" "$TB/exports/77aa0000000000000000000000000000"
{"ok": true, "export_id": "77aa...", "collection_id": 512, "status": "ready", "unique": 18, "copies": 1, "pages": 18, "quota_cost": 0, "wl_cost": 0, "download_url": "https://tidybox.eu/php/label-export-http.php?...", "expires_at": 1761814800}

Polling and downloads

StatusMeaning
generatingCodes are still being created (generated < total). Poll every few seconds.
queued, renderingThe PDF or ZIP is in the render queue. Typical wait is seconds to a minute for large runs.
readydownload_url / pdf_url / zip_url is available.
failederror names the reason; re-request the export with corrected options.
export_failed with created: trueThe codes exist. Re-export instead of creating again.

Download links are signed with an expiry and open without a token. A link that returns expired or source_changed needs a fresh status call or a fresh export.

Errors

HTTPerrorMeaning and what to do
400bad_requestA parameter failed validation; message says which.
400bad_jsonThe body is not a JSON object.
400quotaNot enough code quota: available, limit, unique are included. Top up or reduce the run.
400batch_capMore codes than the plan allows per batch.
400unknown_layout, bad_copies, bad_sheets, bad_count, bad_media, bad_roll_preset, bad_dimensionsA print option is out of range. See Concepts.
400conflicting_optionsOptions that do not belong together, for example layout with media=roll or sheets on a batch.
400label_too_smallThe label cannot fit the QR and margins at print resolution.
400bad_format, bad_numbered, bad_branding, bad_design_hashWrong type or value for that field.
400white_label_unavailablereason is one of not_business, not_configured, logo_not_raster, header_too_long, insufficient_wl_balance. Configure or top up in the profile, or retry with white_label=false.
400bad_brand_id, brand_not_ready, brand_requiredBrand selection problem; see message.
401authMissing, revoked or non-Business token.
403need_businessThe action needs an active Business subscription.
404not_found, brand_not_found, artifact_missingUnknown id, foreign resource or a download that expired and was removed.
405methodWrong HTTP method; the Allow header lists valid ones.
409numbers_requiredCollections (and batches containing collection codes) must be exported with numbered=true.
409mixed_brand_exportThe set contains several saved designs; groups[] lists them. Export one design_hash per PDF.
409collection_pending, export_busy, source_changedThe source is still changing or another export is running; retry shortly.
409brand_archived, brand_version_conflictThe brand changed or is archived; pick another brand.
410expiredThe export has expired; request a new one.
413resource_limitThe run exceeds the renderer limit (1024 labels).
429rate_limitSlow down to 10 POST / 60 GET per minute.
503schema_missing, renderer_unavailable, storage_unavailableServer-side feature temporarily unavailable; retry later and contact support if it persists.
500internal, export_failed, batch_create_failedUnexpected failure; nothing was charged unless created: true is present.

Changelog

  • 1.1 (2026-10-16) REST parity with MCP: print batches, synchronous batches and codes, ZIP collections, exports and export status. Thermal roll presets, numbering rules and colour rules documented.
  • 1.0 (2026-08-18) Print REST (/print-layouts, /print-quote, /print-collections, /print-collections/bulk, /print-collections/{id}) and the MCP print family.