Skip to main content

New Shipping Capabilities in Storefront API Draft

warning

This document is a draft and what it contains is not available yet in any environment, and is subject to change.

This page covers the new shipping fields and mutations available in the Storefront API — enriched shipping method data, pickup locations, updated set mutations, and shipping provider custom data on sessions, methods, and locations.


Get Shipping Methods

checkout.shippingMethods accepts an optional optimizeFor argument — an enum that filters the returned shipping methods for a specific display context. When omitted, the full standard set is returned.

ValueContext
"applepay"Apple Pay payment sheet
"googlepay"Google Pay payment sheet
"ams"AMS

ShippingMethod

ShippingMethod is available on checkout.shippingMethods and checkout.deliveryGroups[].shippingMethods (the list of available options), and on checkout.shippingMethod and checkout.deliveryGroups[].shippingMethod (the currently selected method).

FieldTypeStatusDescription
idInt!ExistingUnique identifier for the shipping method
nameString!ExistingPlain text, max 50 characters. The primary customer-facing label for the shipping option
priceMonetaryValue!ExistingEffective price. See MonetaryValue for sub-fields
originalPriceMonetaryValueNewPre-discount price, shown struck through next to price. null when there is no discount. When present, always strictly greater than price
selectedBoolean!ExistingWhether this method is currently selected on the checkout
carrierNameStringNewCustomer-facing carrier or brand name (e.g. "DHL Express", "Eco delivery"). null when the method does not originate from an external shipping provider
serviceCodeStringNewMachine-readable carrier service identifier (e.g. "EXPRESS", "PICKUP"). Not for customer display. null when the method does not originate from an external shipping provider
providerStringNewMachine-readable identifier of the ESE provider/plugin that returned this option (e.g. "ingrid"). Distinct from carrierName, which is the customer-facing carrier brand. null when the method does not originate from an external shipping provider
providerOptionIdStringNewThe provider's own identifier for this shipping option, passed through as-is. Not for customer display — mainly useful for correlating with the provider's own logs or support tooling. null when not supplied
internalOptionIdIntNewAn internal numeric identifier assigned by the ESE/provider system, passed through as-is. null when not supplied
deliveryTypeDeliveryTypeNewFulfillment method. One of: TO_DOOR, PICKUP, LOCKER, MAILBOX, OTHER. See DeliveryType values. null when the method does not originate from an external shipping provider
descriptionStringNewShort plain-text subtitle, max 120 characters, no markup or newlines (e.g. "Next business day delivery"). null when not supplied by the provider
iconUrlStringNewHTTPS URL to a square SVG image (1:1 aspect ratio). The frontend is responsible for sizing. null when not supplied by the provider
etdShippingETDNewEstimated time of delivery. See ShippingETD. null when not supplied by the provider
labelsShippingLabelList!NewPaginated. Visual indicators attached to the option. Max 5 entries. Empty list when none (never null). See ShippingLabel
customerChoicesShippingMethodCustomerChoiceList!NewPaginated. Customer-configurable selections. Max 10 entries. Empty list when none (never null). See ShippingMethodCustomerChoice
hasLocationBoolean!NewWhether this method supports selectable pickup/drop-off locations. Use this as the authoritative capability flag
locationsShippingMethodLocationList!NewPaginated. Pickup/drop-off locations pre-populated by the ESE for the current shipping address. May be empty even when hasLocation is true — when empty, call getShippingMethodLocations with the order address to retrieve locations
selectedLocationShippingMethodLocationNewThe location currently attached to this method, or null if none has been set
shippingProviderCustomDataShippingProviderCustomDataList!NewPaginated. Provider-defined key/value custom data attached to this shipping method by the ESE. Same structure as Session.shippingProviderCustomData

MonetaryValue

Sub-fieldTypeDescription
valueFloat!Numeric amount
currencyCurrency!Currency object (e.g. ISO 4217 code "SEK", "EUR")
formattedString!Display-ready string (e.g. "50.00 SEK")
formattedValueString!Deprecated — use formatted instead

DeliveryType values

ValueDescription
TO_DOORThe parcel is delivered directly to the customer's address by a carrier.
PICKUPThe customer collects the parcel from a designated pickup point.
LOCKERThe parcel is delivered to an automated parcel locker.
MAILBOXA small parcel or letter-sized shipment delivered directly into the customer's physical mailbox.
OTHERCatch-all for delivery types not covered by the values above.

Frontends should handle all five values. OTHER is the safe fallback rendering.

