Skip to main content

LabelInn Python SDK

PyPI version License: MIT Python

Official Python SDK for the LabelInn Cloud Print API. Send labels to thermal printers (Zebra, TSC, Honeywell), manage your fleet, and build print automation workflows.

Installation

pip install labelinn

Quick Start

from labelinn import LabelInn

# Use a test key for development (no real prints)
client = LabelInn("sk_test_xxxxx")

# Print a ZPL label
job = client.print.create(
    printer_id="prt_abc123",
    payload_type="zpl",
    payload_data="^XA^FO50,50^ADN,36,20^FDHello World^FS^XZ",
)
print(f"Job {job['id']} → {job['status']}")

Authentication

Get your API key from LabelInn → Settings → API Keys.

Key prefix Mode Description
sk_test_xxx Sandbox No real prints, separate quota
sk_live_xxx Live Sends jobs to physical printers
# Test mode — safe for development
dev = LabelInn("sk_test_xxxxx")
print(dev.is_test_mode)  # True

# Live mode — real prints
prod = LabelInn("sk_live_xxxxx")

Print Jobs

Send a ZPL label

job = client.print.create(
    printer_id="prt_abc123",
    payload_type="zpl",
    payload_data="^XA^FO50,50^ADN,36,20^FDShipping Label^FS^XZ",
    copies=2,
    job_name="Order #1234",
)

Send an image label

job = client.print.create(
    printer_id="prt_abc123",
    payload_type="image",
    image_url="https://example.com/labels/shipping.png",
)

Print from a template

job = client.print.create(
    printer_id="prt_abc123",
    payload_type="template",
    design_id="dsg_shipping_v2",
    data={
        "order_id": "ORD-9876",
        "customer": "Ali Yilmaz",
        "barcode": "TR123456789",
    },
)

Idempotency (prevent duplicate prints)

job = client.print.create(
    printer_id="prt_abc123",
    payload_type="zpl",
    payload_data="^XA...^XZ",
    idempotency_key="order-9876-label",
)
# Calling again with the same key returns the original job

List & manage jobs

# List recent jobs
result = client.print.list(limit=10)

# Filter by status
result = client.print.list(status="failed")

# Get job details
job = client.print.get("job_abc123")

# Cancel a queued job
client.print.cancel("job_abc123")

# Reprint with different printer
client.print.reprint("job_abc123", printer_id="prt_backup")

Fleet Management

# List all printers
result = client.fleet.list()

# Filter by status
result = client.fleet.list(status="online")

# Get printer details
printer = client.fleet.get("prt_abc123")

# Quick status check
status = client.fleet.status("prt_abc123")

# Talk to the printer: send a command and get its answer back
answer = client.fleet.command("prt_abc123", "STATUS")

# Lock a printer (operators see the reason)
client.fleet.update("prt_abc123", is_locked=True, lock_reason="Head cleaning")

Designs (Templates)

# List designs
result = client.designs.list()

# Get design with elements
design = client.designs.get("dsg_abc123")

# Get template variables
variables = client.designs.list_variables("dsg_abc123")

# Clone a design
clone = client.designs.clone("dsg_abc123")

# Print directly
client.designs.print(
    "dsg_abc123",
    printer_id="prt_abc123",
    data={"order_id": "ORD-5555", "tracking_number": "TR999"},
    copies=1,
)

Workflows

Build, test and trigger visual label workflows from code.

# Dry-run with a sample record — nothing prints
result = client.workflows.test("wf_abc123", row={"sku": "A-1042", "qty": 2})
print(result["trace"])

# Mint a signed inbound trigger once and store the secret
trigger = client.workflows.create_trigger("wf_abc123", signed=True)

# Then, from your system, run the workflow with a record
client.workflows.fire(
    "wf_abc123",
    trigger["token"],
    {"order_id": "ORD-9876", "sku": "A-1042"},
    secret=trigger["secret"],
)

Print History

history = client.audit.print_history(printer_id="prt_abc123", status="completed", limit=50)
entry = client.audit.print_history_entry("job_abc123")
check = client.audit.verify_print("job_abc123", expect_copies=2)

