Skip to main content

Shipments — Mailhub API Reference

Get shipping rate quotes for an order's shipment and purchase a label from a selected rate. Live carrier tracking is not part of the public API — a shipment's `status` field reflects this and stays `Unknown` after a label purchase.

Operations

POST /api/v1/shipments/{shipmentId}/labels

Buy label

Creates a shipping label for a shipment using a bearer token. The request body is unchanged and carries no idempotency token: repeated requests are recognized server-side from the shipment's durable purchase operation and its effective request. Returns 200 when the purchase has completed — a repeat of the same effective request replays the original result, including one started on the standard surface — 202 when the purchase is still running when the wait window ends, and 409 when a different purchase is already in progress or a label already exists for the shipment. After a 202 the client observes completion through GET v1/orders/{id}; there is no operation-status endpoint to poll. Label files may still be generated asynchronously: when label assets are still processing, postageLabel.labelProcessingStatus will be 'processing' and label URLs may be null or empty. **Label URLs are temporary.** Every URL in postageLabel — the flat labelUrl/labelPdfUrl/labelZpl*Url fields and postageLabel.labelAssets[].url alike — is a pre-signed storage link that downloads the file directly, with no API token. Each one expires (24 hours by default) and cannot be revoked before it does, so treat it as a credential: do not store it, log it, or share it. Once a link has expired, call GET v1/orders/{id} to obtain fresh ones; there is no refresh call, and re-purchasing is never required. The proxy download endpoint remains available and is unchanged.

Authentication: JWTBearerAuth, Bearer http, JWT

Parameters

NameInTypeRequiredDescription
shipmentIdpathstringrequired

Example: b91a2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d

X-SubAccount-Idheaderstring (uuid)optionalOptional. Evaluates the purchase against the sub-account's carrier availability, which can narrow the carriers available to those enabled for that sub-account. Does not change the label's charged price, and does not restrict which shipments/rates can be used to purchase a label — that is enforced by account ownership alone.

Example: 3a7d9e21-6b48-4c15-9f2e-7d0c5b83a614

Request body (required)

application/json — BuyLabelRequest

{
  "rate": {
    "id": "c4a1b2d3-4e5f-6a7b-8c9d-0e1f2a3b4c5d"
  }
}

Responses

StatusDescriptionBody
200Label created successfully

application/json — BuyLabelResponseEnvelope

202Label purchase accepted and still in progress

application/json — BuyLabelAcceptedEnvelope

400Invalid request

application/json — ErrorEnvelope

401Not authenticated

application/json — ErrorEnvelope

403Authenticated, but not with an Open API integration token. Sent without a body.No response body.
404The rate, its shipment, or the order behind it does not exist for your account

application/json — ErrorEnvelope

409A label purchase is already in progress, or a label already exists for this shipment

application/json — ErrorEnvelope

415The request was sent with a `Content-Type` other than `application/json`. Answered by middleware ahead of authentication, so it is reachable on every write operation.

application/json — ErrorEnvelope

422The shipment cannot become a label for a reason the caller can correct. Either the carrier rejected it — address, phone, customs, parcel or a stale rate — or it was refused before the carrier was called: `Order.NotReadyForPurchase` (a sender or recipient field is missing or invalid, most often a phone number), `Order.ClosedAtSource` (the connected store already shipped or cancelled the order), `Order.CustomsRequired` (the destination is outside the US and no customs declaration is available yet), `Order.NotLoaded` or `Order.MetadataUnreadable` (the order behind the shipment could not be read). The pre-carrier reasons apply to orders imported from a connected store; an order created purely through this API carries no completeness metadata and is not held to them.

application/json — ErrorEnvelope

500Internal server error

application/json — ErrorEnvelope

503The carrier is temporarily unavailable. Nothing to correct; retry later

application/json — ErrorEnvelope

POST /api/v1/shipments/{shipmentId}/rates

Get shipment rates

Gets shipping rate quotes from all available carriers for a shipment using a bearer token.

Authentication: JWTBearerAuth, Bearer http, JWT

Parameters

NameInTypeRequiredDescription
shipmentIdpathstringrequired

Example: b91a2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d