Pagination

labels, customerChoices, locations, shippingProviderCustomData, and their nested list fields (customerChoices[].options, shippingProviderCustomData[].data, openingHours.periods, openingHours.specialDays) all take (limit: Int = 20, page: Int = 1) arguments and return a { list, pagination } wrapper rather than a bare array. Select list { ... } to get the actual entries. pagination (a PaginationInfo) is optional to select if you don't need paging metadata.

Full fragment:

fragment ShippingMethodFields on ShippingMethod {
id
name
selected
hasLocation
carrierName
serviceCode
provider
providerOptionId
internalOptionId
deliveryType
description
iconUrl
price { value currency { code } formatted }
originalPrice { value currency { code } formatted }
etd {
relative { min max units }
absolute { from to }
custom
}
labels {
list {
type
displayName
description
iconUrl
}
}
customerChoices {
list {
id
displayName
description
type
default
value
price { value currency { code } formatted }
options { list { key displayName description price { value currency { code } formatted } } }
}
}
selectedLocation {
id
displayName
address { address1 city zipCode country { name } }
latitude
longitude
distanceMeters
openingHours {
periods { list { open { day hour minute } close { day hour minute } } }
specialDays { list { date { year month day } isClosed comment } }
}
openingHoursText
brickAndMortar
shippingProviderCustomData { list { provider data { list { key value } } } }
}
locations {
list {
id
displayName
address { address1 city zipCode country { name } }
latitude
longitude
distanceMeters
openingHours {
periods { list { open { day hour minute } close { day hour minute } } }
specialDays { list { date { year month day } isClosed comment } }
}
openingHoursText
brickAndMortar
shippingProviderCustomData { list { provider data { list { key value } } } }
}
}
shippingProviderCustomData { list { provider data { list { key value } } } }
}

ShippingMethodLocation

Represents a physical pickup or drop-off location. Appears on ShippingMethod.locations, ShippingMethod.selectedLocation, and as the return type of getShippingMethodLocations.

FieldTypeDescription
idString!Unique identifier for this location
displayNameString!Human-readable name of the location
addressAddressPhysical address
latitudeFloatGeographic latitude
longitudeFloatGeographic longitude
distanceMetersFloatDistance in meters from the current shipping address to this location
openingHoursOpeningHoursRegular opening hours and special day exceptions. See OpeningHours
openingHoursTextStringHuman-readable opening hours summary
brickAndMortarIntID of a Centra brick-and-mortar store associated with this location, or null if none. When present, indicates the order may be fulfilled by that physical store
shippingProviderCustomDataShippingProviderCustomDataList!Paginated. Provider-defined key/value custom data attached to this location by the ESE. Same structure as Session.shippingProviderCustomData

OpeningHours

FieldTypeDescription
periodsOpeningHoursPeriodList!Paginated. Regular weekly opening hours as a list of open/close periods
specialDaysSpecialDayList!Paginated. Exceptions to the regular schedule (holidays, closures, etc.)

OpeningHoursPeriod

Each period has an open point and an optional close point. close is null for locations that are open 24 hours. A period can span midnight (e.g. open Monday 09:00, close Tuesday 02:00).

FieldTypeDescription
openOpeningHoursPoint!When the period starts
closeOpeningHoursPointWhen the period ends. null means open 24 hours

OpeningHoursPoint

FieldTypeDescription
dayInt!Day of week: 0 = Sunday, 1 = Monday, …, 6 = Saturday
hourInt!Hour in 24-hour format (0–23)
minuteInt!Minute (0–59)

SpecialDay

FieldTypeDescription
dateSpecialDayDate!Calendar date of the exception
isClosedBoolean!Whether the location is closed for the entire day
commentStringHuman-readable note (e.g. "Christmas Day")

SpecialDayDate

FieldTypeDescription
yearInt!Year (e.g. 2026)
monthInt!Month (1–12)
dayInt!Day of month (1–31)

ShippingMethod.locations may be pre-populated by the ESE when shipping methods are fetched, but it can be empty even when hasLocation is true. When locations is empty, call getShippingMethodLocations with the order address as the search address to retrieve locations. Also use it to search at a different address or retrieve more results. Only call it when hasLocation is true. Pass the optional deliveryGroupId argument to scope the lookup to a specific delivery group's own shipping methods.

