Choosing a service from the offer
Most integrations already know which carrier service they want and pass a
fixed service_id. When you don't — when you want to present the customer
(or your own rules engine) the set of services that can actually carry
this parcel and pick one — price the shipment across all services first,
then choose against the full set of constraints, not price alone.
The cheapest quote is often the wrong pick: a point-to-point service needs a
locker id, an international one needs customs data, some services require an
ordered courier pickup. A service you can't satisfy fails at order_send,
not at valuation.
This guide covers the front of the flow. Everything after order creation (waybill, tracking, cancellation) is identical to the Order lifecycle — this page only replaces the way the service is selected.
order_valuation (no service_id) → service_structure (map requirements) →
enrich payload (pickup / point / customs) → order_send →
waybill / tracking / … (see Order lifecycle)
Examples use the PHP SDK; each step names the underlying API method, so the flow maps 1:1 to raw envelope requests from any language.
1. Price across services — order_valuation without a service
Build the order on a neutral skeleton — SELF pickup, no point, no
customs — and omit the service. order_valuation then returns a
price_table with every service that can carry this parcel.
Code
Without the SDK — same call, no service_id in the payload:
Code
Price the skeleton, not the final order
Adding service-specific fields (a point, a courier pickup, customs) can change or restrict what's available. Quote first on the neutral order, enrich only after you choose.
2. Map the offer to service_structure — check the requirements
price_table tells you who can carry it and for how much.
service_structure tells you what each service demands. Join them by
service_id. Read the dictionary from cache (refresh about once a day)
rather than calling it on every valuation — see
Best practices.
Code
What each flag means for the payload you'll build in step 3:
Service condition (from service_structure) | What you must add before order_send |
|---|---|
pickup_courier = 2 (courier required) | pickup.type = COURIER + date / hours_from / hours_to — pick a window from pickup_hours |
pickup_courier = 0 (courier unavailable) | SELF / drop-off only — no courier pickup |
point routing (door_to_point / point_to_point / point_to_door = 1) | a foreign_address_id from points/{type}/ on the relevant side (sender and/or receiver) |
domestic = 0 (international) | customs: customs_data per shipment item (+ the top-level customs block where the service requires it) |
| COD / options wanted | check options in the dictionary, and option_cod / option_send / option_deliver on the chosen point |
Cheapest ≠ best
Choose against your own policy — SLA, routing, and whether you can actually
meet the extra requirements — not the lowest price_gross. Filtering the
offer down to fulfillable services is the whole point of this flow.
3. Enrich the payload for the chosen service
Once chosen, set the service and add only the fields that service needs.
Code
The top-level customs block (content_type, EORI_number,
documents_form, documents) has no typed builder yet. If the service
requires it, convert the order with toArray(), add the block and pass the
array to sendOrder() — it accepts both.
Pickup naming trap
At order creation the fields are plural — hours_from / hours_to. The
standalone pickup / batch_pickup endpoints use the singular hour_from /
hour_to. See Pickup types.
Enriching the order can change its price — if you showed the first quote to the customer, re-price the final payload before sending (see Order lifecycle → step 2b).
4. Create the order — order_send
Code
order_send is not idempotent — a retried timeout can create a
duplicate order. Reconcile with getOrders() before retrying, never
blind-retry a write. See
best practices.
5. Continue as usual
From here the flow is identical to the Order lifecycle: download the waybill, optionally the dispatch code / turn-in, then track the shipment (Tracking). Cancellation and order inspection are unchanged.
See also: Order lifecycle · Pickup types · Tracking · Best practices · Request signing (HMAC)

