Canada Post Returns — how it all fits together

The single-page map of the Canada Post RMA return flow. Detail lives in the
task docs linked at the bottom; when they disagree with this page, this page
is newer (2026-08-04).

The flow in one paragraph

Canadian RMA returns default to the Canada Post shipping option
(option default 2026-07-01, commit 638a6f3a57; the customer-facing QR
flow went live 2026-07-22, commit 391344e593 / PR #1664, announced
deployed by Ramie the same day). We never generate a return label for
them — ShipEngine cannot produce a Canada Post return label, and attempting
one falls back to a chargeable forward label. Instead the customer uses
Canada Post's own Manage Returns hosted policy, which issues a
print-at-home label or a label-free QR code. Rma#canada_post_return?
(shipping_option.carrier == 'Canadapost') gates return_label_required?
off and switches the customer email to the canada_post_return_html block
carrying the policy link.

The live policy

  • PR267361 — "WarmlyYours Return Policy - Print at home or
    Label-free/QR", status Active.
  • RA validation: "No RA number required." The policy collects an
    optional Return No. (customer types their RMA number; unvalidated;
    prints on the label as a reconciliation reference — it is NOT a gate).
  • Method 1 (preferred; collects Return No. + email):
    https://www.canadapost-postescanada.ca/pr-rc/en/get-return-label?id=PR267361
    (Rma::CANADA_POST_RETURNS_POLICY_URL).
  • Method 2: quote the bare policy ID PR267361 at any Canada Post
    outlet; staff print the label. Collects nothing.

The only gate is operational: the Method 1 link is sent exclusively to
CA customers with an approved RMA (RMA email + return instructions PDF).
Never publish it. Note the exposure is NOT mass label generation (unused
labels are $0 under pay-on-use) — it's that anyone with the link can
physically ship us unwanted parcels, each billed on delivery; recourse is
invoice monitoring + disputes.

The RA-validation endpoint is dead — do not build on it

Api::V1::CanadaPost::ReturnsController (/v1/canada_post/ValidateRsa/…,
PR #1099) implements Canada Post's "validate my external web service"
option. Canada Post never calls it. Controlled retest 2026-07-17: the
merchant-side validation test sent nothing to a neutral webhook.site token,
and the real customer flow issued a QR label without ever prompting for an
RA number. Support case filed 2026-06-10, never answered. The endpoint,
Rma.canada_post_return_valid?, the canada_post_returnable scope, and
record_canada_post_return_inquiry are all dead code kept only as ticket
evidence — see the cleanup task
doc/tasks/202608041100_CANADA_POST_RA_ENDPOINT_CLEANUP.md.

Billing

Canada Post commercial accounts moved to event-based billing 2025-07-02:
a label/QR bills only on physical scan into their network. An unused
Manage Returns label therefore costs nothing (per vendor docs — our own
account behaviour UNVERIFIED; see
doc/integrations/CARRIER_LABEL_BILLING.md).

Visibility in our data

Manage Returns labels create no Shipment record — any per-carrier
return-label analysis over shipments is blind to this flow. Evidence a
customer actually shipped:

  • inbound tracking numbers on rmas.tracking_numbers (external
    registration path), and the RMA's own state transitions;
  • historical Canadapost label_complete shipments predate this flow —
    those were ShipEngine-bought forward labels, not Manage Returns.

Merchant-side notifications (inbound/received emails from the portal's
Notification settings tab) are not yet wired up — the plan is in the
contingency task doc below.

Amazon.ca returns — current manual process, and the QR goal

First live case (RMA60888, 2026-07-30, order 701-7386997-6232265):
a CSR (Shiva) opened our Manage Returns policy link, generated the Canada
Post label, and uploaded it to Seller Central as a "Seller uploaded
label"
(carrier CANADA_POST, tracking 8390279740463741), with the RMA
number as the return reference. That's how the tracking number entered our
system, and it works — but it's one manual label per return, and it
forfeits the label-free/QR experience.

To explicate (open design question, 2026-08-04): how Amazon.ca
returns can skip label generation/upload entirely and instead get the
customer the QR / policy link. Constraints to research: Amazon's
seller-fulfilled return options for CA (whether an RMA-number-only /
merchant-contact return authorization is allowed vs. a prepaid label being
mandatory), and where our policy link could be surfaced (return
authorization message, Communication history, or automated via
SP-API merchant returns). Until that's answered, the CSR
label-generate-and-upload path above is the sanctioned workaround.

Not built yet (decided 2026-08-04; first live return RMA60888 proved the
data exists). The portal's Returns → Inbound returns table shows, per
return: the CP tracking number, Customer reference = the RMA number
(the policy's Return No. field flows straight through), shipping service,
origin/destination, expected delivery date, and last scan status/date —
and offers Excel/CSV export of the results. So the reconciliation
source is self-service: a periodic export (or the per-policy notification
emails, up to 4 recipients, Received/Exception/Delivery events) can drive
matching CP tracking numbers onto rmas.tracking_numbers and advancing
RMA state, replacing today's manual CSR entry. First verify how the
2026-07-30 return's tracking number actually entered our system (manual
vs. some existing path) before designing the feed.

  • doc/tasks/202606121059_CANADA_POST_RETURNS_NOTIFICATION_CONTINGENCY.md
    — the full investigation: RA-gate retests, policy setup, notification plan.
  • doc/tasks/202606031500_PAPERLESS_PAY_ON_USE_RMA_RETURNS.md — Phase 2
    background.
  • doc/tasks/202608041100_CANADA_POST_RA_ENDPOINT_CLEANUP.md — removing the
    dead RA-validation endpoint.
  • doc/integrations/CARRIER_LABEL_BILLING.md — per-carrier billing triggers.