X-SubAccount-Idheaderstring (uuid)optionalOptional. Evaluates the request against the sub-account's carrier availability, which can narrow the carriers returned to those enabled for that sub-account. Does not change rate pricing, and does not restrict which shipments can be rated — that is enforced by account ownership alone.

Example: 3a7d9e21-6b48-4c15-9f2e-7d0c5b83a614

Responses

StatusDescriptionBody
200Rates retrieved successfully

application/json — GetRatesResponseEnvelope

400Invalid request

application/json — ErrorEnvelope

401Not authenticated

application/json — ErrorEnvelope

403Authenticated, but not with an Open API integration token. Sent without a body.No response body.
404Shipment not found

application/json — ErrorEnvelope

409The sub-account given in `X-SubAccount-Id` is not active.

application/json — ErrorEnvelope

415The request was sent with a `Content-Type` other than `application/json`. Answered by middleware ahead of authentication, so it is reachable on every write operation.

application/json — ErrorEnvelope

422The shipment exists but is missing the address or parcel information rating needs

application/json — ErrorEnvelope

500The request could not be completed because of an unexpected server-side failure.

application/json — ErrorEnvelope

503The carrier is temporarily unavailable. Nothing to correct; retry later

application/json — ErrorEnvelope

Schemas

The public schemas the operations above reference. Each is listed once; a type name in the tables above links to its fields here.

ApiError

One thing that went wrong.

FieldTypeRequiredDescription
codestringrequiredMachine-readable error identifier, dotted and stable — for example Order.NotFound. Branch on this rather than on message.
messagestringrequiredReadable explanation of the failure. Wording may change; do not parse it.
metaDataobject nullableoptionalExtra detail about this particular failure. Its shape depends on code.

BuyLabelAccepted

The 202 Accepted body for a label purchase that was still running when the wait window closed. The label is still being bought; poll the order to see it appear.

FieldTypeRequiredDescription
correlationIdstring nullablerequiredCorrelation identifier for the purchase, filled in once it has been dispatched for processing. Diagnostic only, like operationId.
operationIdstringrequiredIdentifier of the in-flight purchase. Diagnostic only: it is never sent back, and there is no public operation-status endpoint to poll it against.
rateIdstringrequiredIdentifier of the rate being bought.
shipmentIdstringrequiredIdentifier of the shipment the label is being bought for.
statusstringrequiredWhere the purchase had got to when the wait window closed. One of Claimed (accepted by Mailhub, not yet sent to the carrier), Processing (sent and running), or OutcomeUnknown (the carrier may have created a label; the purchase is retained and resolved later, never automatically retried). A completed purchase answers 200 and a confirmed failure answers an error, so neither appears here.

Allowed values: Claimed, Processing, OutcomeUnknown

BuyLabelAcceptedEnvelope

The envelope every JSON operation answers with: a success flag and either a result or errors.

FieldTypeRequiredDescription
dataBuyLabelAccepted nullablerequiredThe operation's result. Absent when the call failed.
errorsApiError[] nullablerequiredWhat went wrong. Absent when the call succeeded.
successbooleanrequiredWhether the operation succeeded. When false, read errors.

BuyLabelRequest

Names the rate to buy a label for.

FieldTypeRequiredDescription
rateRateReferencerequired

BuyLabelResponse

A purchased shipping label and the shipment it belongs to: the addresses it prints, the package it covers, the rate that was charged and the label files to download.

FieldTypeRequiredDescription
createdAtstringrequiredUTC instant the label was created, as yyyy-MM-ddTHH:mm:ssZ.
customsInfoCustomsInfo nullablerequiredCustoms declaration for an international shipment. This operation does not populate it today.
fromAddressLabelAddressrequired
idstringrequiredIdentifier of the shipment the label was bought for.
isReturnbooleanrequiredWhether the shipment is a return back to the sender.
objectstringrequiredType discriminator; always Shipment.
orderIdstring nullablerequiredIdentifier of the order the shipment belongs to, when it belongs to one.
parcelLabelParcelrequired
postageLabelPostageLabelrequired
returnAddressLabelAddress nullablerequiredAddress returns are sent to, when one differs from the sender's address.
selectedRateSelectedRaterequired
statusstringrequiredShipment status as the enum member name. Values are Unknown, PreTransit, InTransit, OutForDelivery, Delivered, AvailableForPickup, ReturnToSender, Failure, Cancelled and Error. Carrier tracking is not yet wired in, so in practice this reads Unknown — it is not a label-generation status. For that, read postageLabel.labelProcessingStatus.

