HomeBlog › LabelInn REST API

LabelInn REST API — Build Print into Your ERP, WMS or Custom Tools (2026)

If your team builds software around printing — an ERP that fulfils orders, a WMS that drives a warehouse floor, an in-house dashboard your operators live in — you've probably hit one of two walls.

Wall one: every printer brand has its own SDK, its own driver assumptions, its own quirks. Building a fleet that's half Zebra, half TSC, plus a couple of Epson ColorWorks for color labels means three integrations and three on-call rotations. Wall two: the existing label "APIs" you've evaluated are basically file-upload endpoints. They print one PDF, return a job ID, and stop there. There's no fleet view, no template versioning, no event stream when a label fails halfway through a 1,000-label batch.

The LabelInn REST API is built for the second case. It's a single, versioned, OpenAPI-specced surface that handles printing, fleet management, design CRUD, batch operations, webhooks, audit trails, and quota — across every printer LabelInn supports. This guide walks through the surface, the auth model, idempotency, rate limits, and the integration patterns we see most often.

Base URL & Versioning

The API is hosted at:

https://api.labelinn.com/v1

The /v1 prefix is permanent. Breaking changes ship as /v2; /v1 is supported for at least 18 months after a successor's GA. Additive changes (new optional fields, new endpoints) land on /v1.

The full OpenAPI 3.0.3 spec is published — point your codegen tool at it and you have a typed client in any language in under a minute.

Authentication

LabelInn uses API keys with Bearer auth:

curl https://api.labelinn.com/v1/print/jobs \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json"

Generate keys in Settings → API Keys in your LabelInn dashboard. We recommend creating scoped keys per use case:

Test keys (sk_test_*) hit a sandbox that never touches a physical printer — perfect for CI. Live keys (sk_live_*) drive real hardware.

The Endpoints That Matter

POST /v1/print/jobs — Submit a Print Job

The workhorse. Three input modes: a saved design, raw ZPL, or a hosted image URL.

POST /v1/print/jobs
{
  "printer_id": "prn_warehouse_a_01",
  "design_id": "dsg_shipping_pro",
  "variables": {
    "order_id": "ORD-45123",
    "customer_name": "Jane Doe",
    "tracking_url": "https://track.example.com/45123"
  },
  "copies": 2
}

Response:

{
  "id": "job_01HVZK...",
  "status": "queued",
  "printer_id": "prn_warehouse_a_01",
  "queued_at": "2026-05-07T09:14:22.103Z"
}

Status transitions: queued → printing → completed (or failed). Use webhooks to be told; don't poll.

POST /v1/print/batch — Submit Up to 100 Jobs Atomically

For end-of-day order runs. The batch is accepted or rejected as a unit (any invalid job fails the batch with field-level errors), then each child job runs through the normal queue. You get an array of job IDs back.

GET /v1/print/jobs — List & Filter

Query params: status, printer_id, design_id, created_after, created_before, limit (max 100), cursor. Cursor pagination — never page-number — so the API stays correct under heavy churn.

POST /v1/print/jobs/:id/reprint and /retry

Reprint creates a new job with the same payload (your call — for re-shipping). Retry re-queues the original after a transient failure (driver, network, paper jam) and is idempotent within a 24h window. Use retry for ops automation; use reprint for human re-runs.

GET /v1/fleet/printers — Inventory and Status

Returns every printer your company owns, with model, firmware, supported media sizes, current status (online, offline, busy, error), queue depth, and last error. Use it to power a fleet dashboard or to pick a healthy target before submitting a job.

GET / POST / PUT /v1/designs — Template CRUD

Read your template library, create new designs from a JSON description, or update existing ones programmatically. Combined with POST /v1/designs/:id/publish you have full version control: every published snapshot is immutable and has a snapshot_id you can pin in your print calls.

POST /v1/render — Render Without Printing

Useful for previews, audits, or feeding a PDF into another system. Pass a design + variables, get back a PNG or PDF URL. Async by default — for AI agents and long-running renders, the response is a job ID you poll or webhook on.

POST / GET / DELETE /v1/webhooks — Event Subscriptions

Subscribe to events. The five most useful:

Events are signed (HMAC-SHA256 over the body, your endpoint secret as the key). Retry policy: 1s → 5s → 25s → 60s, up to 5 attempts. After 50 consecutive failures the subscription auto-disables and we email the owner.

Idempotency

