Zippendo Ruby SDK
Official Ruby client for the Zippendo shipping & logistics API. Requires Ruby 2.7+.
Install
gem install zippendo
Authentication
Create an API token in your Zippendo dashboard (Settings → API tokens) — a Bearer token prefixed
with zipp_. Configure it once:
require "zippendo"
Zippendo.configure do |config|
config.access_token = ENV["ZIPPENDO_API_TOKEN"]
end
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:
shipments = Zippendo::ShipmentsApi.new
orders = Zippendo::OrdersApi.new
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
(Pitaya, Kiwi) keeps each label's orders and shipments separate, with its own company name, address and
logo on the documents its shipments produce. Any call can be scoped to one brand by sending the
X-Zippendo-Brand header with the brand's ID or slug.
The header is not a method argument: it applies uniformly to every operation, so set it once as a default header on the client and every call inherits it.
Zippendo.configure do |config|
config.access_token = ENV["ZIPPENDO_API_TOKEN"]
end
Zippendo::ApiClient.default.default_headers["X-Zippendo-Brand"] = "pitaya" # brand ID or slug
shipments = Zippendo::ShipmentsApi.new
shipments.list_shipments("org_8f3kd92ld0", limit: 50) # Pitaya's shipments only
To address two brands from one process, give each its own ApiClient:
kiwi = Zippendo::ApiClient.new
kiwi.default_headers["X-Zippendo-Brand"] = "brnd_8f3kd92ld0"
Zippendo::OrdersApi.new(kiwi).list_orders("org_8f3kd92ld0")
Omit the header and the request covers the whole organization — the behaviour of every existing token.
A header naming a brand that does not exist in the organization is rejected with 404 BRAND_NOT_FOUND.
A token created with a brand_id (see CreateApiTokenRequest) is permanently confined to that brand and
needs no header. Sending X-Zippendo-Brand naming a different brand on such a token is refused with
403 BRAND_ACCESS_DENIED — the binding is never widened.
Creating, updating and deleting brands is done in the Zippendo dashboard; brand management is not part of this SDK.
Listing & pagination
List endpoints accept :page (1-based) and :limit, and return a page with data plus total,
page, limit, and total_pages:
result = shipments.list_shipments("org_8f3kd92ld0", page: 1, limit: 50)
puts result.data # Array<Shipment>
puts "#{result.total} / #{result.total_pages}"
Creating resources
order = orders.create_order("org_8f3kd92ld0", Zippendo::CreateOrderRequest.new(
order_number: "1001",
order_channel_id: "chan_7d2k1",
order_lines: [Zippendo::CreateOrderRequestOrderLinesInner.new(name: "T-shirt", quantity: 2)]
))
puts order.id
See ./docs for the full request/response shape of every operation.
Error handling
Non-2xx responses raise Zippendo::ApiError. The body is Zippendo's canonical
{ code, error, message } — branch on the machine-readable code:
begin
shipments.get_shipment("org_8f3kd92ld0", "shp_missing")
rescue Zippendo::ApiError => e
puts e.code # HTTP status
puts e.response_body # JSON, e.g. {"code":"SHIPMENT_NOT_FOUND", ...}
end
Configuration
Point the client at a different environment by overriding the host:
Zippendo.configure do |config|
config.access_token = ENV["ZIPPENDO_API_TOKEN"]
config.host = "staging.api.zippendo.com"
end
Reference
Full per-endpoint and per-model documentation is in ./docs. Hosted reference:
https://www.zippendo.com/docs/api-reference/overview.