Booking flow
When you create a shipment (or confirm a draft), Carriyo runs the
booking flow. It has two parts: a synchronous part, validating the
payload and selecting a carrier, that returns immediately with status
pending; and an asynchronous part, the carrier's actual booking,
whose outcome (booked with a label, or error) arrives later on a
webhook. Knowing which part you're in helps you diagnose unexpected
results.
The sequence
create / confirm
│ synchronous: validate, select carrier, submit to carrier
├──▶ error source: CARRIYO (e.g. no carrier assignable)
▼
pending → returned to your call immediately
│ asynchronous: carrier responds, delivered by webhook
├──▶ booked tracking number + label generated
└──▶ error source: CARRIER (carrier rejected)
Carrier selection
The first decision in the flow. Two paths:
-
Explicit selection. If your call carries
carrier_account.carrier_id, the rule engine doesn't run and eligibility checks are bypassed. The named account is used as-is. Your code has made an operator-level choice and Carriyo honors it. -
Automation. If
carrier_accountis absent, the rule engine fires for the(merchant, entity_type, country)-scoped Ruleset. Each rule is evaluated against the shipment data; when a rule matches, its target carrier account is then eligibility-checked before being used:- Account active
- Merchant on the account's allowed list
- network profile covers both pickup and dropoff
- capacity profile threshold not exceeded
If the matched rule's target account fails any check, the engine falls through to the next matching rule. The first rule whose target account passes all eligibility checks wins. If no rule yields an eligible account, the shipment lands in
errorimmediately, synchronously, witherror_details[].source: CARRIYO, and no carrier is contacted.
See Shipping rules for the rule-evaluation detail.
Rate computation
Once a carrier is locked in, the rate is computed:
- Carrier Shipping Rates. If the account's Carrier shipping rates toggle is on, Carriyo calls the carrier's rates endpoint in real-time.
- costing profile. If the toggle is off (or the carrier has no rates API), the configured Costing profile computes the rate from your fixed / weight-tier / COD-surcharge config.
Both produce the same result: a cost breakdown persisted on the shipment record.
Carrier booking call (asynchronous)
This is the moment that costs real money, and it happens after your
API call has already returned pending. Carriyo packages the shipment
into the carrier's request shape and submits it, without waiting for
the reply.
When the carrier accepts, it returns a tracking number, a label (or
labels), and, for cross-border, a commercial invoice; Carriyo persists
them on the shipment and moves it to booked. When the carrier rejects
(capacity, address validation, restricted commodity), the shipment
moves to error with the carrier's message captured
(error_details[].source: CARRIER). Either way the outcome is
delivered on a status webhook, not in the original API response,
see Book a shipment. To recover
an errored shipment, see
Fix or reassign a shipment.