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
- Open your profile and create an API token (up to 10 active tokens per account). The token is shown once - copy it immediately.
- For MCP, add
https://tidybox.eu/mcp/<token>as a custom connector. - 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 withContent-Type: application/json. - Every response carries
ok(trueorfalse). Errors carryerror(a machine code from the Errors table) and usually a humanmessage. POSTbodies are JSON objects. Numbers and booleans must be real JSON types, not strings.GETparameters go in the query string; integers, numbers and booleans (true,false,1,0) are converted by the server.- Rate limit: 10
POSTand 60GETrequests per minute, per IP and per account. Over the limit you get HTTP 429rate_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
| Collection | Batch | |
|---|---|---|
| What it is | A named set of codes that belong together (one storage unit, one customer, one move). | Independent codes with no container (collection_id stays empty). |
| Numbers | Always 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. |
| Size | 2 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. |
| Serial | TB-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. |
| Outputs | A4 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.
| id | Grid | Cells per sheet | Label size, mm | Default copies | Max sheets |
|---|---|---|---|---|---|
sc | 3 x 4 | 12 | 63.5 x 72 | 1 in the catalogue; the API and the website default sc to 2 | 10 |
mv | 3 x 5 | 15 | 70 x 50.8 | 3 | 10 |
mid | 3 x 7 | 21 | 63.5 x 38.1 | 1 | 10 |
mini | 4 x 10 | 40 | 52.5 x 29.7 | 1 | 10 |
xl | 2 x 4 | 8 | 105 x 74 | 1 | 10 |
mix | 2 x 4 | 72 unique over 4 sheets | 105 x 74 | 1, fixed | 4, 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_preset | Width x height, mm | Notes |
|---|---|---|
shipping-100-150 | 100 x 150 | Portrait |
square-100-100 | 100 x 100 | Portrait |
label-100-90 | 100 x 90 | Landscape |
wide-100-50 | 100 x 50 | Landscape |
brother-ql-62 | 62 x continuous | Brother QL continuous tape; height is measured from the content |
dymo-89-36 | 89 x 36 | Dymo address label, landscape |
dymo-54-101 | 54 x 101 | Dymo shipping label, portrait |
mini-50-30 | 50 x 30 | Minimal: QR and number only, no header or logo |
mini-40-30 | 40 x 30 | Minimal: QR and number only |
custom | 20 to 120 x 20 to 300 | Pass 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 forsc, otherwise the layout default (1 for roll).sheets: 1 to 10 A4 sheets for a print collection. Unique codes are derived fromlayout x copies x sheets; do not passcountfor A4 collections.- Print batches derive pages from
count x copies; do not passsheets. - 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=trueapplies 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 totrue(account default brand); batches and ZIP collections default tofalse.white_label=trueprints 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). Defaultfalse. Optionalwl_spec(bg,header_text,header_color,logo) overrides the design for one run.- Results echo
brand_id,branding_applied,branding_binding_idandbrand_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=falseexists 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:
- Poll the status of the collection or export until
done/status=ready. - Open the returned
pdf_url,zip_urlordownload_url. These links are signed, expire (PDF exports after 7 days) and need no Authorization header. - Keep
collection_id,batch_idandserialin your own records.
MCP
Connecting
| Client | How |
|---|---|
| Claude Desktop | Settings > Connectors > Add custom connector > paste https://tidybox.eu/mcp/<token> |
| Claude Code | claude mcp add --transport http tidybox https://tidybox.eu/mcp/<token> |
| Codex and other clients | Remote 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
| Tool | Purpose | Key arguments | Returns |
|---|---|---|---|
list_print_layouts | Catalogue of A4 layouts and roll presets. | media (a4, roll, all) | layouts, roll_presets, custom_bounds |
quote_print_collection | Cost and sticker count of a print collection before creating it. | layout, copies, sheets or media=roll, roll_preset, count; white_label, brand_id | unique, stickers, blanks, pages, wl_available, wl_cost |
create_print_collection | One numbered print collection (A4 or roll) with a PDF. | as quote plus name, branding, white_label, wl_spec, brand_id | collection_id, serial, unique, print |
create_print_collection_bulk | Up to 100 identical print collections in one call. | quantity, name_prefix, same print options | collections[] with collection_id, serial, name |
collection_status | Progress of any collection; returns the signed pdf_url or zip_url when ready. | collection_id | generated, total, done, export_status, pdf_url, zip_url |
list_collections | Collections owned by the token account, newest first. | limit, offset | collections[] |
create_collection | One ZIP collection of PNG codes (no paper layout). | count, name, colored, brand_id, branding, white_label | collection_id, serial, total |
create_collections_bulk | Up to 200 ZIP collections in one call. | quantity, count, name_prefix, colored | collections[] |
export_collection | Free re-export of an existing collection as A4, roll or PNG ZIP. | collection_id, format (pdf, png-zip), media, layout, roll_preset, copies, design_hash | export_id, status, download_url when ready |
export_status | Inspect an export, a collection or a batch without creating anything. Pass exactly one of export_id, collection_id, batch_id. | one id | status, download_url, last_spec, design_groups |
quote_print_batch | Cost and pages of a print batch. | count, media, layout or roll_preset, copies, numbered | unique, pages, quota_cost, wl_cost |
create_print_batch | Independent codes plus a printable PDF (A4 or roll), numbered or plain. | as quote plus batch_name, prefix, brand_id, branding, white_label, wl_spec | batch_id, export_id, status, download_url when ready |
export_batch | Free re-export of an existing batch. | batch_id, format, media, layout, roll_preset, copies, numbered, design_hash | export_id, status, download_url when ready |
create_batch | Up to 100 codes immediately, PNG ZIP, no paper layout. | count, prefix, batch_name, style_json, accent_color, numbered | uids[], batch_id, zip_url |
create_code | One code immediately. | name, style_json | code, url, png_url |
list_brands | The account's brand library. | include_archived | brands[], default_brand_id, ready |
Typical conversations
- "Make 30 numbered stickers for unit A12 on SC paper, two per box":
quote_print_collectionthencreate_print_collection(layout=sc,copies=2,sheets=5), pollcollection_status, openpdf_url. - "Print 40 labels on my Brother QL-700":
list_print_layouts(media=roll), thencreate_print_collectionwithmedia=roll,roll_preset=brother-ql-62,count=40. - "I need 200 plain QR labels without numbers, 100 x 50":
create_print_batchwithcount=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), pollexport_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.
| Name | Type | Required | Description |
|---|---|---|---|
media | string (query) | no | a4 (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.
| Name | Type | Required | Description |
|---|---|---|---|
media | string (query) | no | a4 (default) or roll |
layout | string (query) | no | A4 layout id, default sc |
copies | integer (query) | no | 1 to 3 |
sheets | integer (query) | no | 1 to 10 (A4) |
roll_preset | string (query) | roll | Preset id or custom |
custom_width_mm, custom_height_mm | number (query) | custom | Label size in mm |
count | integer (query) | roll | 2 to 1024 unique codes |
white_label | boolean (query) | no | Echoed back; the quote always includes the white-label balance |
brand_id | integer (query) | no | Own 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.
| Name | Type | Required | Description |
|---|---|---|---|
name | string (body) | no | Shown in the dashboard, max 200 characters |
media | string (body) | no | a4 (default) or roll |
layout | string (body) | no | sc, mv, mid, mini, xl, mix |
copies | integer (body) | no | 1 to 3 |
sheets | integer (body) | no | 1 to 10, A4 only |
roll_preset, custom_width_mm, custom_height_mm, count | see quote (body) | roll | Roll options |
brand_id | integer (body) | no | Own brand; omitted = account default brand |
branding | boolean (body) | no | Default true |
white_label | boolean (body) | no | Default false |
wl_spec | object (body) | no | bg, header_text, header_color, logo |
webhook_url | string (body) | no | Reserved; 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.
| Name | Type | Required | Description |
|---|---|---|---|
quantity | integer (body) | yes | 1 to 100 |
name_prefix | string (body) | yes | Names become <prefix> 001, <prefix> 002, ... |
| print options | as above (body) | no | Same 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.
| Name | Type | Required | Description |
|---|---|---|---|
include_archived | boolean (query) | no | Default 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.
| Name | Type | Required | Description |
|---|---|---|---|
count | integer (query) | yes | 1 to 1024 unique codes |
media | string (query) | no | a4 (default) or roll |
layout | string (query) | no | A4 layout id, default sc |
roll_preset, custom_width_mm, custom_height_mm | see above (query) | roll | Roll options |
copies | integer (query) | no | 1 to 3, default 1 |
numbered | boolean (query) | no | Default true |
white_label, brand_id, branding | see above (query) | no | Brand 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.
| Name | Type | Required | Description |
|---|---|---|---|
count | integer (body) | yes | 1 to 1024 |
batch_name | string (body) | no | Dashboard name, max 200 |
prefix | string (body) | no | Code names <prefix>-001, ... (independent from printed numbers) |
media, layout, roll_preset, custom_width_mm, custom_height_mm, copies, numbered | as quote (body) | no | Print options |
brand_id, branding, white_label, wl_spec | as above (body) | no | Brand 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.
| Name | Type | Required | Description |
|---|---|---|---|
format | string (body) | yes | pdf or png-zip |
media | string (body) | a4 (default) or roll | |
layout, roll_preset, custom_width_mm, custom_height_mm, copies | as above (body) | no | Print options (omit all for png-zip) |
numbered | boolean (body) | no | Default true; false re-renders plain centred labels |
design_hash | string (body) | no | Only 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.
| Name | Type | Required | Description |
|---|---|---|---|
count | integer (body) | yes | 1 to 100 |
prefix | string (body) | no | Code name prefix |
batch_name | string (body) | no | Dashboard name |
style_json | string (body) | no | QR style as a JSON string, for example {"fgColor":"#062028","bgColor":"#ffffff"} |
accent_color | string (body) | no | #rrggbb accent for the scan pages |
numbered | boolean (body) | no | Omit for the historical plain PNG; true prints numbers |
brand_id, branding, white_label, wl_spec | as above (body) | no | Brand 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.
| Name | Type | Required | Description |
|---|---|---|---|
name | string (body) | no | Stored as <name>-001 |
style_json | string (body) | no | QR 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.
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer (query) | no | 1 to 100, default 20 |
offset | integer (query) | no | Default 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).
| Name | Type | Required | Description |
|---|---|---|---|
count | integer (body) | yes | 2 to 1024 |
name | string (body) | yes | Collection name |
colored | boolean (body) | no | Default true; false renders black on white |
numbered | boolean (body) | no | Only true is accepted |
brand_id, branding, white_label, wl_spec | as above (body) | no | Brand 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.
| Name | Type | Required | Description |
|---|---|---|---|
quantity | integer (body) | yes | 1 to 200 |
count | integer (body) | yes | 2 to 1024 codes per collection |
name_prefix | string (body) | yes | Names become <prefix> 001, ... |
colored, brand_id, branding, white_label, wl_spec | as above (body) | no | Options |
{"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.
| Name | Type | Required | Description |
|---|---|---|---|
format | string (body) | yes | pdf or png-zip |
media | string (body) | a4 or roll | |
layout, roll_preset, custom_width_mm, custom_height_mm, copies | as above (body) | no | Print options (omit all for png-zip) |
design_hash | string (body) | no | Only after mixed_brand_export |
confirm_existing, expected_unique | boolean, integer (body) | legacy | Only 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
| Status | Meaning |
|---|---|
generating | Codes are still being created (generated < total). Poll every few seconds. |
queued, rendering | The PDF or ZIP is in the render queue. Typical wait is seconds to a minute for large runs. |
ready | download_url / pdf_url / zip_url is available. |
failed | error names the reason; re-request the export with corrected options. |
export_failed with created: true | The 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
| HTTP | error | Meaning and what to do |
|---|---|---|
| 400 | bad_request | A parameter failed validation; message says which. |
| 400 | bad_json | The body is not a JSON object. |
| 400 | quota | Not enough code quota: available, limit, unique are included. Top up or reduce the run. |
| 400 | batch_cap | More codes than the plan allows per batch. |
| 400 | unknown_layout, bad_copies, bad_sheets, bad_count, bad_media, bad_roll_preset, bad_dimensions | A print option is out of range. See Concepts. |
| 400 | conflicting_options | Options that do not belong together, for example layout with media=roll or sheets on a batch. |
| 400 | label_too_small | The label cannot fit the QR and margins at print resolution. |
| 400 | bad_format, bad_numbered, bad_branding, bad_design_hash | Wrong type or value for that field. |
| 400 | white_label_unavailable | reason 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. |
| 400 | bad_brand_id, brand_not_ready, brand_required | Brand selection problem; see message. |
| 401 | auth | Missing, revoked or non-Business token. |
| 403 | need_business | The action needs an active Business subscription. |
| 404 | not_found, brand_not_found, artifact_missing | Unknown id, foreign resource or a download that expired and was removed. |
| 405 | method | Wrong HTTP method; the Allow header lists valid ones. |
| 409 | numbers_required | Collections (and batches containing collection codes) must be exported with numbered=true. |
| 409 | mixed_brand_export | The set contains several saved designs; groups[] lists them. Export one design_hash per PDF. |
| 409 | collection_pending, export_busy, source_changed | The source is still changing or another export is running; retry shortly. |
| 409 | brand_archived, brand_version_conflict | The brand changed or is archived; pick another brand. |
| 410 | expired | The export has expired; request a new one. |
| 413 | resource_limit | The run exceeds the renderer limit (1024 labels). |
| 429 | rate_limit | Slow down to 10 POST / 60 GET per minute. |
| 503 | schema_missing, renderer_unavailable, storage_unavailable | Server-side feature temporarily unavailable; retry later and contact support if it persists. |
| 500 | internal, export_failed, batch_create_failed | Unexpected 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.