PRO — $24.90/MO / 14-DAY PRO TRIAL ON SIGNUP

Label printing API

To print a label through a REST API, send POST https://labelinn.com/v1/print/jobs with a Bearer API key, a printer_id, a payload_type (template, zpl or image) and your data. The job is queued for the PC that runs the printer, which renders it in the printer's own language; poll GET /v1/print/jobs/{id} until the status is completed. API writes need the Pro plan; a sk_test_ key lets you build first without printing.

PRO PLAN · 14-DAY TRIAL · KEYS: SK_TEST AND SK_LIVE
PRINT CONTROLPRINTER READY
Label printing API — LabelInn
Native printer languagesZPL, TSPL, TPCL, ESC/Label
No driver to installUSB, network or Bluetooth
Every platformWindows, macOS, Android, web
Free to startNo credit card, 14-day Pro trial

01

Who this is for

SaaS and in-house developers who need their web or desktop application to reach a thermal label printer that they do not control.

02

Step by step

  1. Create an API key from your LabelInn account.
  2. Choose a direction: push a print job to the API, or configure a label to pull JSON from your own endpoint.
  3. Send a request to https://labelinn.com/v1/print/jobs with the design and the field values.
  4. Read the job status back, and subscribe to a webhook if you need completion events.

Try it with your own data — signing up starts a 14-day Pro trial, no credit card. After that this feature needs Pro at $24.90/mo. Download now → | See pricing →

03

What you can do

  • One request shape regardless of whether the target speaks ZPL, TSPL, TPCL or Epson.
  • A label can also be the client: point a field group at your JSON endpoint with Bearer, Basic or API-key auth.
  • Webhooks report job events back to your system instead of making you poll.
  • The same operations are exposed over MCP, so an AI agent can drive printing through the identical surface.

04

Technical details

Public API basehttps://labelinn.com/v1
Submit a print jobPOST /v1/print/jobs
Inbound data source authBearer, Basic or API key header
Two directionsYour app calls LabelInn, or a label pulls JSON from your endpoint
Agent accessAn MCP server exposes the same operations to AI agents

05

Limits and honest caveats

  • A physical printer still needs a LabelInn runtime near it: the PC that has the printer must be online with cloud printing enabled for that printer. The API routes the job; it does not create a network path to hardware.
  • API writes (creating jobs) need Pro ($24.90/month) or the 14-day trial. Free and Starter keys can read and use the read-only sandbox quota.
  • A 201 means the job was queued, not printed. Poll the job, or subscribe to webhooks, to learn the outcome.
  • Limits are counted in requests, not labels: see the table below before designing a loop that sends one label per call.

THE FIRST LABEL

Four calls from a key to a printed label

This is the order the API reference recommends. Every request body below was validated against the CreateJobRequest schema in openapi.yaml.

  1. Create a key in LabelInn under Settings, API Keys. sk_test_ keys run against a sandbox that never prints and has its own quota; sk_live_ keys send jobs to physical printers.
  2. GET /v1/fleet/printers: pick a printer with is_online: true and cloud_print_enabled: true. The second flag is switched on in the desktop app by the customer; the API cannot enable it. A job for an offline printer waits in the queue.
  3. GET /v1/designs/{designId}/variables: returns the exact field names and a ready-made example_payload. Keys you send that the design does not know are ignored silently, which looks identical to a binding bug.
  4. POST /v1/print/jobs with payload_type: "template", then GET /v1/print/jobs/{id} about every 2 seconds until the status is terminal.
EXAMPLESHELL
curl https://labelinn.com/v1/print/jobs \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: order-SO-10442-line-1:1" \
  -d '{
    "printer_id": "prt_abc123",
    "payload_type": "template",
    "design_id": "dsg_shipping",
    "data": { "order_id": "SO-10442", "customer": "Maya Brandt", "barcode": "TR123456789" },
    "copies": 2
  }'
EXAMPLEJSON
HTTP/1.1 201 Created
{
  "success": true,
  "data": {
    "id": "job_...",
    "status": "queued",
    "printer_id": "prt_abc123",
    "payload_type": "template",
    "copies": 2,
    "is_test_mode": false,
    "created_at": "2026-10-17T12:00:00Z"
  }
}

The response shape is the JobResponse / PrintJob schema of the OpenAPI file; the values above are placeholders, not output captured from the live service.

PHYSICAL AND ASYNCHRONOUS

What each job status means

StatusMeaningTerminal?
scheduledWaiting for its print_at time (at most 30 days ahead).no
queuedAccepted, not yet picked up by the printer's PC.no
claimedThe PC has taken the job.no
waitingForPrinterThe printer is switched off or unreachable. The job prints by itself when the printer is back, and ends cancelled after 24 hours if it never does. waiting_since is set.no (keep polling)
rendering, printingBeing rendered and sent.no
completedDelivered to the printer.yes
failedRender or hardware error, in error_message. Retrying needs a new idempotency key.yes
cancelledCancelled by you (POST /print/jobs/{id}/cancel, or DELETE) or after 24 hours waiting.yes

Render and hardware errors never appear in the create response, only in the job. A job you never poll is a job whose failure you will never see.

NO DOUBLE LABELS

Idempotency keys, and the retry trap

