Skip to main content

printsocket

Python client for the PrintSocket cloud print API.

A lightweight agent runs on a machine, connects outbound to PrintSocket, and exposes that machine's printers (and scales) to a REST API. This library wraps API v1: devices, printers, scales, documents, print jobs, webhooks, and API keys, plus webhook signature verification for your receiver.

Zero dependencies; the standard library does all the work. Requires Python 3.10 or newer, and ships with inline type hints. Full API documentation lives at www.printsocket.com/docs.

Install

pip install printsocket

Quickstart

An sk_test_ key comes with a virtual device and printer that runs the full job lifecycle, so this works before any hardware is enrolled:

import os
import printsocket

ps = printsocket.PrintSocket(api_key=os.environ["PRINTSOCKET_API_KEY"])

printers = ps.printers.list({"state": "online"})

job = ps.jobs.create({
    "printer_id": printers["data"][0]["id"],
    "title": "Order #12345 label",
    "content": {"format": "pdf", "url": "https://example.com/label.pdf"},
    "metadata": {"order_id": "12345"},
})

print(job["id"], job["status"])  # job_...  queued

Responses are dicts with the exact snake_case fields the API reference documents, so the docs read straight across to the code.

Configuration

ps = printsocket.PrintSocket(
    api_key="sk_live_...",                        # required
    base_url="https://api.printsocket.com/v1",    # default
    timeout=30.0,                                 # seconds per attempt
    max_retries=2,                                # connection failures, 429s, and 5xx
)

Errors

Every API error raises a typed subclass of APIError carrying status, type, code, param, and request_id (quote the request id in support requests):

import printsocket

try:
    ps.jobs.cancel(job_id)
except printsocket.ConflictError as e:
    if e.code == "job_not_cancelable":
        ...  # already printing or finished
    else:
        raise

The classes are InvalidRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, RateLimitError, BillingError, and ServerError, one per error.type the API returns. Requests that never got a response raise APIConnectionError.

Retries and idempotency

Connection failures, 429s, and 5xx responses are retried automatically (max_retries, default 2), honoring Retry-After. Every POST carries an Idempotency-Key header, generated when you do not pass one, and the key is identical across the client's own retry attempts, so a retried create cannot produce a duplicate job. To extend the guarantee across your own retries, pass a key derived from your record:

ps.jobs.create(params, idempotency_key="order-12345-label")

Pagination

list() returns one page (data, has_more, next_cursor). Each list resource also has iterate(), which follows cursors for you:

for job in ps.jobs.iterate({"status": "failed", "limit": 100}):
    print(job["id"], (job.get("error") or {}).get("message"))

Documents

Upload once, print many times:

with open("packing-slip.pdf", "rb") as f:
    doc = ps.documents.upload(f.read(), "application/pdf", expire_after_seconds=3600)

ps.jobs.create({
    "printer_id": "prn_...",
    "content": {"format": "pdf", "document_id": doc["id"]},
})

ps.documents.create_from_url({"source_url": ...}) has the API fetch the file server-side instead.

Webhooks

Subscribe with the client, verify deliveries with printsocket.webhook. Verification needs the raw request body; a decoded and re-encoded body will not match the signature.

import printsocket
from printsocket import webhook

endpoint = ps.webhooks.create({
    "url": "https://example.com/printsocket/webhook",
    "events": ["job.*", "printer.state_changed"],
})
# endpoint["secret"] is shown only this once; store it.

# In your receiver (Flask shown; any framework works the same way):
@app.post("/printsocket/webhook")
def receive():
    try:
        event = webhook.construct_event(
            request.get_data(),
            request.headers.get("PrintSocket-Signature", ""),
            os.environ["PRINTSOCKET_WEBHOOK_SECRET"],
        )
    except printsocket.WebhookVerificationError:
        return "", 400
    # Delivery is at-least-once: dedupe on event["id"] before acting.
    return "", 200

Enrolling devices

Generate a short-lived, single-use token server-side and hand it to the agent installer, so your API keys never touch a customer machine:

token = ps.enrollment_tokens.create({"name": "Front desk PC"})
# token["token"] is the secret; it expires in about an hour.

Scales

scale = ps.scales.get("scl_...")
reading = scale.get("reading")
if reading and reading["stable"]:
    print(reading["weight_grams"], "g at", reading["captured_at"])

Development

PYTHONPATH=src python -m unittest discover -s tests

The test suite uses only the standard library on purpose; it runs anywhere Python does, with no install step.

License

MIT

Metadata

Release files for printsocket 0.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 printsocket 0.1.0
File Size Uploaded
printsocket-0.1.0.tar.gz 15.8 kB Details

Built distribution (wheel)

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

Total release size: 35.8 kB

Release files / printsocket-0.1.0.tar.gz

Download URL printsocket-0.1.0.tar.gz
Size 15.8 kB
Tags Source
SHA-256 checksum
How to use checksums
291712e8579ccec03f085763a1fb6394145b266c3a5d43b7aecf9619e8618587
BLAKE2b-256 checksum
How to use checksums
4dced04ea0eac30824ac7b0408de91b89503964e1c6efb19647a62aaa746eb11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / printsocket-0.1.0-py3-none-any.whl

Download URL printsocket-0.1.0-py3-none-any.whl
Size 20.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5219940f3e8c2269fbca93c8de5feff8552fc52a4c3dd51496067ac5f7c73483
BLAKE2b-256 checksum
How to use checksums
5810a300deb6493f96f341863a7705f0bad23d6a7fe6c4d5e53a3035aeb3e7db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

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