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)
| File | Size | Uploaded | |
|---|---|---|---|
| printsocket-0.1.0.tar.gz | 15.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|