Every POST accepts an Idempotency-Key header. We cache the response for 24 hours and return the same body on duplicates. This is the single biggest reliability lever your integration has — set it, and a network blip during a 1,000-job end-of-day batch can never produce 1,000 duplicate prints.

curl https://api.labelinn.com/v1/print/jobs \
  -H "Authorization: Bearer sk_live_..." \
  -H "Idempotency-Key: order-45123-shipping-v2" \
  -H "Content-Type: application/json" \
  -d '{...}'

Choose keys that include both the business ID and the job purpose — order-45123-shipping-v2 not just 45123 — so a customer-service reprint isn't deduped against the original.

Rate Limits

PlanDaily quotaBurst (per minute)Concurrent jobs
Pro2,000 requests6020
Business10,000 requests12060
Enterprise50,000 requests (negotiable)300500

Limits are returned on every response in X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. A 429 includes a Retry-After header in seconds — back off, don't hammer.

Need higher limits? Enterprise customers regularly run 100k+ jobs/day. Talk to us. Contact sales →

Error Model

Every error is a JSON body with a stable code, a human message, and a details object. The code is what you switch on:

{
  "error": {
    "code": "printer_offline",
    "message": "Printer prn_warehouse_a_01 is offline.",
    "details": {
      "printer_id": "prn_warehouse_a_01",
      "last_seen": "2026-05-07T08:42:11.000Z"
    }
  }
}

Common codes: invalid_argument, printer_offline, printer_busy, design_not_found, quota_exceeded, idempotency_key_conflict, media_mismatch (the design's media size doesn't fit the printer's loaded label).

Common Integration Patterns

Pattern 1: ERP Submits, App Prints

Your ERP holds orders. When a packer marks an order ready, the ERP fires POST /v1/print/jobs with the order's design and variables. The LabelInn cloud queues the job and pushes it to the right printer. Your ERP gets a job.completed webhook and updates the order status. End-to-end latency is typically 1.5–4 seconds depending on printer warm-up.

Pattern 2: Sidecar Service for Legacy Printer Code

You have a Windows service that's been printing labels via the Zebra ZPL SDK for years. Replacing it is risky. Instead, point it at the LabelInn API as a drop-in: keep your ZPL templates, send them via POST /v1/print/jobs with "raw_zpl": "...", and you immediately gain the fleet view, retry semantics, and audit trail without touching your business logic.

Pattern 3: Multi-Site Routing

Your company has three warehouses, each with their own printers. Tag your printers with site IDs in LabelInn, then submit jobs with "site_id": "warehouse_b" instead of a specific printer_id — LabelInn's edge router picks the healthiest printer at that site and falls over to the next-closest if the first is offline.

Pattern 4: Audit-Heavy Industries

Pharma, food traceability, regulated electronics. You need to prove which design version printed which serial number to which physical printer at what timestamp. LabelInn's design snapshot mechanism plus per-job audit log gives you that out of the box. Plug your serial number pool into the design as a variable, gate publication behind your QA workflow, and the API will refuse to print anything that drifts from an approved snapshot.

Webhooks: Don't Poll

Polling GET /v1/print/jobs/:id works, but it scales badly. Set up a webhook on job.completed and job.failed the same day you wire up your first POST /v1/print/jobs call. Sample receiver in Node:

app.post('/labelinn-webhook', (req, res) => {
  const sig = req.header('LabelInn-Signature');
  const computed = hmacSha256(req.rawBody, process.env.WEBHOOK_SECRET);
  if (!timingSafeEqual(sig, computed)) return res.sendStatus(401);

  const evt = JSON.parse(req.rawBody);
  if (evt.type === 'job.failed') {
    notifyOps(evt.data.job_id, evt.data.error);
  }
  res.sendStatus(200);
});

Always respond 200 within 10 seconds. Do the heavy work in a background queue — webhook timeouts trigger retries, which create duplicate processing.

What's Not in the API (Yet)

Get an API Key Today

API access ships on the Pro plan and above. The 14-day Pro trial includes API access — generate a test key, point your codegen at the OpenAPI spec, and you can be submitting your first job in well under an hour. If your scale lands you in Business or Enterprise territory, our team will help you with the integration directly.

Ship Print Into Your Stack

✓ OpenAPI 3.0 spec ✓ Webhooks, idempotency, audit log ✓ 50+ printer models, multi-site routing

Free 14-day Pro trial — no credit card. Generate test and live API keys from your dashboard the moment you sign up.

Start Pro Trial Free →