Shipment lifecycle
Separate draft creation, booking acceptance, and completed booking.
Creating a shipment saves a draft. Booking is a separate request: the API accepts it, then a background worker contacts the carrier. Read the shipment to find the completed result.
Lifecycle at a glance
This diagram shows the normal flow for carrier shipments. Cancellation is available only when the shipment meets the eligibility rules below.
PENDINGDraft savedCreate a draftPROCESSINGBooking acceptedBackground workBOOKEDBooking completedCarrier booking succeedsPICKED_UPPicked upPickup is recordedDELIVEREDDeliveredDelivery is recorded
- Booking failure:
PROCESSING→FAILED. Read the failure code and message. - Cancellation: eligible
PENDINGorBOOKED→CANCELED. See the cancellation rules below.
| Stage | What the response confirms | What to do next |
|---|---|---|
| Draft saved | POST /shipments returns 201 and PENDING. No carrier booking has been requested. |
Review or update the draft, then request booking. |
| Booking accepted | POST /shipments/{id}/book returns 200 and PROCESSING. The request has been accepted and dispatched for background processing. |
Read GET /shipments/{id} for the result. |
| Booking completed | A shipment read reports BOOKED. Background booking has succeeded. |
Read tracking and request an existing label when ready. |
| Booking failed | A shipment read reports FAILED with a failure code and message. |
Inspect the failure details before deciding the next action. |
OTHER shipments do not follow the carrier-booking flow and cannot have printable labels.
Create or update a draft
POST /shipments returns 201 with a priced PENDING draft and stored address snapshots. It does not book. PUT /shipments/{id} returns 200 after updating and repricing an eligible draft. Updating and booking require PENDING and exclude shipments linked to payments, quotations, proforma data, or automatic returns.
The reference uses GLS Business Parcel with one package. Use a service and package type returned by service discovery for your account. Supply the required package/contact fields and a valid pickup date on the Copenhagen calendar; carrier dates cannot be in the past.
For SHOP_DELIVERY, select a GLS pickup location before previewing a price or creating the draft. Price and shipment requests need only pickupLocation: { externalLocationId }. Bookogsend supplies the shop details.
Request booking and read the result
Send {} to POST /shipments/{id}/book with Authorization, JSON Content-Type, and a new Idempotency-Key. Booking validates the stored draft and recalculates its price.
200 with PROCESSING confirms booking acceptance and queue dispatch. It does not confirm completed carrier booking. Read GET /shipments/{id} at a modest interval to observe progress, within the account rate limit. A later read reports BOOKED or FAILED. Failed shipments include a safe failure code and message. Shipment reads include tracking numbers and package delivery states; pickup and delivery updates appear as they are recorded.
409 PRICE_CHANGED leaves the draft PENDING, updates its stored price, and returns errors.price. Review the new price and use a new idempotency key to accept it. The old key replays the price conflict. 409 SERVICE_NO_LONGER_AVAILABLE queues nothing.
Cancel a shipment
Send {} to POST /shipments/{id}/cancel with an idempotency key. Eligible PENDING or BOOKED shipments become CANCELED and remain stored. Already canceled shipments succeed.
Cancellation can be rejected with 409 CANCELLATION_NOT_ALLOWED; errors.currentStatus reports the shipment status. Success confirms committed cancellation. Notifications and fulfillment reconciliation run afterward in the background.
Download an existing label
GET /shipments/{id}/label requires SHIPMENTS_READ and returns 302 with a Location header pointing to a PDF URL signed for five minutes. Follow the redirect in your HTTP client. Request a fresh URL when it expires. This response has no JSON success envelope.
Labels require a printable service, a BOOKED, PICKED_UP, or DELIVERED state, and an existing PDF. labelReady in reads is a lifecycle hint; it does not verify the PDF exists. The endpoint returns 409 LABEL_NOT_READY for an unready/missing label and 400 LABEL_NOT_SUPPORTED for an unsupported service. It never books or regenerates a label.