shipzil

Providers

Supported operations, adapter behavior and verification status.

shipzil 0.1.0 contains four provider adapters.

Support matrix

AdapterRatingMulti-parcel pathPurchaseCancel/refundVerification retained in this repository
ShippoimplementedFANOUTimplementedrefund requestlive rating, test purchase and refund; captured responses
EasyshipimplementedFANOUTimplementedcancellationcaptured sandbox rating and label responses; payload tests
ShipStation v1implementedFANOUTimplemented; base64 labelvoidcaptured rating; one Stamps.com/USPS testLabel response
ShipStation v2implementednative packages[]implementedvoidlive rating; captured responses; purchase not run live

"Implemented" describes the adapter code. The final column states what has been run against a provider. It is not a guarantee that every carrier connected to an account supports the operation.

Shippo supports native multi-piece rating for some carrier and account combinations. The current adapter does not use that path; it rates parcels separately and returns FANOUT rates.

Configure adapters

The short form accepts credentials:

gateway = z.Gateway(
    shippo="shippo_test_...",
    easyship="sand_...",
    shipstation_v1=("key", "secret"),
    shipstation_v2="key",
)

Construct adapters directly for provider-specific options:

from shipzil.providers import EasyshipAdapter, ShipStationV1Adapter

gateway = z.Gateway({
    "easyship-sandbox": EasyshipAdapter(
        "sand_...",
        sandbox=True,
        default_category="fashion",
    ),
    "shipstation-legacy": ShipStationV1Adapter(
        key,
        secret,
        carriers=("stamps_com",),
        test_labels=True,
    ),
})

Provider notes

Shippo

  • Test tokens start with shippo_test_; live purchase tests reject other tokens.
  • The test environment is inconsistent about refunds. A label refunded immediately after purchase has returned HTTP 201 with status: "ERROR" and no reason, as well as an accepted refund. void() raises on a refusal rather than returning False, so an unexplained rejection is not mistaken for success.
  • A rate list shortened by a throttled carrier is reported as RATE_LIMITED alongside the rates that did return.
  • The adapter uses the shipment endpoint for rating and the transaction endpoint for purchase.
  • Provider messages are preserved in quote.messages and normalized to exclusions when no rates are returned.
  • Customs values are sent as line totals.
  • EEI/PFC data is currently transmitted only through this adapter.

Easyship

  • Sandbox keys use the sand_ prefix and the sandbox host.
  • Every parcel needs at least one Item.
  • Every item needs an explicit value and either category, hs_code or an adapter default_category.
  • Parcel dimensions may be supplied on the parcel or derived from item dimensions or stored SKU data.
  • Customs values are sent per unit.
  • Label purchase requires company on both addresses, although rating does not.
  • The rate response carries only meta and rates, with no per-courier failure field, so a shortened rate list cannot be explained. shipzil does not invent a reason for it.

ShipStation v1

  • Authentication needs a key and secret.
  • Rating requires one request per connected carrier because carrierCode is mandatory.
  • Rate responses do not include currency or delivery estimates.
  • Labels are returned as base64 in Label.label_data, not as a URL.
  • test_labels=True sends testLabel: true. The retained live evidence covers one Stamps.com/USPS test label; other carriers are not verified as no-charge.
  • The API has no duty-liability or EEI field in its international options model.
  • Customs values are USD line totals.

ShipStation v2

  • Rating accepts native packages[] and returns structured per-carrier errors.
  • Rating has been run live with production credentials; it is a read-only call.
  • Purchase and void are implemented but have not been run live in this repository.
  • Customs values are sent per unit.
  • ship_date is currently transmitted by this adapter only.

Adding an adapter

Adapter authors import the extension contract from shipzil.providers:

from shipzil.providers import Adapter, Capabilities, Quote

Implement rate_single() and buy(), assign a stable name, and populate Rate.provider plus Rate.service_key. Add rate_native_multi() and void() only when supported. See CONTRIBUTING.md for the test and evidence requirements.

On this page