# Search by address
query {
getShippingMethodLocations(
shippingMethodId: 42
deliveryGroupId: "1"
address: { address1: "14 Downing Street", city: "London", zipCode: "SW1A 2AA", country: "GB" }
) {
id
displayName
address { address1 city zipCode country { name } }
openingHours { periods { list { open { day hour minute } close { day hour minute } } } specialDays { list { date { year month day } isClosed comment } } }
distanceMeters
}
}

# Search by coordinates
query {
getShippingMethodLocations(shippingMethodId: 42, deliveryGroupId: "1", latitude: 51.5033, longitude: -0.1276) {
id
displayName
address { address1 city zipCode country { name } }
distanceMeters
}
}

# Default to the selection's current shipping address
query {
getShippingMethodLocations(shippingMethodId: 42, deliveryGroupId: "1") {
id
displayName
address { address1 city zipCode country { name } }
distanceMeters
}
}

Omitting both address and coordinates defaults to the selection's current shipping address. Providing both is an error.

ShippingETD

Estimated time of delivery. Any combination of sub-fields can coexist. When custom is present, we recommend displaying it to the customer in place of any label derived from relative or absolute — Centra does not enforce this on the backend.

FieldTypeDescription
relativeShippingETDRelativeRange expressed as min, max, and units. min and max are positive integers (>= 1). min can equal max (exact estimate — render "2 days", not "2–2 days"). units is one of: HOURS, DAYS, BUSINESS_DAYS, WEEKS
absoluteShippingETDAbsoluteDate range with from and to as ISO 8601 datetimes with timezone offset (e.g. "2026-02-25T08:00:00-05:00")
customStringPlain text, max 80 characters (e.g. "Delivered by Christmas")

ShippingLabel

Visual indicators attached to a shipping option — sustainability badges, signature-required notices, and similar.

FieldTypeDescription
typeString!Machine-readable label type. See known values below
displayNameString!Plain text, max 30 characters. Customer-facing label name
descriptionStringPlain text, max 120 characters. null when not supplied
iconUrlStringHTTPS URL to a square SVG image (1:1 aspect ratio). null when not supplied

ShippingLabel type values

The following values are currently defined. New values may be added over time — always handle unknown values gracefully.

ValueDescription
SUSTAINABILITYIndicates an environmentally friendly shipping option
SIGNATURE_REQUIREDDelivery requires a recipient signature
FASTESTThe fastest available shipping option
CHEAPESTThe cheapest available shipping option
OTHERA provider-specific label type not covered by the values above

ShippingMethodCustomerChoice

Customer-configurable selections attached to a shipping method. Four interaction types are supported: INPUT (text entry), CHECKBOX (toggle), CHOICE (dropdown with sub-options), and TIMESLOT (delivery time window selection).

FieldTypeDescription
idString!Identifier for this choice. Pass this back as id in ShippingMethodCustomerChoiceValueInput when submitting a value
displayNameString!Label shown to the customer
descriptionStringExplanatory text
typeString!INPUT, CHECKBOX, CHOICE, or TIMESLOT
defaultStringDefault value before any submission. For INPUT: shown in the input box, defaults to empty. For CHOICE and TIMESLOT: the option with the matching key is pre-selected, defaults to the first option. For CHECKBOX: "1" means checked, defaults to unchecked
valueStringThe value most recently submitted via setShippingMethodCustomerChoices / setDeliveryGroupShippingMethodCustomerChoices. null until a value has been submitted for this choice
priceMonetaryValueAdditional cost on top of the base shipping price (additive, not a replacement). Display as "+X.XX". null when the choice has no extra cost
optionsShippingMethodCustomerChoiceOptionList!Paginated. Sub-options — required when type is CHOICE or TIMESLOT. Max 10 entries

Type-specific constraints:

  • INPUT — max customer entry: 80 characters.
  • CHECKBOX — no additional constraints.
  • CHOICEoptions is required. Max 10 options.
  • TIMESLOToptions is required. Max 10 options. Each option's displayName carries the pre-formatted time window (e.g. "Mon 25 Feb, 09:00–12:00").

ShippingMethodCustomerChoiceOption

FieldTypeDescription
keyString!Choice identifier
displayNameString!Customer-facing label
descriptionStringExplanatory text
priceMonetaryValueOverrides the parent ShippingMethodCustomerChoice.price when set. Same semantics — additive on top of the base shipping price

Set Shipping Method

setShippingMethod now accepts an optional locationId parameter. When provided, the chosen pickup or drop-off location is attached to the method in the same call. The selected location is then readable on checkout.shippingMethod.selectedLocation.

