Shopify live checkout rates

Shopify live checkout rates

During checkout, Shopify asks EcartAPI for shipping rates. EcartAPI sends one POST to your quote URL and waits for your rates. Your JSON array becomes the shipping methods the buyer sees. Home delivery (dropOff) and pickup (pickup) are both rows in that same list.

You have 5 seconds. After that the request fails and Shopify receives no rates from you.


Request you receive

POST your quote URL with Content-Type: application/json.

The body is one quote: origin, destination, items, package, currency, and locale. Item prices are in major units. Weight is kilograms.

{
  "origin": {
    "name": null,
    "company": "TechNest",
    "street": "Vasconcelos 1400",
    "city": "San Pedro",
    "state": "NL",
    "country": "MX",
    "postalCode": "66236"
  },
  "destination": {
    "name": "testing test",
    "street": "Casa de los azulejos #234, Casa",
    "city": "San Nicolas",
    "state": "NL",
    "country": "MX",
    "postalCode": "34567"
  },
  "items": [
    {
      "name": "Prueba del checkout",
      "quantity": "1",
      "weight": "0",
      "price": "4000",
      "productId": "10306702442665",
      "variantId": "50504275624105"
    }
  ],
  "package": {
    "weight": "1",
    "weightUnit": "KG",
    "lengthUnit": "CM",
    "dimensions": { "length": "17.1", "width": "17.1", "height": "17.1" }
  },
  "currency": "MXN",
  "locale": "es-MX"
}

Response you return

Answer HTTP 200 with a JSON array. Each element is one shipping method. An empty array is valid and means you have no rates. Do not wrap the array in { "rates": [] } — EcartAPI builds that object for Shopify after mapping.

No field is required. Unknown keys are ignored. If one element has a known field with the wrong type, that element is dropped and the rest are still shown.

type chooses the mapper. Comparison is case-insensitive.

type you sendMapper
pickup, PICKUP, PickupPickup
dropOff, DROPOFF, any other text, or omittedHome delivery

Pickup elements that include pickupPoint are limited to 6 per serviceId. Home-delivery elements are not limited.

Empty string, null, and a missing key are treated the same: that value is skipped and the next priority is used.

Home delivery example

{
  "type": "dropOff",
  "serviceId": "1",
  "service": "FedEx Nacional Económico",
  "serviceDescription": "Door to door",
  "totalPrice": 119.87,
  "currency": "MXN",
  "phoneRequired": false,
  "deliveryDate": {
    "min": { "date": "2026-10-03", "time": "09:00" },
    "max": { "date": "2026-10-04", "time": "18:00" }
  }
}

Pickup example

{
  "type": "pickup",
  "serviceId": "9",
  "service": "Branch delivery",
  "totalPrice": 80,
  "currency": "MXN",
  "phoneRequired": true,
  "deliveryDate": {
    "max": { "date": "2026-10-04", "time": "18:00" }
  },
  "pickupPoint": {
    "pickupPointCode": "SUC-02",
    "reference": "Entrega en Sucursal",
    "address": {
      "address": "Av. Insurgentes",
      "number": "200",
      "locality": "Roma Norte",
      "city": "Ciudad de México",
      "postalCode": "06700"
    }
  }
}

date is YYYY-MM-DD. time is HH:mm. totalPrice is major units (80 or 119.87), not cents — "119.87" as a string is accepted. phoneRequired accepts true, false, "true", and "false".


Shared fields

These three fields use the same rule for home delivery and pickup.

Price → total_price

Your totalPriceShopify total_price
119.87 or "119.87"11987 (two decimals, then ×100)
808000
Missing, null, or not a number0

Currency → currency

Your currencyShopify currency
A non-empty string, such as MXNThat string
Missing, null, or ""null

Phone flag → phone_required

The phone string is ignored. Only the boolean is mapped.

Your phoneRequiredShopify phone_required
true or "true"true — checkout asks for a phone number
false, "false", missing, or nullfalse

Home delivery mapping

Shopify fields produced: service_name, service_code, description, total_price, currency, min_delivery_date, max_delivery_date, phone_required.

Title → service_name

PriorityFieldUsed whenShopify title
1serviceNot emptyThe service text
2serviceDescriptionservice is missing, null, or ""The serviceDescription text
3noneBoth are emptynull

service and serviceDescription can both be present. The title uses service. The second line can still use serviceDescription. If you send only serviceDescription, that text becomes both the title and the second line.

You sendTitle the buyer sees
service: FedEx Nacional Económico, serviceDescription: Door to doorFedEx Nacional Económico
service omitted, serviceDescription: Door to doorDoor to door
Both omittedNo title

Second line → description

There is no fallback chain. The second line is only serviceDescription.

Your serviceDescriptionShopify description
Non-empty textThat text
Missing, null, or ""null

If you also send deliveryDate.min.date and deliveryDate.max.date, Shopify shows its own delivery promise from those dates — for example "1 a 2 días hábiles" — instead of relying on this text.