Webhooks

# Subscribe to events
webhook = client.webhooks.create(
    url="https://yourapp.com/webhooks/labelinn",
    events=["print.job.completed", "print.job.failed", "printer.status.changed"],
    description="Production monitoring",
)

# Save the signing secret!
print("Secret:", webhook["signing_secret"])

# List subscriptions
result = client.webhooks.list()

# Send a test ping
client.webhooks.test(webhook["id"])

# Unsubscribe
client.webhooks.delete(webhook["id"])

Verifying webhook signatures

from labelinn.webhooks import verify_signature

# In your Flask handler:
@app.route("/webhooks/labelinn", methods=["POST"])
def handle_webhook():
    is_valid = verify_signature(
        payload=request.data.decode(),
        signature=request.headers["X-LabelInn-Signature"],
        secret=WEBHOOK_SECRET,
    )
    if not is_valid:
        return "Invalid signature", 401

    event = request.json
    print(f"Event: {event['event']}")
    return "ok", 200

Data Connect

Data Connect lets you ingest data from any enterprise system (SAP, Oracle, CSV exports, custom APIs) and print labels from it. Supports XML/IDoc, CSV/TSV, and JSON/NDJSON formats with auto-detection.

Ingest Data

# From a JSON payload
result = client.connect.ingest(
    source_id="src_abc123",
    payload='[{"sku": "A001", "name": "Widget"}, {"sku": "A002", "name": "Gadget"}]',
    format="json",
)
print(f"Ingested {result['records_count']} records")

# From XML/IDoc
result = client.connect.ingest(
    source_id="src_sap",
    payload=xml_string,
    format="xml",
)

Test Parse (Dry Run)

parsed = client.connect.test_parse(payload=csv_string, format="csv")
print(f"Detected {len(parsed['records'])} records")
for field in parsed["schema"]:
    print(f"  {field['path']} ({field['type']})")

Manage Sources

# Create a source
source = client.connect.create_source(name="SAP Orders", format="xml")

# List all sources
sources = client.connect.list_sources()

# Get source details
detail = client.connect.get_source("src_abc123")

# Update a source
client.connect.update_source("src_abc123", name="SAP Orders v2")

# Delete a source
client.connect.delete_source("src_abc123")

Schema & Records

# Get detected schema
schema = client.connect.get_schema("src_abc123")
for field in schema["fields"]:
    print(f"{field['path']} ({field['type']}): {field['sample']}")

# List ingested records
records = client.connect.list_records("src_abc123", limit=50)

Field Mappings

# Get current mappings
mappings = client.connect.get_mappings("src_abc123")

# Update mappings
client.connect.update_mappings("src_abc123", {"sku": "product_code", "name": "product_name"})

Print from Connector

result = client.connect.print(
    source_id="src_abc123",
    design_id="dsg_shipping",
    printer_id="prt_warehouse1",
    copies=1,
)
print(f"Created {result['count']} print jobs")

Product Passports, GHS and UFI

client.passport.update(gtin="09506000134352", serial="SN1",
                       fields=[{"key": "state_of_health", "value": 92}])
client.passport.set_page(gtin="09506000134352", brand={"name": "Acme", "accent": "#1f7a4d"})
passport = client.passport.resolve("01/09506000134352/21/SN1")   # public JSON

ghs = client.labels.preview(data={"h_codes": ["H225", "H319"], "languages": ["en"]})
ufi = client.ufi.generate(vat="DE123456789", formulation_number=4521, country_code="DE")

Also: client.connect.print_design(...) (print a design from its bound data source, with row_start / row_count), client.connect.custom (custom API connections), client.audit.compliance.sign(...), client.relay.status().

Local Edge API (LAN, pinned TLS)

Every PC running the LabelInn desktop app can serve a local API on port 6631. LabelInnEdge reads ~/.labelinn/edge.json (written by the app) for the address and token. When the PC serves HTTPS with its own self-signed certificate, the file carries tlsSha256 and the client pins it: right after the TLS handshake the certificate's SHA-256 is compared with the pin, before any byte of the request is sent, and a mismatch raises LabelInnEdgePinError. PCs without TLS (or older app versions) keep working over plain http. Standard library only.