Allowed values: Unknown, PreTransit, InTransit, OutForDelivery, Delivered, AvailableForPickup, ReturnToSender, Failure, Cancelled, Error

toAddressLabelAddressrequired
trackingCodestringrequiredCarrier tracking number printed on the label.
updatedAtstringrequiredUTC instant the label was last modified, as yyyy-MM-ddTHH:mm:ssZ.
uspsZoneinteger (int32) nullablerequiredUSPS delivery zone between origin and destination, when USPS reported one.

Format: int32

BuyLabelResponseEnvelope

The envelope every JSON operation answers with: a success flag and either a result or errors.

FieldTypeRequiredDescription
dataBuyLabelResponse nullablerequiredThe operation's result. Absent when the call failed.
errorsApiError[] nullablerequiredWhat went wrong. Absent when the call succeeded.
successbooleanrequiredWhether the operation succeeded. When false, read errors.

CarrierRateResult

The outcome of asking one carrier for rates. Present for every carrier that was asked, so a carrier that returned nothing can be told apart from a carrier that was never contacted.

FieldTypeRequiredDescription
carrierstringrequiredThe carrier that was asked for rates.
errorCodestring nullablerequiredMachine-readable reason the carrier returned no rates.
errorMessagestring nullablerequiredReadable explanation of why the carrier returned no rates.
successbooleanrequiredWhether that carrier returned rates.

CustomsInfo

Customs declaration accompanying an international shipment.

FieldTypeRequiredDescription
contentsExplanationstringrequiredFree-text description of the contents, required by some carriers for certain content types.
contentsTypestringrequiredWhat the parcel contains, in the carrier's vocabulary — merchandise, a gift, documents and so on.
createdAtstringrequiredUTC instant the declaration was created, as yyyy-MM-ddTHH:mm:ssZ.
customsCertifybooleanrequiredWhether the signer certified the declaration as accurate.
customsItemsCustomsItem[]requiredThe individual line items being declared.
customsSignerstringrequiredName of the person certifying the declaration.
declarationstring nullablerequiredAdditional declaration text the carrier requires.
eelPfcstringrequiredUS Electronic Export Information exemption or Proof of Filing Citation carried on the declaration.
idstringrequiredIdentifier of the customs declaration.
nonDeliveryOptionstringrequiredWhat the carrier should do if the parcel cannot be delivered — return it or abandon it.
objectstringrequiredType discriminator; always CustomsInfo.
restrictionCommentsstring nullablerequiredFree-text detail about the restriction named in restrictionType.
restrictionTypestringrequiredAny export or import restriction that applies to the contents.
updatedAtstringrequiredUTC instant the declaration was last modified, as yyyy-MM-ddTHH:mm:ssZ.

CustomsItem

One declared line on a customs declaration.

FieldTypeRequiredDescription
codestringrequiredYour own product or SKU code for the item.
createdAtstringrequiredUTC instant the line item was created, as yyyy-MM-ddTHH:mm:ssZ.
currencystring nullablerequiredCurrency of value, as an ISO 4217 three-letter code. The set of codes accepted here is not constrained by this contract.
descriptionstringrequiredWhat the item is, in plain words, for the customs authority.
eccnstring nullablerequiredExport Control Classification Number, when the item is export-controlled.
hsTariffNumberstringrequiredHarmonized System tariff code classifying the item.
idstringrequiredIdentifier of the declared line item.
manufacturerstring nullablerequiredWho made the item.
objectstringrequiredType discriminator; always CustomsItem.
originCountrystringrequiredCountry the item was made in, as a two-letter ISO 3166-1 alpha-2 code.
quantityinteger (int32)requiredHow many of this item are in the parcel.

Format: int32

updatedAtstringrequiredUTC instant the line item was last modified, as yyyy-MM-ddTHH:mm:ssZ.
valuestringrequiredDeclared value of the line, in currency.
weightnumber (decimal)requiredWeight of the line in pounds.