Code → service_code

This value is not shown to the buyer. Shopify sends it back when the buyer selects the method.

PriorityYour serviceIdShopify service_code
1Any value other than missing, null, "", or 0. Numbers are turned into textThat text — 1 becomes "1"
2Missing, null, "", or 0The text undefined

Always send serviceId. Without it, the selected method comes back as undefined.

Delivery window

Shopify fieldSourceWritten whenFormat
min_delivery_datedeliveryDate.minmin.date is not emptyYYYY-MM-DD HH:mm:00 when time is present. YYYY-MM-DD when time is missing
max_delivery_datedeliveryDate.maxmax.date is not emptySame format

If deliveryDate is missing, or a bound has no date, that Shopify field is omitted. min and max are independent — you can send only one.

You sendShopify receives
min.date 2026-10-03, min.time 09:00min_delivery_date: 2026-10-03 09:00:00
max.date 2026-10-04, max.time 18:00max_delivery_date: 2026-10-04 18:00:00
max.date 2026-10-04, no timemax_delivery_date: 2026-10-04
No deliveryDateNeither date field

Pickup mapping

Shopify fields produced: service_name, service_code, description, total_price, currency, max_delivery_date, phone_required.

min_delivery_date is never set for pickup, even if you send deliveryDate.min.

Title → service_name

PriorityFieldUsed whenShopify title
1pickupPoint.referenceNot emptyThe branch name
2servicereference is missing, null, or ""The service text
3serviceDescriptionThe two fields above are emptyThe serviceDescription text
4noneAll three are emptynull
You sendTitle the buyer sees
reference: Entrega en Sucursal, service: Branch deliveryEntrega en Sucursal
No reference, service: Branch deliveryBranch delivery
No reference, no service, serviceDescription: Collect at storeCollect at store
None of the threeNo title

Second line → description

The second line is the address only. serviceDescription is not used here. Opening hours in availability are not shown here.

Pieces are skipped when they are missing, null, or "". The remaining pieces stay in this order, joined with , :

OrderPieceSourceRule
1Streetaddress and numberJoined with a space. If one is empty, only the other is kept
2Placelocality, otherwise citylocality wins when not empty. city is used only when locality is missing, null, or ""
3Postal codepostalCodeAppended last

If every piece is empty, description is null.

Address you sendShopify description
Street Av. Insurgentes, number 200, locality Roma Norte, city Ciudad de México, postal code 06700Av. Insurgentes 200, Roma Norte, 06700
Same, but no localityAv. Insurgentes 200, Ciudad de México, 06700
Street onlyAv. Insurgentes
Postal code only06700
No address objectnull

These address keys are accepted and ignored: street, country, province, state, latitude, longitude.

Code → service_code

PriorityYour pickupPoint.pickupPointCodeShopify service_code
1Not empty. Numbers are turned into textThat text — SUC-02 stays SUC-02
2Missing, null, or ""null

This is not the same rule as home delivery. A pickup without pickupPointCode becomes null, not undefined. serviceId is not the pickup code — it only caps pickup rows at 6 per service.

Delivery window → max_delivery_date

You sendShopify receives
deliveryDate.max.date and max.timemax_delivery_date: YYYY-MM-DD HH:mm:00
max.date without timemax_delivery_date: YYYY-MM-DD
No max.datemax_delivery_date is omitted
deliveryDate.min onlyNothing — minimum is ignored for pickup

Same Shopify field, different source

Shopify fieldHome delivery sourcePickup source
service_nameservice, then serviceDescriptionpickupPoint.reference, then service, then serviceDescription
descriptionserviceDescription onlyAddress: street + number, locality or city, postalCode
service_codeserviceId, or the text undefinedpickupPoint.pickupPointCode, or null
min_delivery_datedeliveryDate.minNot set
max_delivery_datedeliveryDate.maxdeliveryDate.max
total_pricetotalPrice in cents, or 0Same
currencycurrency, or nullSame
phone_requiredphoneRequired, or falseSame

Fields that never reach checkout

You may sendWhy it does not appear
carrierName of the carrier company. Not copied
phonePhone string. Use phoneRequired instead
localeLanguage of your own text. Text is copied as you sent it
landedCostTotalNot copied
pickupPoint.availabilityOpening hours. Not copied into the pickup description
Address street, country, province, state, latitude, longitudeNot copied into the pickup description

Timeout and error handling

Your responseResult in Shopify
HTTP 200 + JSON array, within 5 sYour rates, after the mapping above
HTTP 200 + empty arrayNo rates from you
HTTP 400No rates. Shopify receives No rates available
HTTP 200 whose body is an object, string, or anything other than an arraySame error, No rates available
Any other HTTP status, timeout, or network failureShopify receives { "rates": [] }
One array element has a known field with the wrong typeThat element is omitted. Valid elements are returned

Answer in under 5 seconds. A slow 200 is a failure, not a late success.


Did this page help you?