Carrier label billing: charge-on-creation vs charge-on-scan
Audience: whoever (human or agent) next has to reason about why a label
billed, whether pay-on-scan is available, or who to contact to change it.
Evidence quality: carrier-published documentation and vendor help-centre
articles, gathered 2026-07-30, plus one closed UPS billing case of our own.
Everything is sourced. Claims we have not verified against our own accounts
are marked UNVERIFIED — check the portal or ask the rep before acting.
Related: doc/tasks/202607301800_ERRORED_LABEL_ORPHAN_BILLING.md
(the ST726098 orphan, still open), AppSignal #3573.
What each carrier calls this
There is no industry-standard term. Every carrier has its own, and using the
wrong one on a call is how these conversations stall.
| Carrier | Their term for charge-on-scan | Their term for charge-on-creation |
|---|---|---|
| UPS | "pay on use" / "pay on scan" — but do not trust this for our account, see UPS bills unused labels | billed at label creation; the nominal remedy is Void Shipment, which failed for us — the working remedy is a billing dispute |
| FedEx | "pay on use"; FedEx bills on the first carrier scan | n/a for returns — pay-on-use is the default |
| USPS | "Scan-Based Payment" (SBP) — legacy, migrated into the "USPS Returns" platform. Via our reseller (Stamps.com/Endicia) the term is "Pay-On-Use Returns" | "postage at print" — the default for Stamps.com/Endicia-generated labels |
| Canada Post | "event-based billing" — billed on physical scan in their network, effective 2025-07-02 for commercial accounts | the pre-2025-07-02 model; required label-cancellation requests |
| Purolator | "Outbound Return Service" (return label bundled with an outbound shipment) and "Returns Management Service" (standalone). Both bill only once the shipment is scanned | n/a for those two services |
| Canpar | "Return Tag Service" / "Return Tags"; reconciliation runs off a monthly report of barcodes with pickup and delivery scans | UNVERIFIED — Canpar does not publish its billing trigger |
Every row is sourced under Sources.
ShipEngine's vocabulary, which is what our code actually sends
ShipEngine normalises all of the above into one charge_event field on label
creation (Return Labels):
on_creation— "Charge for the label at the time of label creation. This is
the default behavior for USPS (Stamps.com) and ShipStation Carriers."on_carrier_acceptance— "Charge for the label when it is scanned by the
carrier. This is the default behavior for most other carriers."carrier_default— "Use the carrier's default charge behavior."
Sending on_carrier_acceptance does not enable anything. It is an
assertion that the entitlement already exists on the carrier account:
"You typically must have the carrier enable this on your account before
setting this option in your requests.""If you send a request with
charge_event: on_carrier_acceptanceand the
carrier has not enabled this feature on your account, you will receive an
error.""It can take the carrier 3-4 weeks to update your account to use the
on_carrier_acceptanceoption."
This is why the 2026-06-30 change that set on_carrier_acceptance on every
label was rejected by 100% of carriers and reverted on 2026-07-30.
Where we stand, account by account
All six are our own carrier accounts connected to ShipEngine (not
ShipStation-provided carriers), so the account relationship — and therefore the
entitlement conversation — is ours to have directly. Account IDs live in
Rails.application.credentials.shipengine.production:
| Carrier | ShipEngine account | Expected default | Confirmed? |
|---|---|---|---|
| FedEx US | se-4639775 |
pay-on-use | UNVERIFIED |
| FedEx CA | se-4639782 |
pay-on-use | UNVERIFIED |
| UPS US | se-5233835 |
unknown | UNVERIFIED |
| UPS CA | se-5233863 (shipper no. V1471A) |
bills unused labels | CONFIRMED — UPS bills unused labels |
| USPS (Stamps.com/Endicia) | se-5330594 |
outbound: charge-on-creation; returns: Pay-On-Use ACTIVE since 2026-06-03 | CONFIRMED — USPS POUR is active |
| Canada Post | se-5009700 |
event-based since 2025-07-02 | UNVERIFIED |
| Purolator | se-5009827 |
scan-based for the two return services | UNVERIFIED |
| Canpar | se-5009743 |
unknown — one unused return tag was invoiced with zero scans (see doc/tasks/202608041700_RMA_RETURN_LABEL_AUDIT_FINDINGS.md); billing trigger undetermined |
UNVERIFIED |
The one hard datum we have is negative: none of them accept
charge_event: on_carrier_acceptance on outbound labels today. One day of
production logs (2026-07-30) — UPS 23 rejections, FedEx 14, Purolator 1,
Canpar 1, Canada Post 1, plus USPS via a message-form variant. Note the USPS
rejection does not contradict the active POUR entitlement below: POUR is
returns-only, and during that window pay-on-scan was being requested on
every label including outbound.
Note the tension: FedEx and Canada Post are documented as scan-billed by
default, yet both still reject the explicit flag. That is consistent with the
ShipEngine docs — the flag is a per-account override entitlement, separate
from whatever the carrier does natively. Rejection of the flag is not
evidence that we are being billed at creation. Do not conflate the two.
Separately, retailer-owned accounts used for marketplace returns (Walmart.ca
UPS se-5380741, Costco.ca UPS se-5364680, Amazon.ca UPS se-5377028,
Amazon.ca Canada Post se-5167231, Walmart.ca Purolator se-6265849) are in
config/initializers/shipping.rb. Their billing is the retailer's problem, not
ours — do not raise entitlement requests against them.
UPS bills unused labels
Confirmed, with the receipt. This is the best-evidenced part of this document,
because it comes from our own closed UPS billing case rather than from vendor
blogs. Do not let the general "UPS is pay-on-use" claim talk you out of it.
What actually happened on ST726098
- Account V1471A — our own UPS Canada account (ShipEngine
ups_ca_account_id=se-5233863), not a retailer-owned one. - A cross-border transfer, our Canadian warehouse → our US warehouse, as a
multi-package shipment: one master plus five children. - ShipEngine errored mid-generation, but UPS had already issued all six
tracking numbers. We regenerated a second set of six for the same cartons
and shipped on those. - UPS invoiced the unused master
1ZV1471A6895329185at $426.74 on
invoice0000V1471A226(2026-05-30, CAD 971.56 total). - The labels could not be voided on UPS.com. This was attempted and failed
— screenshots went to UPS with the dispute. - Ramie opened a billing case 2026-07-01; UPS Billing Canada (Ligia C.) issued
a $426.74 credit, posting within 1–2 billing cycles.
What this establishes, and what it doesn't
Established: an errored-but-tracking-number-issued UPS label bills, is not
voidable through the UPS.com self-serve path, and is recoverable only by
opening a billing case. The money came back, so the real cost of an orphan is
staff time on a support case, not the invoice amount — as long as somebody
notices it on the invoice. An orphan nobody catches is a silent loss.
Still unconfirmed: why it billed. The leading hypothesis is that UPS's
practical billing trigger is the PLD (Package Level Detail) / End-of-Day
manifest transmission rather than a physical scan:
"If a shipping manifest is processed, all tracking on it gets 'scanned' in
the shipper's system even though there may be some tracking numbers that were
not shipped or scanned individually."
— Refund Retriever
We do not build or submit carrier manifests ourselves —
grep -rn "manifest" app/services/shipping/ finds only
Shipping::SpeedeeManifestGenerator. For ShipEngine carriers, ShipEngine
handles End-of-Day/PLD submission on our behalf
(Manifests and Carrier End of Day Documents),
so if the hypothesis holds, the errored label entered UPS's billing stream
through ShipEngine's automatic transmission. UNVERIFIED — confirm with
ShipEngine before building on it (the question to ask is under
Who to contact and what to ask).
Why charge_event was never going to fix this
Even with the pay-on-scan entitlement granted, a label UPS considers
tendered-by-manifest would presumably still bill. What actually recovered the
money was a billing dispute, and what would have prevented it sits on our
side of the line: don't let an errored label reach the manifest, or detect and
dispute it systematically. Neither needs a carrier's permission, which makes
both better bets than a 3–4 week entitlement request.
What to build, in priority order
Because the self-serve void failed, prevention and detection matter more than
remediation.
- Detect — flag any
create_labelcall that errored after the carrier
issued a tracking number, and record those tracking numbers somewhere
queryable. Today they exist only in logs. - Reconcile — match that list against UPS invoices monthly. Canpar already
emails a scanned-barcode reconciliation report (see the Canpar entry below);
UPS does not, so this one is ours to build. - Dispute — the proven path, below.
Who to contact and what to ask
Work down the ladder in AGENTS.md — API, then portal, then ticket, then
human. Most of these are portal-or-rep questions, not support tickets.
ShipEngine — one question, then stop
They are the only party who can see the state of all eight connected accounts
at once. Ask exactly this and nothing more:
For each of our connected carrier accounts (UPS
se-5233835/se-5233863,
FedExse-4639775/se-4639782, USPSse-5330594, Canada Post
se-5009700, Purolatorse-5009827, Canparse-5009743): what is the
effectivecharge_eventdefault, and which have theon_carrier_acceptance
entitlement enabled?
Second question, only if the manifest hypothesis above is still live:
Does ShipEngine include labels whose creation errored — but which returned a
tracking number — in the automatic End-of-Day / PLD transmission to UPS?
Do not ask ShipEngine to contact the carriers on our behalf. They can't
grant the entitlement and it isn't their queue.
UPS — billing case first, account rep second
The billing dispute is the proven path and it works. Do this whenever an
orphan appears on an invoice, rather than trying to void:
- UPS Billing Canada — csbillingsupport@ups.com, 1-888-592-6188.
Handled the ST726098 credit (Ligia C., Billing Canada Associate). - Have ready: account number (V1471A for the Canada account), the invoice
date and number, total amount due, the unused tracking numbers, and the
replacement tracking numbers that actually shipped for the same cartons.
Pairing unused against shipped is what made the case obvious. - Attempt the UPS.com void first anyway and screenshot the failure — that
evidence went into the successful dispute. - Credits post within 1–2 billing cycles.
The full request that worked is in the ST726098 email thread (subject
C-0372874305 - Billing/Invoice/Sender, 2026-07-01). Reuse its structure.
Then, separately, the account rep for two things the billing desk can't
answer: (1) can we get pay-on-scan / billed-on-use billing on the account —
budget 3–4 weeks per ShipEngine's guidance; (2) how does UPS treat a tracking
number that appears in a PLD transmission but never receives a physical scan?
The second question matters more than the first.
FedEx — likely nothing to do
Pay-on-use is FedEx's default for returns and FedEx bills on first scan.
Confirm with the rep rather than requesting a change. If FedEx confirms
scan-billing is already active, the charge_event rejection is cosmetic and
needs no action.
USPS — Pay-On-Use Returns ACTIVE since 2026-06-03
DONE. We reach USPS through Stamps.com/Endicia, and the feature is theirs
to enable. Stamps.com ticket 9741649 (Asmin B., 2026-06-03):
"Your request for the POUR (Pay-on-Use Return) account has been approved and
successfully activated. Your account is now live with a credit limit of
$16,000.00."
Ramie confirmed it working in production 2026-06-04 (same ticket; email
subject [Stamps.com] Re: POUR Request). So USPS return labels
(is_return_label: true) generated since 2026-06-03 bill only when
scanned — an unused one costs nothing and needs no void. Returns-only: it
does not address outbound orphans, which remain postage-at-print. (Endicia
support: 800-576-3279 ext. 140.)
Canada Post — probably already solved, verify in the portal
Event-based billing went live 2025-07-02 for commercial accounts:
"Payment will be processed on your credit card or account once the item(s)
receive a physical scan in Canada Post's network. If we don't get a physical
scan, we will not invoice you. If a label has been printed and discarded, you
will not see a charge for that label on your invoice."
If our commercial account was migrated, there is nothing to request — verify on
an invoice in the Canada Post commercial portal rather than opening a ticket.
This supersedes the older understanding that Canada Post bills forward labels
at creation.
Purolator — likely already scan-billed, verify wording
"Outbound returns and returns management shipments cannot be cancelled as
they will only be billed once the shipment is scanned."
Use their product names on the call — Outbound Return Service and
Returns Management Service. What is not documented is Purolator's
treatment of forward labels; ask the rep specifically about those.
Canpar — the genuine unknown
Canpar publishes no billing trigger. What they do publish is a reconciliation
process worth understanding, because it implies scan-driven billing with a
correction pass:
Canpar produces a monthly report of all individual barcodes with pickup and
delivery scans, aligns it against previously billed barcodes, and emails the
discrepancies to the billing contact.
Find out who our Canpar billing contact is and whether we receive that report —
it may already be the audit trail we need. Ask the rep for the billing trigger
on Return Tag Service and on forward labels.
What not to do
- Don't re-enable
charge_event: 'on_carrier_acceptance'on outbound
labels. It is rejected by every account, the drop-and-retry doubles every
create_labelcall, and the extra failure window has already 422'd the
warehouse (delivery 797431, AppSignal #3573). Re-enable it per-carrier only
after that carrier confirms the entitlement is live. - Don't read a
charge_eventrejection as "we are billed at creation."
They are independent — see
Where we stand, account by account. - Don't try to void an errored UPS label and stop there. It fails. Screenshot
the failure and open a billing case instead. - Don't file carrier tickets before checking the portal. Canada Post's
change is visible on an invoice; Purolator's terms are published. See the
external-systems ladder inAGENTS.md— five unnecessary Wayfair tickets is
the origin story for that rule. - Don't raise entitlement requests on retailer-owned accounts (Walmart.ca,
Costco.ca, Amazon.ca — listed above).
Sources
- ShipEngine — Return Labels —
charge_eventenum, the entitlement requirement, the 3–4 week lead time, and the Endicia Pay-on-Use-Returns note. - ShipEngine — Manifests and Carrier End of Day Documents
- ST726098 UPS billing case — email thread
C-0372874305 - Billing/Invoice/Sender, 2026-07-01, csbillingsupport@ups.com. The only primary evidence here. - Canada Post — Commercial invoice and billing FAQ — event-based billing, 2025-07-02.
- Canada Post — Customer return policy
- Purolator — FAQs for Shipping Systems & Tools — Outbound Return Service / Returns Management Service billing.
- Purolator — Returns Management
- Canpar — Return Tag Service and Return Solutions
- USPS — Scan Based Payment (SBP) and USPS Returns | PostalPro
- ACMA — MRS & SBP replaced by USPS Returns
- Endicia — Create Return Labels — Pay-On-Use Returns, how to request, plan eligibility.
- Refund Retriever — How to void unused UPS labels — the manifest-counts-as-scan claim and the 90/180-day void windows.
- Share A Refund — unused labels on your UPS account
Code touchpoints: Shipping::ShipengineBase#get_label_options_hash (request
shape), #get_label (the invalid_charge_event and
CHARGE_EVENT_UNSUPPORTED_MESSAGE drop-and-retry axes),
config/initializers/shipping.rb (retailer-owned accounts).