Format: decimal

ErrorEnvelope

The envelope every JSON operation answers with: a success flag and either a result or errors.

FieldTypeRequiredDescription
dataobject nullablerequiredThe operation's result. Absent when the call failed.
errorsApiError[]requiredWhat went wrong. Absent when the call succeeded.
successbooleanrequiredWhether the operation succeeded. When false, read errors.

GetRatesResponse

The shipping options available for a shipment, and how each carrier answered.

FieldTypeRequiredDescription
carrierCountinteger (int32)requiredNumber of carriers that returned at least one rate.

Format: int32

carrierResponsesCarrierRateResult[]requiredOne entry per carrier that was asked, including the ones that returned nothing, so a carrier that declined can be told apart from a carrier that was never contacted.
ratesRateQuote[]requiredEvery rate available for the shipment, across all carriers that answered. Buy one by sending its id to the label operation.
totalCountinteger (int32)requiredNumber of entries in rates.

Format: int32

GetRatesResponseEnvelope

The envelope every JSON operation answers with: a success flag and either a result or errors.

FieldTypeRequiredDescription
dataGetRatesResponse nullablerequiredThe operation's result. Absent when the call failed.
errorsApiError[] nullablerequiredWhat went wrong. Absent when the call succeeded.
successbooleanrequiredWhether the operation succeeded. When false, read errors.

LabelAddress

A postal address as Mailhub stored it.

FieldTypeRequiredDescription
carrierFacilitystring nullablerequiredCarrier facility this address refers to, when one was supplied.
citystringrequiredCity or locality.
companystring nullablerequiredCompany name at the address.
countrystringrequiredTwo-letter ISO 3166-1 alpha-2 country code, for example US.
createdAtstringrequiredUTC instant the address record was created, as yyyy-MM-ddTHH:mm:ssZ.
emailstringrequiredContact email address.
federalTaxIdstring nullablerequiredFederal tax identifier recorded for customs paperwork.
idstringrequiredIdentifier of the stored address record.
namestringrequiredContact name at the address.
objectstringrequiredType discriminator; always Address.
phonestringrequiredContact phone number.
residentialboolean nullablerequiredWhether the address is residential.
statestringrequiredState, province or region. For US addresses, the two-letter state code.
stateTaxIdstring nullablerequiredState tax identifier recorded for customs paperwork.
street1stringrequiredFirst street line — house or building number and street.
street2stringrequiredSecond street line: apartment, suite, unit or floor.
updatedAtstringrequiredUTC instant the address record was last modified, as yyyy-MM-ddTHH:mm:ssZ.
zipstringrequiredPostal or ZIP code.

LabelAsset

One rendering of the label, in a single file format.

FieldTypeRequiredDescription
formatstringrequiredThe label file format this entry describes: PDF, ZPL203DPI, ZPL300DPI or ZPL600DPI.

Allowed values: PDF, ZPL300DPI, ZPL203DPI, ZPL600DPI

statusstringrequiredcompleted when the file exists and url is filled in, processing while it is still being rendered. Every listed format is eventually produced, so processing means "come back", not "unavailable".

Allowed values: completed, processing

urlstring nullablerequiredTime-limited link that downloads the file directly, without an API token. It expires; buy-time links can be replaced by requesting the order again.

LabelParcel

The physical package the label covers.

FieldTypeRequiredDescription
createdAtstringrequiredUTC instant the parcel record was created, as yyyy-MM-ddTHH:mm:ssZ.
heightnumber (decimal)requiredShortest side of the package, in inches. Reads 0 when the order named a predefined package.

Format: decimal

idstringrequiredIdentifier of the stored parcel record.
lengthnumber (decimal)requiredLongest side of the package, in inches. Reads 0 when the order named a predefined package instead.

Format: decimal

objectstringrequiredType discriminator; always Parcel.
predefinedPackagestring nullablerequiredCarrier-defined packaging named on the order, when dimensions were not given.
updatedAtstringrequiredUTC instant the parcel record was last modified, as yyyy-MM-ddTHH:mm:ssZ.
weightnumber (decimal)requiredPackage weight in pounds.

Format: decimal

widthnumber (decimal)requiredSecond-longest side of the package, in inches. Reads 0 when the order named a predefined package.