# Without a location
mutation {
setShippingMethod(id: 12) {
selection {
checkout {
shippingMethod { id name }
}
}
}
}

# With a location
mutation {
setShippingMethod(id: 12, locationId: "loc-7") {
selection {
checkout {
shippingMethod {
id
name
selectedLocation {
id
displayName
address { address1 city zipCode country { name } }
}
}
}
}
}
}

When the checkout has multiple delivery groups, use setDeliveryGroupShippingMethod instead. The locationId parameter works the same way.

# Without a location
mutation {
setDeliveryGroupShippingMethod(deliveryGroupId: "1", shippingMethodId: 12) {
selection {
checkout {
deliveryGroups {
id
shippingMethods { id name selected }
}
}
}
}
}

# With a location
mutation {
setDeliveryGroupShippingMethod(deliveryGroupId: "1", shippingMethodId: 12, locationId: "loc-7") {
selection {
checkout {
deliveryGroups {
id
shippingMethods {
id
name
selected
selectedLocation { id displayName }
}
}
}
}
}
}
warning

Use setShippingMethod only when the selection has no delivery groups, and setDeliveryGroupShippingMethod only when it does. Using the wrong mutation for the selection's structure will result in an error.


Submit Shipping Method Customer Choices

Once a shipping method with customerChoices is selected, submit the customer's picks with setShippingMethodCustomerChoices (no delivery groups) or setDeliveryGroupShippingMethodCustomerChoices (with delivery groups) — the same split as setShippingMethod/setDeliveryGroupShippingMethod.

Each choice is submitted as a ShippingMethodCustomerChoiceValueInput:

FieldTypeDescription
idString!The ShippingMethodCustomerChoice.id being answered. Must belong to the currently selected shipping method's customerChoices
valueString!The submitted value. For INPUT: free text, max 80 characters. For CHOICE: must match one of that choice's options[].key. For CHECKBOX and TIMESLOT: any string is currently accepted

A choice ID that isn't present on the currently selected shipping method, or a value that fails its type's validation, returns a user error. Submissions are all-or-nothing — if any choice in the call fails validation, none of the choices in that call are applied.

# Without delivery groups
mutation {
setShippingMethodCustomerChoices(choices: [{ id: "parcel-size", value: "l" }]) {
selection {
checkout {
shippingMethod {
id
customerChoices { list { id value } }
}
}
}
}
}
# With delivery groups
mutation {
setDeliveryGroupShippingMethodCustomerChoices(
deliveryGroupId: "1"
choices: [{ id: "gift-message", value: "Happy birthday!" }]
) {
selection {
checkout {
deliveryGroups {
id
shippingMethods {
id
customerChoices { list { id value } }
}
}
}
}
}
}
warning

Use setShippingMethodCustomerChoices only when the selection has no delivery groups, and setDeliveryGroupShippingMethodCustomerChoices only when it does — same rule as setShippingMethod/setDeliveryGroupShippingMethod.


External Provider Shipping Custom Data

shippingProviderCustomData is available on Session, ShippingMethod, and ShippingMethodLocation — an array of provider-grouped custom data entries that a shipping provider integration can attach server-side. The frontend does not need to do anything to populate it; Centra stores and exposes it automatically whenever it receives custom data from the provider.

Each entry groups all custom data from a single provider:

FieldTypeDescription
providerString!Identifier of the shipping provider that set these entries
dataShippingProviderCustomDataEntryList!Paginated. Key/value pairs defined by the provider

ShippingProviderCustomDataEntry:

FieldTypeDescription
keyString!Custom data key, defined by the provider
valueString!Custom data value, defined by the provider
query {
session {
shippingProviderCustomData {
list {
provider
data {
list {
key
value
}
}
}
}
}
}

Keys and values are defined by the provider — Centra passes them through without interpretation. Typical contents include:

  • Delivery window tokens — identifiers the provider uses to track a promised delivery slot
  • Widget initialization data — a session token or config blob a third-party shipping widget can use to bootstrap itself on the frontend, without requiring a separate authentication step
  • Delivery promises — human-readable strings such as "Delivered by Tuesday"
  • Session correlation IDs — references the provider backend uses to look up the corresponding session on their side

This makes shippingProviderCustomData a general-purpose side-channel between the shipping provider's backend and your frontend: the provider writes to it, and the frontend reads it back from the session.


Express Checkout

Express checkout flows (e.g. Apple Pay) are fully supported. Centra handles the ESE integration transparently — no additional frontend implementation is required.