Skip to main content

Shipping Method API

Shipping methods in EverShop are produced by shipping providers. A provider is registered at bootstrap (the built-in one has the code core) and attached to one or more shipping zones. When a cart has a shipping address, every provider attached to a matching zone is asked for its methods, and the merged list is what the customer picks from.

That split drives the API surface:

  • Listing available methods is a GraphQL query on the cart — the list depends on the cart's contents and destination, so it cannot be a static REST collection.
  • Selecting a method is the single REST endpoint documented below.
Removed endpoints

GET /api/shippingMethods and GET /api/carts/{cart_id}/shippingMethods no longer exist. Read the available methods with the GraphQL query below, and the currently selected one with Cart.shippingMethodData.

List Available Shipping Methods (GraphQL)

Query Cart.availableShippingMethods against the storefront endpoint POST /graphql. The destination arguments are optional — when omitted the cart's saved shipping address is used.

query AvailableShippingMethods($cartId: String!) {
cart(id: $cartId) {
availableShippingMethods(country: "US", province: "CA", postcode: "90001") {
id
providerCode
code
name
cost {
value
text
}
carrier
serviceCode
delivery {
minBusinessDays
maxBusinessDays
estimatedDate
}
}
}
}

Both providerCode and code are required when the customer commits to a method — keep them together as you carry the selection through your UI.

FieldTypeDescription
idString!Alias of code, kept for backward compatibility
providerCodeString!Code of the provider that produced this method. Send it back as provider_code when selecting
codeString!Provider-opaque method identifier. Send it back as method_code
nameString!Customer-facing method name
costPrice!Quoted cost in the cart's currency
carrierStringCustomer-facing carrier label (e.g. USPS). Usually null for Core-only stores
serviceCodeStringFulfillment metadata used when buying a label. Never display it
deliveryDeliveryWindowEstimated delivery window when the provider supplies one
method_code is opaque

Do not hardcode values like "standard" or "express". The code is whatever the provider chooses to emit — the built-in Core provider returns the core_shipping_method.uuid of the admin-defined method. Always read the code from availableShippingMethods and echo it back verbatim.


Set Shipping Method for Cart

Applies a selected shipping method to a shopping cart. The server re-quotes the method against the cart's current state and stores an enriched snapshot in cart.shipping_method_data.

Request Schema (application/json)
Field NameField TypeRequired
provider_codestringYes
method_codestringYes
POST/api/carts/{cart_id}/shippingMethods
curl
-H "Accept: application/json"
--data-raw "<JSON DATA>"
https://<your domain>/api/carts/{cart_id}/shippingMethods
Sample Of Response
{
"data": {
"method": {
"code": "0f1c8b7a-9d3e-4f2a-a1b6-77d4c2e9b510",
"provider_code": "core"
}
}
}
provider_code is mandatory

Earlier releases defaulted the provider to core when the field was absent. That default is gone: a payload without provider_code is rejected with 400 provider_code is required. Silently defaulting routed non-core selections through Core's validator and surfaced later as a misleading "method no longer available" error.

Path Parameters

ParameterTypeRequiredDescription
cart_idstringYesThe UUID of the cart to apply the shipping method to

Reading Back the Selection

The cart.shipping_method and cart.shipping_method_name columns were dropped, along with their order counterparts. The selection now lives in the shipping_method_data JSONB column, exposed as Cart.shippingMethodData:

query SelectedShippingMethod($cartId: String!) {
cart(id: $cartId) {
shippingMethodData {
providerCode
methodCode
snapshot {
code
name
cost {
value
text
}
carrier
}
fingerprint
quotedAt
}
}
}

The underlying column looks like this:

{
"provider_code": "core",
"method_code": "0f1c8b7a-9d3e-4f2a-a1b6-77d4c2e9b510",
"snapshot": {
"code": "0f1c8b7a-9d3e-4f2a-a1b6-77d4c2e9b510",
"name": "Standard Shipping",
"cost": 5.99,
"carrier": "usps",
"serviceCode": "usps_ground_advantage"
},
"fingerprint": "3d0f9a...",
"quotedAt": "2025-04-04T09:12:44.201Z"
}

fingerprint and quotedAt are cart-only. When the cart's items, address, or totals change, the snapshot is re-quoted against the provider automatically — a method that no longer applies raises the shipping-quote error described below.


Managing Providers, Methods and Rates

Creating the methods that customers see is an admin task and lives on different endpoints:

EndpointPurpose
POST /api/shippingZones/:zone_id/providersAttach a provider to a zone
PATCH /api/shippingZones/:zone_id/providers/:provider_codeEnable/disable or reconfigure an attachment
DELETE /api/shippingZones/:zone_id/providers/:provider_codeDetach a provider from a zone
POST /api/shippingProviders/core/methodsCreate a Core shipping method
POST /api/shippingProviders/core/ratesGive a Core method a per-zone rate

See the Shipping Zone API for the full schemas.


Troubleshooting

Shipping Quote Errors

When the selection cannot be quoted, the endpoint answers 400 with a provider-specific reason in error.message. These are user-facing strings — surface them at checkout rather than a generic failure.

MessageCause
provider_code is requiredThe payload omitted provider_code
Missing provider_code or method_codeOne of the two fields was present but empty
Shipping provider "x" is not registeredNo provider with that code is registered at bootstrap
Shipping address is requiredThe cart has no shipping address, so no zone can be resolved
We do not ship to this addressNo shipping zone matches the cart's destination
Invalid cartNo cart exists with the supplied cart_id

Common Error Codes

Status CodeDescriptionSolution
400Bad RequestA missing field, an unknown cart, or a shipping-quote rejection. Read error.message
401UnauthorizedOnly relevant on the admin provider/method endpoints — check your access token
429Too Many RequestsThe /api/** tier allows 120 requests per minute per IP. Back off using the Retry-After header
500Server ErrorUnexpected failure while saving the cart. Check the server logs