Format: decimal

PostageLabel

The label itself and the files it can be downloaded as.

FieldTypeRequiredDescription
createdAtstringrequiredUTC instant the label was created, as yyyy-MM-ddTHH:mm:ssZ.
dateAdvanceinteger (int32)requiredNot populated by Mailhub; always 0.

Format: int32

idstringrequiredIdentifier of the label. Use it on the label download and cancel operations.
integratedFormstringrequiredNot populated by Mailhub; always empty.
labelAssetsLabelAsset[]requiredOne entry per printable format, each with its own status and link. The flat label*Url fields above carry the same links.
labelDatestringrequiredDate the label is mailed on, as yyyy-MM-ddTHH:mm:ssZ, falling back to the label's creation instant when the carrier supplied no mailing date.
labelFilestring nullablerequiredNot populated by Mailhub. Label files are served through the time-limited links above.
labelFileTypestringrequiredFile type of labelUrl; always PDF.
labelPdfUrlstring nullablerequiredTime-limited link to the PDF rendering.
labelProcessingStatusstringrequiredcompleted once every listed format has been rendered, processing while any is still being produced. This is the field to poll on after buying a label — not the shipment's status.

Allowed values: completed, processing

labelResolutioninteger (int32)requiredNot populated by Mailhub; always 0. Resolution is carried by the per-format asset entries.

Format: int32

labelSizestringrequiredNot populated by Mailhub; always empty.
labelTypestringrequiredNot populated by Mailhub; always empty.
labelUrlstringrequiredTime-limited link to the PDF rendering — the general-purpose "the label file" link. Same value as labelPdfUrl. Links expire; request the order again for fresh ones.
labelZpl203Urlstring nullablerequiredTime-limited link to the 203 dpi ZPL rendering.
labelZpl300Urlstring nullablerequiredTime-limited link to the 300 dpi ZPL rendering.
labelZpl600Urlstring nullablerequiredTime-limited link to the 600 dpi ZPL rendering.
objectstringrequiredType discriminator; always PostageLabel.
updatedAtstringrequiredUTC instant the label was last modified, as yyyy-MM-ddTHH:mm:ssZ.

RateQuote

One priced shipping option for a package: which carrier and service, what it costs and how fast it is expected to be. Returned by the rate and combined create-and-rate operations.

FieldTypeRequiredDescription
billingTypestring nullablerequiredHow the carrier bills this rate, in the carrier's own vocabulary.
carrierstringrequiredThe carrier offering the rate, for example USPS or UPS.
carrierCodestring nullablerequiredThe carrier's own account or brand code, when the carrier supplies one.
currencystringrequiredCurrency of rate, as an ISO 4217 three-letter code. The set of codes a carrier may return is not constrained by this contract.
deliveryDateGuaranteedbooleanrequiredWhether the carrier guarantees the delivery date rather than estimating it.
deliveryDaysinteger (int32)requiredCarrier-supplied transit estimate, in days. This is not a commitment: every carrier integration fills deliveryDays and estDeliveryDays from one quantity, so the two always carry the same number on a given rate. 0 means the carrier supplied no transit time for this rate, not same-day delivery. The day basis is the carrier's own — UPS reports business days in transit, USPS a span derived from its quoted delivery window — so do not compare the number across carriers. Read deliveryDateGuaranteed for whether anything is guaranteed.

Format: int32

destinationEntryFacilityTypestring nullablerequiredUSPS destination entry facility the price assumes, when the carrier is USPS.
estDeliveryDaysinteger (int32)requiredCarrier-supplied transit estimate, in days. Currently always equal to deliveryDays: both are filled from the same carrier quantity on every integration, and neither is a separate estimated-versus-committed figure. 0 means the carrier supplied no transit time.

Format: int32

estimatedDeliveryDatestring (date-time) nullablerequiredDate the carrier expects to deliver on. null when the carrier supplied no date, which is the common case for carriers that report transit days instead. The label-purchase response republishes this same value under the name selectedRate.deliveryDate.

Format: date-time

idstring (guid) nullablerequiredIdentifier of this rate. Send it as rate.id to the label operation to buy this exact option; a rate cannot be reconstructed from its other fields.

Format: guid

