Skip to main content

Collection & Pickup Workflow (Enlèvements)

This guide demonstrates how fulfillment orders get grouped into a collection batch (a "collect") for a scheduled carrier pickup, through the Wing API v3.

Overview​

A pickup location (OrganizationPickup) has one fixed carrier (organizationExpeditor) and its own pickup schedule (plannedCollectCronRules) — you don't choose a carrier or a date per collect, you ask for the next collect of that pickup location and attach labelled fulfillment orders to it:

  1. Authentication - Obtain an access token
  2. Query Pickup Locations - Find the pickup location's id and its carrier
  3. Get the Next Collect - upsertNextCollect for that pickup location
  4. Add Fulfillment Orders to the Collect - Attach labelled fulfillment orders to the batch
  5. Track the Collect - Follow the batch through pickup and closure

Collect lifecycle​

A Collect moves through a fixed set of CollectStatus values:

CANCELLED is not reachable from the v3 API — there is no cancel mutation exposed here; it happens only through Wing's internal operations tooling.

Data model for this workflow​

Each OrganizationPickup has exactly one OrganizationExpeditor (its carrier) and produces many Collects over time; each Collect batches many FulfillmentOrders:

Step 1: Authentication​

First, obtain an access token using your credentials:

mutation {
createAccessToken(
input: { email: "your_email@example.com", password: "your_password" }
) {
accessToken
refreshToken
expiresAt
}
}

Step 2: Find your Pickup Locations​

List the pickup points configured for your organization, along with their carrier:

query {
organizationPickups(input: { limit: 25 }) {
id
friendlyName
line1
city
zip
countryCode
organizationExpeditor {
id
company
}
plannedCollectCronRules
}
}

Important: Save the id of the pickup location you want to schedule a collect from. The carrier and the pickup schedule are already fixed on this object — there's nothing to choose per collect.

Step 3: Get the Next Collect​

Ask for the next collect of that pickup location. upsertNextCollect is idempotent for the current collect window — the pickup's own plannedCollectCronRules decide when a new window opens, so calling it again before the current one closes just returns the same Collect:

mutation {
upsertNextCollect(input: { organizationPickupId: "pickup_456" }) {
id
status
shift
shouldStartAt
shouldEndAt
}
}

Response:

{
"data": {
"upsertNextCollect": {
"id": "collect_789",
"status": "INITIATED",
"shift": "MORNING",
"shouldStartAt": "2024-02-20T08:00:00Z",
"shouldEndAt": "2024-02-20T10:00:00Z"
}
}
}

Important: Save the id (collect_789) — it is the collectId used to attach fulfillment orders in the next step.

Step 4: Add Fulfillment Orders to the Collect​

Once a fulfillment order has a parcel and shipping label, add it to the batch. Failures for individual fulfillment orders are returned in error, not thrown — always check it alongside fulfillmentOrders:

mutation {
addFulfillmentOrdersToCollect(
input: {
collectId: "collect_789"
fulfillmentOrderIds: ["fo_123", "fo_456"]
}
) {
collect {
id
status
}
fulfillmentOrders {
id
status
}
error {
notFoundIds
notLabelledIds
statusNotAllowedIds
archivedIds
notNewIds
}
}
}

Fulfillment orders can be removed the same way, before the carrier picks up the batch — note there is no collectId here, it is resolved from each fulfillment order's current collect:

mutation {
removeFulfillmentOrdersFromCollect(
input: { fulfillmentOrderIds: ["fo_456"] }
) {
fulfillmentOrders {
id
status
}
error {
notInCollectIds
inAnomalyIds
inClosedCollectIds
}
}
}

Step 5: Track the Collect​

Poll the collect's status until the carrier has picked it up and the batch has been processed:

query {
collects(input: { limit: 10 }) {
id
status
shouldStartAt
shouldEndAt
parcelsCount
receivedParcelsCount
}
}

Common Errors​

Error / fieldCauseSolution
PICKUP_LOCATION_NOT_FOUNDInvalid organizationPickupIdVerify the pickup location's id via organizationPickups
addFulfillmentOrdersToCollect.error.notFoundIdsUnknown fulfillmentOrderIdsVerify the IDs from createOrder/createFulfillmentParcel responses
addFulfillmentOrdersToCollect.error.notLabelledIdsFulfillment order has no parcel/label yetCall createFulfillmentParcel before adding the FO to a collect
addFulfillmentOrdersToCollect.error.statusNotAllowedIdsFulfillment order status doesn't allow collectionQuery fulfillmentOrder.status before retrying
removeFulfillmentOrdersFromCollect.error.inClosedCollectIdsCollect already RECEIVED/FINISHEDChanges are only possible while the collect is INITIATED

Next Steps​