Outtake
An outtake ships vaulted units back out to an address you specify. Requesting one takes the units out of circulation immediately — they stop being sellable and cannot be outtaken again until the request completes or is cancelled.
Queries
previewOuttakeFees
Quote a selection before requesting — read-only, nothing locked or reserved. Takes the same selectors as the outtake mutation (line items, end user, or product + quantity) plus the savedAddressId it would ship to, and returns one preview per facility the selection spans, since fees are charged per facility group:
query {
previewOuttakeFees(input: { externalUserId: "user-8821", savedAddressId: "9f8e…" }) {
previews {
facilityId
itemCount
handling { totalCents isComplete }
shipping { pending carrier service totalCents parcelCount unquotableConfigurationIds }
dwell { storagePerUnitDayCents freeDays unitCount billableUnitDaysAsOf estimatedCents asOf }
totalCents
}
error { message code }
}
}
totalCents is handling + shipping + dwell as one figure, and it is null whenever any part is unresolved — never show a partial sum as the price. Shipping quotes asynchronously: on the first call shipping.pending is true and shipping.totalCents is null, so poll until it resolves. Omit savedAddressId to price handling and dwell only. dwell estimates storage beyond the free days — billableUnitDaysAsOf keeps accruing until the outtake is packed, so the estimate is stamped asOf.
getOuttakeRequests
query {
getOuttakeRequests(input: { includeProductInfo: true, pagination: { limit: 20 } }) {
facilityMovementRequests {
id
facilityId
facility { id name }
status
cancelBy
completeBy
isCancellable
items { lineItemId status releasedAt }
productSummaries { assetConfiguration { name primaryImageUrl } keyId unitCount lineItemCount }
}
pagination { totalCount hasNextPage }
error { message code }
}
}
Defaults to in-progress requests — REQUESTED, PROCESSING, IN_TRANSIT, PARTIALLY_COMPLETED. Pass statuses to reach finished ones:
getOuttakeRequests(input: { statuses: [COMPLETED, CANCELLED] })
includeProductInfo attaches per-product rollups (productSummaries) — the full catalog row plus unit and line-item counts per product, so a list screen doesn't need a follow-up read per request. Reads also carry the facility the request is at, the shipTo address as captured at request time, and the money: outtakeQuote is what you agreed to at request time, chargedTotalCents is what packing actually assessed (null until then — show the quote until it lands).
getOuttakeRequest
One request in full, including the shipping side:
query {
getOuttakeRequest(input: { facilityMovementRequestId: "9f8e…", includeProductInfo: true }) {
facilityMovementRequest { id status cancelBy completeBy items { lineItemId status releasedAt } }
transfers { id status }
shipmentGroups { id }
error { message code }
}
}
shipmentGroups is where tracking lives — shipping labels on them carry tracking codes, carrier, and status once the facility purchases labels.
Lifecycle
You don't drive the status — it follows the shipment.
| Status | Means |
|---|---|
REQUESTED | Created. Units are gated and can't be sold |
PROCESSING | The facility is working the request — picking, packing, purchasing labels |
IN_TRANSIT | Labels are scanning |
COMPLETED | Every label delivered. Units have left the vault |
PARTIALLY_COMPLETED | Some items released, some still pending |
CANCELLED | Cancelled before the window closed. Units back in the vault |
On completion the units stop being vaulted: their placements move to UNVAULTED and they no longer appear in listFacilityItems as held stock. You still own them — they're just no longer with us, so they can't back a sale on the exchange until they're intaken again.
Mutations
requestFacilityLineItemOuttake
Ships vaulted units back out. Three ways to select what ships — provide exactly one:
lineItemIds— explicit unitsexternalUserId— everything held for one of your end usersassetConfigurationId+quantity(optionally narrowed bykeyId) — the server picks that many vaulted units of the product, oldest first
Units ship to one of your saved addresses. Create one first with createSavedAddress, or look up an existing id with getSavedAddresses. See Address Management.
mutation {
requestFacilityLineItemOuttake(input: {
lineItemIds: ["a1b2…", "c3d4…"]
externalRef: "your-ref-0001"
savedAddressId: "9f8e…"
notes: "Leave at side door"
}) {
facilityMovementRequests {
id
facilityId
status
cancelBy
completeBy
items { lineItemId status }
}
transfers { id status }
error { message code }
}
}
To ship everything held for one of your end users, swap the selector:
requestFacilityLineItemOuttake(input: {
externalUserId: "user-8821"
externalRef: "your-ref-0002"
savedAddressId: "9f8e…"
})
Or ship a quantity of one product without naming units — the server picks the oldest vaulted units first:
requestFacilityLineItemOuttake(input: {
assetConfigurationId: "315b…"
keyId: "29ac…"
quantity: 10
externalRef: "your-ref-0003"
savedAddressId: "9f8e…"
})
| Field | Notes |
|---|---|
lineItemIds | Up to 500, no duplicates. Exclusive with the other selectors |
externalUserId | Ships every VAULTED unit held for that user |
assetConfigurationId / keyId / quantity | Quantity selector — that many vaulted units of the product, oldest first. Short supply returns INSUFFICIENT_VAULTED_QUANTITY with the available count |
externalRef | Your idempotency key. Required |
savedAddressId | Where it ships. Required, and must be an address on your account |
notes | Handling instructions for the facility. Optional |
allowPalletization | Consent to palletized/repacked fulfilment and its pricing — higher handling fee, freight billed at actuals. The facility decides the actual mode at packing; without consent the request is always priced as parcels. Defaults to false |
preferredCarrier | Preferred carrier (UPS, FEDEX, USPS). Preference only — no label is bought at request time; it seeds the default when labels are purchased and is overridable then |
preferredSpeed | Preferred shipping speed. Preference only |
preferredInsurance | Whether you want the shipment insured. Preference only |
The address is copied onto the request when it's created. Editing that saved address afterwards does not redirect a shipment already in flight.
Units spanning facilities
If the selected units sit at more than one facility, you get one request and one transfer per facility — they ship separately. facilityMovementRequests is a list for this reason.
Retries
externalRef is an idempotency key. Retrying with the same value returns the original request rather than creating a second one, so a timeout is always safe to repeat.
Over the limit
An end-user selection with more than 500 vaulted units returns TOO_MANY_LINE_ITEMS with the real count. It does not ship the first 500 — narrow the selection with lineItemIds and send it in batches.
cancelOuttakeRequest
mutation {
cancelOuttakeRequest(input: { facilityMovementRequestId: "9f8e…" }) {
facilityMovementRequest { id status }
transfers { id status }
error { message code }
}
}
Cancelling returns the units to the sellable pool and clears the gates set when the request was made.
cancelBy is a hard cutoff — past it, cancellation fails with CANCEL_WINDOW_CLOSED whatever the status. A null cancelBy means no deadline was set, not a deadline of now. isCancellable reflects the current moment and goes stale once cancelBy passes.
Cancelling an already-cancelled request succeeds rather than erroring, so retries are safe.
Errors
| Code | Cause |
|---|---|
VALIDATION_ERROR | Zero or multiple selectors given, or externalRef missing |
NOT_FOUND | No vaulted units for that end user, unknown request, or an address that isn't yours |
TOO_MANY_LINE_ITEMS | More than 500 units selected |
DUPLICATE_LINE_ITEM_IDS | The same line item appears twice |
INSUFFICIENT_VAULTED_QUANTITY | Quantity selector asked for more units than are vaulted — the payload carries the available count |
OUTTAKE_DISABLED | A unit is gated — usually an outtake already in flight |
CANCEL_WINDOW_CLOSED | cancelBy has passed |