from labelinn import LabelInnEdge

edge = LabelInnEdge.from_descriptor()                      # this PC
remote = LabelInnEdge("192.168.1.40", token="EDGE_TOKEN", tls_sha256="3f1c...e9")

accepted = edge.print({"printerId": "usb_zebra_01", "payloadType": "zpl",
                       "payloadData": "^XA^XZ"})
result = edge.get_job(accepted["jobId"])                   # 404 until processed
printers = edge.list_printers(include_peers=False)

Other methods: health(), list_peers(), start_discovery(), get_discovery(), list_designs(), get_design(), schedule_status(), schedule_run_now(), audit_recent().

MQTT note: the app's built-in broker only accepts labelinn/cmd/* commands from a client that logs in with the configured MQTT username and password (or from the same PC).

Rate Limits

Every response includes rate limit info:

result = client.print.list()
print(result["_rate_limit"])
# {"limit": 2000, "remaining": 1847, "reset": 3600}
Plan Daily Limit
Pro 2,000
Enterprise 50,000
Test keys 500 minimum

When rate-limited, the SDK raises RateLimitError:

from labelinn import RateLimitError

try:
    client.print.create(...)
except RateLimitError as e:
    print(f"Rate limited. Retry in {e.retry_after}s")

Error Handling

from labelinn import LabelInnError

try:
    client.print.create(...)
except LabelInnError as e:
    print(f"[{e.status}] {e.code}: {e.message}")
    # e.raw contains the full response body

CLI Tool

The SDK includes a command-line tool:

# Set your API key
export LABELINN_API_KEY=sk_test_xxxxx

# Verify connectivity
labelinn test

# List printers
labelinn printers

# Print a ZPL label
labelinn print prt_abc123 --zpl "^XA^FO50,50^ADN,36,20^FDHello^FS^XZ"

# Print from a template
labelinn print prt_abc123 --design dsg_shipping --data '{"name": "Ali"}'

# List jobs
labelinn jobs

# --- Data Connect ---
# List connected data sources
labelinn connect sources

# Ingest data from a file
labelinn connect ingest conn_abc123 --file data.csv

# Test-parse a local file
labelinn connect parse --file data.csv --format csv

# Get help
labelinn --help

Configuration

client = LabelInn(
    "sk_test_xxxxx",
    base_url="https://labelinn.com/v1",  # default
    timeout=30,                           # 30s default
)

Requirements

  • Python 3.8+
  • requests (only dependency)

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/my-feature)
  3. Install dev dependencies: pip install -e ".[dev]"
  4. Run tests: pytest
  5. Submit a Pull Request

License

MIT — see LICENSE for details.

Metadata

Release files for labelinn 3.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for labelinn 3.1.0
File Size Uploaded
labelinn-3.1.0.tar.gz 42.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for labelinn 3.1.0
File Interpreter ABI Platform
labelinn-3.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 74.8 kB

Release files / labelinn-3.1.0.tar.gz

Download URL labelinn-3.1.0.tar.gz
Size 42.6 kB
Tags Source
SHA-256 checksum
How to use checksums
66d29b127801c8fe23a7188f07be8f9c40e82a98bd31341577c1a4759dab9994
BLAKE2b-256 checksum
How to use checksums
fdaa80596f802b14dd6c3d04dfae0ed8cb38f70c26bbe8584e4563f8815cf127
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / labelinn-3.1.0-py3-none-any.whl

Download URL labelinn-3.1.0-py3-none-any.whl
Size 32.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c72ee3026fdf9c635f4fb34fb3de04fd6b5115796035ceb63c99d2d04778706c
BLAKE2b-256 checksum
How to use checksums
e068b45044d5f0c714b2e493cfe6556274de3478c2684c455c91b353ca0b99de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

3.1.0 This release

2 release files

3.0.0

2 release files

2.1.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page