Carrier for Craft CMS

Carrier for USPS

Carrier for USPS connects Craft Commerce to the United States Postal Service through the USPS APIs v3 at apis.usps.com, not the retired Web Tools XML. The add-on is free; it needs Carrier, which is the paid part and owns packing, checkout methods, label storage, bulk printing, the claim that stops a label being bought twice, the tracking schedule, the pickup-point picker and the log.

It ships from the United States and its territories (US, PR, VI, GU, AS, MP, FM, MH, PW), in pounds and inches.

Install

composer require justinholtweb/craft-carrier-usps
php craft plugin/install carrier-usps

Then Carrier → Connections → New connection and pick USPS. The add-on has no settings screen of its own; everything lives on the connection.

What it does

FeatureSupportedNotes
Live ratesYesShipping Options prices every class in one call, once per distinct package
LabelsYesOne call per package: USPS has no shipment grouping. See Partial failure
VoidYesCancelled at no charge, or a refund request when USPS has already processed the label
ReprintYesDomestic and international
ReturnsYesPay-on-use return labels, domestic only
TrackingYesUp to 35 numbers per request
Pickup pointsYes, search modePost Offices, looked up live, for the Hold for Pickup services
CollectionsYesFree carrier pickups, from US addresses
Close dayNo
Address validationYesUS addresses and territories
Cash on deliveryNo
InternationalYesOne package per shipment, with customs
AccessorialsYesSignature, adult signature
Heaviest parcel70 lb

Connecting

You need two things from USPS:

  1. An app on the USPS developer portal, which gives you a Consumer Key and Consumer Secret. Labels, international labels and carrier pickup are separate access requests on the portal; ask for each one you need.
  2. For labels, a USPS business account with a CRID, a MID and a funded EPS (or permit) account, from the Business Customer Gateway. Prices, tracking and address checks work without it.
FieldWhat to put there
EnvironmentProduction, or Sandbox / test. Sandbox uses USPS's Testing Environment for Mailers (TEM). TEM labels are watermarked and not billed.
Consumer Key / Consumer SecretFrom your app on the USPS developer portal.
CRIDCustomer Registration ID, from the Business Customer Gateway.
MIDThe Mailer ID used for labels.
Manifest MIDLeave blank to use the MID above.
Payment account typeEPS (Enterprise Payment System) or Permit.
Payment account numberThe EPS account number, or the permit number.
Permit ZIP CodeOnly for a permit account.
PricesCommercial, Retail, or Contract (Negotiated Service Agreement).
Where the carrier collects pickupsFront door, back door, side door, knock on door / ring bell, mail room, office, reception, porch, mailbox, or other (explain in the pickup's instructions).

Test connection reads which APIs your app has been granted, and says which are missing. When the payment account is filled in, it also proves it can pay for a label.

Two tokens, not one. The OAuth token opens every API. A second payment authorization token, minted from your CRID, MID and EPS account, is what pays for a label. Both last about eight hours and are cached. The payment token is cached per connection and per account, so changing the account never pays with the old one.

Services

CodeServiceNotes
USPS_GROUND_ADVANTAGEUSPS Ground Advantage
PRIORITY_MAILPriority Mail
PRIORITY_MAIL_EXPRESSPriority Mail Express
MEDIA_MAILMedia Mail
USPS_GROUND_ADVANTAGE_HFPUSPS Ground Advantage, Hold for PickupDelivered to a Post Office
PRIORITY_MAIL_HFPPriority Mail, Hold for PickupDelivered to a Post Office
PRIORITY_MAIL_EXPRESS_HFPPriority Mail Express, Hold for PickupDelivered to a Post Office
FIRST-CLASS_PACKAGE_INTERNATIONAL_SERVICEFirst-Class Package International ServiceInternational
PRIORITY_MAIL_INTERNATIONALPriority Mail InternationalInternational
PRIORITY_MAIL_EXPRESS_INTERNATIONALPriority Mail Express InternationalInternational

Prices are for your own box handed over at the counter. USPS also quotes flat-rate, cubic and destination-entry prices, which need USPS packaging or a trip to a USPS facility; those are left out. A domestic service sent to another country, or an international one sent at home, is refused with a message naming the service.

Label formats

FormatNotes
PDF, 4×6 in thermalUSPS has no sheet size; the 4×6 PDF is the paper option
ZPL (Zebra thermal)203 dpi
PNG image, 4×6 in

See labels for storage and bulk printing.

Hold for Pickup at a Post Office

Post Offices are searched live near the customer, so there is nothing to sync or import. See pickup points for the storefront picker.

Hold for Pickup is not a mail class of its own. It is Ground Advantage, Priority Mail or Priority Mail Express delivered to the Post Office the customer chose, priced as that class. That is why the _HFP services exist: put a checkout method that requires a pickup point on one of them.

Hold for Pickup makes more fields mandatory. USPS needs:

  • the customer's email address and a 10-digit phone number;
  • a first and last name, an email address and a phone number on your ship-from address.

Commerce addresses have no phone field, so map one in Carrier's settings. A label missing any of these is refused before anything is bought.

Partial failure

USPS buys labels one package at a time. If package 2 fails after package 1 was bought:

  • A refusal or throttle voids package 1 at once. Only when USPS confirms every void cost nothing is the shipment reported as refused, so it can be fixed and retried. The voided numbers are in the message.
  • Anything else, such as no answer for package 2, a refund dispute instead of a clean void, or a void that fails, marks the shipment uncertain, with every tracking number already bought in the message. Carrier never buys an uncertain shipment again on its own; it waits on Problems.

Things to know about USPS

  • The quota is small. USPS's default is 60 calls per hour per API. That is why rates come from one Shipping Options call per distinct package. Keep Carrier's rate cache on.
  • Dimensions are required, for prices and for labels. A parcel without length, width and height is refused here rather than by USPS. Weight is decimal pounds, at most 70 lb.
  • International labels are one package per shipment, because each carries its own customs form. Ship each package as its own shipment. An international label without customs lines is refused.
  • Returns are domestic only.
  • The mailing date must be today through seven days ahead (US Eastern); it is clamped to that window.
  • Pickups are free and run Monday to Saturday, from US addresses only. They default to tomorrow when no date is given.
  • A label that would print without postage. USPS's defaults hide the postage and the mail date on the label; the add-on turns both back on for outbound domestic labels.
  • TEM labels are watermarked and not billed.

Not yet verified

This add-on was written against the USPS v3 OpenAPI specifications and examples without a live USPS account. These points are marked UNVERIFIED in the code. Test them in TEM before you go live:

  • The machinable thresholds that send a parcel as NONSTANDARD (longest side over 22 in, second over 18 in, third over 15 in, or over 25 lb). They come from the DMM, not the API specification.
  • Hold for Pickup on Priority Mail and Priority Mail Express. USPS's example only shows Ground Advantage; the other two are offered because USPS's retail service has them. Also which street address the label should carry beside the Post Office id (the customer's is sent, as in USPS's example).
  • That the payment-authorization LABEL_OWNER role accepts the account fields.
  • USPS tracking event codes (Pub 199) and status categories. Unknown codes fall back to the event text.
  • The meaning of every DPVConfirmation letter beyond Y, D, S and N.
  • The 60-calls-per-hour default quota, which comes from USPS FAQ text rather than the specification.

See all carriers for the rest of the family.