Ship order items#
This guide walks through shipping items of an order: creating a parcel through one of three shipping flows, optionally generating packing slips and shipping labels, then marking the parcel as shipped.
Overview#
- Choose a shipping flow and create a parcel:
- Provider flow — query
shippingProviderOptions, then create a parcel withaddProviderOptionToItems - Existing parcel flow — add items to an open parcel with
addItemsToParcel - Manual flow — supply your own track & trace with
addTrackTraceToItems
- Provider flow — query
- (Provider flow) Generate a shipping label with
createShippingLabelForParcel - Mark the parcel as shipped with
setParcelStatus
Choosing a flow#
| Flow | When to use |
|---|---|
| Provider | You ship through a connected carrier (e.g. PostNL, DHL) and want Afosto to book the shipment and generate the label |
| Existing parcel | An open parcel already exists for the same delivery — add the items to it instead of creating a new one |
| Manual | You arrange shipping yourself and only want to register a track & trace code |
All three mutations take the order item IDs to ship as items.
Flow A — Ship with a provider#
Step 1 — Query the available provider options#
Provider options are concrete carrier products (size, weight class, cost) available for your items.
Step 2 — Create the parcel#
Input: AddProviderOptionToItems!
| Name | Type | Required | Description |
|---|---|---|---|
provider_option_id | String! | Required | ID of the provider option from step 1. |
items | [String!]! | Required | Order item IDs to ship in this parcel. |
Returns: AddProviderOptionToItemsPayload
| Name | Type | Required | Description |
|---|---|---|---|
parcel | Parcel▾ | Optional | The created parcel |
items | [OrderItem!]!▾ | Required | Items shipped in the parcel |
Save the returned parcel.id — you'll need it for the label and status steps.
Step 3 — Generate the shipping label#
Input: CreateShippingLabelForParcelInput!
| Name | Type | Required | Description |
|---|---|---|---|
parcel_id | String! | Required | ID of the parcel from step 2. |
printer_id | Int64 | Optional | ID of the printer to print the label on directly. |
Returns: CreateShippingLabelForParcelPayload
| Name | Type | Required | Description |
|---|---|---|---|
parcel | Parcel▾ | Optional | The parcel including the generated label |
The response includes labels[].label_url — a URL to the printable label — and the carrier track_trace details.
Generate labels one parcel at a time (or use GraphQL aliases to batch) so a single carrier failure does not fail the whole request.
Flow B — Add items to an existing parcel#
Use this when an open parcel already exists for the same delivery (same origin, destination, and shipping method). Only parcels with status OPEN can receive additional items.
Input: AddItemsToParcelInput!
| Name | Type | Required | Description |
|---|---|---|---|
parcel_id | String | Optional | ID of the open parcel — when omitted, the items are added to an existing matching parcel or a new one is created. |
items | [String!]! | Required | Order item IDs to add. |
Returns: AddItemsToParcelPayload
| Name | Type | Required | Description |
|---|---|---|---|
parcels | [Parcel!]!▾ | Required | Parcels the items were added to |
items | [OrderItem!]!▾ | Required | Items added to the parcel |
Find open parcels by querying the order's deliveries and filtering parcels on status: OPEN. Make
sure the items share the delivery's origin address, destination address, and shipping method.
Flow C — Manual shipping with your own track & trace#
Use this when you book the shipment outside Afosto and only want to register the tracking details.
Input: AddTrackTraceToItemsInput!
| Name | Type | Required | Description |
|---|---|---|---|
track_trace_url | String! | Required | Tracking URL provided by your carrier. |
track_trace_number | String! | Required | Tracking number provided by your carrier. |
items | [String!]! | Required | Order item IDs to ship in this parcel. |
Returns: AddTrackTraceToItemsPayload
| Name | Type | Required | Description |
|---|---|---|---|
parcels | [Parcel!]!▾ | Required | Parcels carrying the updated track & trace |
items | [CollectionItem!]!▾ | Required | Items the track & trace was attached to |
The response includes the created parcel carrying the track & trace details you supplied.
Mark the parcel as shipped#
Setting the parcel status to IN_TRANSIT completes the flow — the items are now registered as shipped on the order.
Input: SetParcelStatusInput!
| Name | Type | Required | Description |
|---|---|---|---|
parcel_id | String! | Required | ID of the parcel. |
status | ParcelStatus!▾ | Required | New status — use IN_TRANSIT to mark as shipped. |
Returns: SetParcelStatusPayload
| Name | Type | Required | Description |
|---|---|---|---|
parcel | Parcel▾ | Optional | The updated parcel |
In the provider flow, only set the status to IN_TRANSIT after the shipping label was generated
successfully — a parcel without a label cannot be handed over to the carrier.
Batching multiple parcels#
All parcel mutations accept one input per call. To process multiple parcels in a single request, use GraphQL aliases:
Each aliased call returns its own parcels in the response.
Notes#
- Items in one parcel must share the same origin, destination, and shipping method. Split items across multiple parcels when they differ.
- A delivery can have multiple parcels; query the order's deliveries to see existing parcels and their statuses.
- In the provider flow, the track & trace details are filled in by the carrier when the label is generated — they will be empty until then.
- Packing slips are generated per parcel via the REST endpoint for parcel slip options and are independent of the shipping label.
- Bundles and composed products (
OFFER,PART,PRICED_PART,ASSEMBLE_BUNDLE) are shipped by their individual item IDs, the same as regular items. - See Authentication for how to pass your API key.