Zippendo Python SDK
Official Python client for the Zippendo shipping & logistics API. Models are pydantic v2, so requests and responses are both type-hinted and validated at runtime. Requires Python 3.9+.
Book shipments and print labels with PostNord, GLS, DAO, Bring, DHL, DPD, UPS and more, track parcels, and manage orders, shipping rules and webhooks from your own code. New to the API? Start with the SDK guide or browse the API reference. To work from an AI assistant instead, connect the Zippendo MCP server.
Install
pip install zippendo
Authentication
Create an API token in your Zippendo dashboard (Settings → API tokens) — a Bearer token prefixed
with zipp_. Pass it as access_token:
import os
import zippendo
config = zippendo.Configuration(access_token=os.environ["ZIPPENDO_API_TOKEN"])
The base URL defaults to https://api.zippendo.com.
Resources & clients
The API is split into resource clients — ShipmentsApi, OrdersApi, CarriersApi, AddressesApi,
RulesApi, WebhooksApi, TokensApi, and more. Create an ApiClient from your config, then the
resource clients you need:
with zippendo.ApiClient(config) as client:
shipments = zippendo.ShipmentsApi(client)
orders = zippendo.OrdersApi(client)
The org_id parameter
Every call takes an org_id (your organization ID, found in the dashboard). It is explicit on each
call by design: one API token can be granted access to multiple organizations, and org_id selects
which one the request acts on.
Brands
A brand is a sub-account inside your organization — one company running several consumer-facing labels
(say Acme and Globex) out of one Zippendo org, with each brand's orders and shipments kept separate.
Scope a request to a single brand with the X-Zippendo-Brand header, which takes the brand's ID or slug.
The header applies uniformly to every operation, so it is not a method parameter — set it once on the
ApiClient and every call made through that client inherits it:
with zippendo.ApiClient(config) as client:
client.set_default_header("X-Zippendo-Brand", "acme") # brand ID or slug
shipments = zippendo.ShipmentsApi(client)
result = shipments.list_shipments("org_8f3kd92ld0", limit=50) # Acme's shipments only
Omit the header and you get the organization-wide view across every brand. To work with both views in
one program, build a second ApiClient from the same Configuration and leave its default header unset.
An API token can instead be bound to a brand at creation time (CreateApiTokenRequest(brand_id=...)).
Such a token is permanently confined to that brand, so the header is unnecessary — and sending
X-Zippendo-Brand naming a different brand is refused with BRAND_ACCESS_DENIED (403); the binding is
never widened. A header naming a brand that is not in the organization raises BRAND_NOT_FOUND (404).
List operations also take a brand_scope query parameter ("own" / "shared" / "both") to narrow
further within whichever brand context already applies: "own" returns only that brand's rows and
needs a brand context (otherwise 400); "shared" returns only the unassigned rows (equivalent to
brand_id="none"). Set X-Zippendo-Brand-Scope as a default header the same way to cover every call:
client.set_default_header("X-Zippendo-Brand-Scope", "own")
An explicit brand_scope argument passed to a call still wins over the header.
Managing brands
Brands are managed with BrandsApi. Use an organization-wide client for this — you are
administering brands, not acting inside one:
with zippendo.ApiClient(config) as client:
brands = zippendo.BrandsApi(client)
created = brands.create_org_brand(
"org_8f3kd92ld0",
zippendo.CreateOrgBrandRequest(name="Acme", company_name="Acme ApS"),
)
page = brands.list_org_brands("org_8f3kd92ld0")
brands.update_org_brand(
"org_8f3kd92ld0",
created.id,
zippendo.UpdateOrgBrandRequest(vat_number="DK12345678"),
)
brands.archive_org_brand("org_8f3kd92ld0", created.id)
Retire a brand with archive_org_brand — archived brands keep their slug and can be restored with
unarchive_org_brand. Permanent deletion is dashboard-only: it is refused while any order, shipment,
member or token still references the brand. Brands require a plan that includes them; creating one
past your plan's limit returns 403.
Listing & pagination
List endpoints accept page (1-based) and limit, and return a page with data plus total,
page, limit, and total_pages:
with zippendo.ApiClient(config) as client:
shipments = zippendo.ShipmentsApi(client)
result = shipments.list_shipments("org_8f3kd92ld0", page=1, limit=50)
print(result.data) # list[Shipment]
print(result.total, result.total_pages) # pagination metadata
Creating resources
with zippendo.ApiClient(config) as client:
orders = zippendo.OrdersApi(client)
order = orders.create_order(
"org_8f3kd92ld0",
zippendo.CreateOrderRequest(
order_number="1001",
order_channel_id="chan_7d2k1",
order_lines=[zippendo.CreateOrderRequestOrderLinesInner(name="T-shirt", quantity=2)],
),
)
print(order.id)
See ./docs for the full request/response shape of every operation.
Error handling
Non-2xx responses raise ApiException. The body is Zippendo's canonical { code, error, message } —
branch on the machine-readable code:
from zippendo.rest import ApiException
try:
shipments.get_shipment("org_8f3kd92ld0", "shp_missing")
except ApiException as e:
print(e.status, e.body) # e.body contains the JSON, e.g. {"code": "SHIPMENT_NOT_FOUND", ...}
Configuration
Point the client at a different environment by overriding host:
config = zippendo.Configuration(
access_token=os.environ["ZIPPENDO_API_TOKEN"],
host="https://staging.api.zippendo.com",
)
Reference
Full per-endpoint and per-model documentation is in ./docs. Hosted reference:
https://www.zippendo.com/docs/api-reference/overview.
License
Metadata
Release files for zippendo 1.3.14
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| zippendo-1.3.14.tar.gz | 238.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| zippendo-1.3.14-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 847.4 kB
Release files / zippendo-1.3.14.tar.gz
| Download URL | zippendo-1.3.14.tar.gz |
|---|---|
| Size | 238.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8bc6ca27010cadeef722a4a989529c2d8bb93d055e3e3e7c7306b2fbfabe665f
|
|
BLAKE2b-256 checksum How to use checksums |
e94d8b0a64cbd1b068ee8a7515589586aa810c9d457c4adb0a3937c21e84c476
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / zippendo-1.3.14-py3-none-any.whl
| Download URL | zippendo-1.3.14-py3-none-any.whl |
|---|---|
| Size | 609.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dcfbd2c6c5ea3eab64404c862bb7eb5816dfceea7c7e0ca32b030020d8108273
|
|
BLAKE2b-256 checksum How to use checksums |
3f8978139df87dac25abf1999950648d6a7e22025ae63839643a14cad107645b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for zippendo 1.3.14
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for zippendo-1.3.14.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.