listCurrencystring nullablerequiredCurrency of listRate, as an ISO 4217 three-letter code.
listRatenumber (decimal) nullablerequiredThe carrier's published list price for the same service, when the carrier publishes one. Like retailRate, a comparison figure rather than the charged amount.

Format: decimal

mailClassstring nullablerequiredUSPS mail class for the rate, when the carrier is USPS.
processingCategorystring nullablerequiredUSPS processing category for the package, when the carrier is USPS.
ratenumber (decimal)requiredThe amount your account is charged if this rate is bought.

Format: decimal

rateIndicatorstring nullablerequiredUSPS rate indicator describing how the price was derived, when the carrier is USPS.
retailCurrencystring nullablerequiredCurrency of retailRate, as an ISO 4217 three-letter code.
retailRatenumber (decimal) nullablerequiredThe carrier's over-the-counter retail price for the same service, when the carrier publishes one. It is a comparison figure, not what you are charged.

Format: decimal

serviceCodestringrequiredThe carrier's own code for the service, for example GroundAdvantage. This is the machine value; serviceName is the readable one.
serviceNamestringrequiredReadable name of the service, for example USPS Ground Advantage. Suitable for display; match on serviceCode rather than on this.
skustring nullablerequiredThe carrier's own product code for this rate, when it supplies one.
zonestring nullablerequiredCarrier delivery zone between origin and destination, when the carrier reports one.

RateReference

A reference to a previously quoted rate.

FieldTypeRequiredDescription
idstringrequiredThe id of the rate to buy, taken from a rate returned by the rate or combined create-and-rate operation.

SelectedRate

The rate that was bought, and what it cost.

FieldTypeRequiredDescription
billingTypestringrequiredHow the carrier bills this rate, in the carrier's own vocabulary.
carrierstringrequiredThe carrier the label was bought from.
createdAtstringrequiredUTC instant the rate was quoted, as yyyy-MM-ddTHH:mm:ssZ.
currencystringrequiredCurrency of rate, as an ISO 4217 three-letter code. The set of codes a carrier may return is not constrained by this contract.
deliveryDatestring nullablerequiredDate the carrier expects to deliver on, as yyyy-MM-ddTHH:mm:ssZ. This is the same value the rate operation publishes as estimatedDeliveryDate, renamed on this response only. null when the carrier supplied no date, which is the common case for carriers that report transit days instead.
deliveryDateGuaranteedbooleanrequiredWhether the carrier guarantees the delivery date rather than estimating it.
deliveryDaysinteger (int32)requiredCarrier-supplied transit estimate, in days, carried over from the rate that was bought. Not a commitment, and always equal to estDeliveryDays: both are filled from one carrier quantity. Reads 0 when the carrier supplied no transit time. The day basis is the carrier's own, so do not compare the number across carriers.

Format: int32

estDeliveryDaysinteger (int32)requiredCarrier-supplied transit estimate, in days. Currently always equal to deliveryDays: both are filled from the same carrier quantity. Reads 0 when the carrier supplied none.

Format: int32

idstringrequiredIdentifier of the rate that was bought.
listCurrencystringrequiredCurrency of listRate. Falls back to currency when the carrier published no list price.
listRatenumber (decimal)requiredThe carrier's published list price for the same service. When the carrier published none, this repeats the charged rate, on the same terms as retailRate.

Format: decimal

objectstringrequiredType discriminator; always Rate.
ratenumber (decimal)requiredThe amount charged to your account for this label, in currency.

Format: decimal

retailCurrencystringrequiredCurrency of retailRate. Falls back to currency when the carrier published no retail price.
retailRatenumber (decimal)requiredThe carrier's over-the-counter retail price for the same service. When the carrier published no retail price, this repeats the charged rate rather than being omitted — so an equal value does not by itself mean the carrier quoted the same figure.

Format: decimal

servicestringrequiredThe carrier's own service code for the bought rate, for example GroundAdvantage. This is the same value the rate operation publishes as serviceCode; no readable service name is returned here.
shipmentIdstringrequiredIdentifier of the shipment this rate was quoted for.
updatedAtstringrequiredUTC instant the rate was last modified, as yyyy-MM-ddTHH:mm:ssZ.