Send X-Idempotency-Key on every create. For 24 hours a repeated key returns the original job and prints nothing, which is what protects you from a double label after a network retry. A second request with the same key while the first is still running gets 409 IDEMPOTENCY_IN_PROGRESS with Retry-After; the same key with a different body gets 409 IDEMPOTENCY_KEY_REUSED.

The trap: after a job comes back failed, sending the same key again returns the old failed job instead of reprinting. Put an attempt counter in the key, for example order-SO-10442-line-1:<attempt>. A request refused with a 4xx releases its key, so a corrected request may reuse it.

LIMITS

Rate limits per plan

From entitlements.json and middleware.js. Daily counters reset at midnight UTC; test keys use a separate counter with at least 500 requests a day.

PlanRequests per dayRequests per minuteNotes
Free0 production (25 read-only sandbox)5Can authenticate and read; cannot create print jobs
Starter0 production (250 read-only sandbox)20Same: read-only evaluation
14-day Pro trial10010Includes writing, so you can build against the real endpoints
Pro ($24.90/month)2,00060The first plan with production print jobs
Enterprise (contact sales)50,000300Higher volume

Over a limit the API answers 429 with RATE_LIMIT_EXCEEDED (daily) or BURST_RATE_LIMIT (per minute) and a Retry-After header. The unit is a request, not a label. One POST /v1/print/batch carries up to 100 jobs, and one job whose data is an array carries up to 1000 rows (one label per row), so printing 500 labels is one request. A loop that posts one label per call tops out at 2,000 labels a day on Pro.

ERRORS

Errors you will meet

HTTPCodeWhat to do
400INVALID_REQUEST, BATCH_TOO_LARGEFix the body. A batch is 1 to 100 jobs.
401unauthorizedMissing or wrong key. Header is Authorization: Bearer sk_....
403PLAN_NO_APIThe plan has no API quota at all; upgrade or start the trial.
409IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_KEY_REUSED, AMBIGUOUS_WORKFLOWWait and retry with Retry-After; use a new key for a different body; name the workflow explicitly.
409cloud printing offThe company switched cloud printing off; jobs from the API are refused by design.
429RATE_LIMIT_EXCEEDED, BURST_RATE_LIMITBack off for Retry-After seconds.

The official SDKs raise a typed rate-limit error that carries the wait time; see the language pages for Python, Node.js, C# and Go.

WHICH PAGE FOR WHAT

This API next to the neighbouring pages

You want toGo to
See the call from your language with tested snippetsPython, Node.js, C#, Go
Keep layout out of code: design once, send only dataPrint labels from code
Start a no-code workflow from your system (webhook, polling)Print labels from any API or webhook and trigger a workflow from code
Talk to a Zebra only, with ZPLZebra printer API and send ZPL to a Zebra printer
Replace the API of a label tool you already useNiceLabel alternative: API, BarTender alternative: API, ZebraDesigner alternative: API

ANY PRINTER

Design it, bind your data, print on the printer you already own.

Zebra, TSC, Toshiba, Epson and more — over USB, network or Bluetooth, with no driver to install.

QUESTIONS / FAQ

Frequently asked questions

Can I print ZPL from a browser without building a print bridge?

That is the case this API exists for. Your web app calls LabelInn, and the LabelInn runtime next to the printer performs the actual output — you never ship printer-specific code.

Do I have to generate ZPL myself?

No. You send data and a design reference; LabelInn generates the command language the target printer actually speaks.

Is there an MCP server?

Yes. The same print, design and fleet operations are exposed over MCP so AI agents can call them directly.

How do I print labels via a RESTful API?

POST JSON to https://labelinn.com/v1/print/jobs with Authorization: Bearer sk_live_..., a printer_id, payload_type (template, zpl or image) and data for a template. Then GET /v1/print/jobs/{id} until status is completed. A sk_test_ key does the same against a sandbox that never prints.

Is there a label printer with an API?

Thermal printers take printer language (ZPL, TSPL, TPCL, ESC/Label) over USB or TCP port 9100; a REST API needs software in front of them. LabelInn is that layer: a runtime next to the printer connects out to the cloud, and your code calls one HTTPS API from anywhere.

Does the API return "printed" immediately?

No. 201 Created means queued. The job moves through claimed, rendering and printing to completed or failed, so poll the job or use webhooks.

What are the API rate limits?

Production keys: 100 requests a day on the trial, 2,000 on Pro and 50,000 on Enterprise, with 10, 60 and 300 requests per minute. Requests are counted, not labels, so batch calls and array data print many labels per request.

How do I avoid printing a label twice when I retry?

Send an X-Idempotency-Key. A repeated key returns the original job for 24 hours. After a failed job use a new key, for example with an attempt counter, or the retry returns the failed job again.

Is there a sandbox?

Yes. Keys starting sk_test_ never print, have their own counter and at least 500 requests a day.

NEXT STEP / LABELINN

Print your REST API data on the printer you already own

This feature runs on Pro — $24.90/mo, or $249/year (pay for 10 months, use 12). Signing up starts a 14-day Pro trial, so you can bind your own REST API data and print a real label before you pay anything. · 14-day Pro trial on signup · No credit card required · Windows, macOS, Android, Web

Start free →