Saltar al contenido
SendIt está en desarrollo y todavía no opera comercialmente · SendIt is in development and not yet commercially available.
SendItdocs
English
Esc
navigateopen⌘Jpreview
En esta página

Rates

Compare rates from every carrier in a single call; the quoted total is exactly what you pay.

Rates come to you: when you create a shipment, the response already includes rates[] with quotes from every carrier enabled for that route. There is no separate quoting call to manage.

If you already know which carrier and service you want, or just want the cheapest, add the purchase object when you create the shipment. See One-call buy.

The rate object

{
  "id": "DHL_standard_a1b2c3",
  "carrierCode": "DHL",
  "serviceCode": "EXPRESS_WORLDWIDE",
  "carrierName": "DHL Express",
  "serviceName": "DHL Express Nacional",
  "serviceLevel": "standard",
  "totalPrice": 326.82,
  "currency": "MXN",
  "isInsured": false,
  "estimatedDays": { "min": 1, "max": 2 },
  "expiresAt": "2026-07-18T14:30:00.000Z",
  "breakdown": {
    "baseRate": 264.50,
    "fuelSurcharge": 17.24,
    "insuranceCost": 0.00,
    "subtotal": 281.74,
    "ivaRate": 0.16,
    "ivaAmount": 45.08,
    "total": 326.82
  }
}
Field Description
id The rateId — pass it to the label purchase
serviceCode The carrier-native exact product code
serviceLevel Normalized across carriers (express, standard, economy, …)
totalPrice The total to pay, IVA included — matches breakdown.total
isInsured true if the rate includes insurance (you created the shipment with requestInsurance)
estimatedDays Estimated business-day delivery range
expiresAt Rate validity (24 hours)
breakdown Transparent split: base rate, surcharges, insurance, subtotal, and IVA as a separate line

If you created the shipment with requestInsurance: true and a declaredValue, rates come back with the premium in breakdown.insuranceCost and isInsured: true. Buying an insured rate creates a real policy you can claim against. See Insurance & claims.

A rate’s lifecycle

POST /v1/shipments
  → creates the shipment (DRAFT)
  → quotes every enabled carrier
  → returns the shipment + rates[] (valid: 24 h)

GET /v1/shipments/:id/rates        ← fetch or refresh any time

POST /v1/shipments/:id/label { rateId }   ← buy at the quoted price

If carriers are slow

Quoting has an 8-second budget. If a carrier lags, the shipment returns immediately with rates on the way:

{
  "success": true,
  "data": {
    "id": "clxq1w2e3r4t5y6u7i8o9p0a",
    "status": "DRAFT",
    "rates": [],
    "ratesStatus": "pending",
    "ratesExpiresAt": null,
    "ratesPollUrl": "/v1/shipments/clxq1w2e3r4t5y6u7i8o9p0a/rates"
  }
}

Poll ratesPollUrl (e.g. every 2 seconds) until ratesStatus is "ready".

Fetch or refresh rates

GET /v1/shipments/:id/rates                  ← returns the current rates
GET /v1/shipments/:id/rates?refresh=true     ← re-quotes the carriers

Without ?refresh=true you get the cached rates while their 24-hour validity lasts. With ?refresh=true everything is re-quoted and the validity resets.

When a rate expires

Buying with an expired rateId returns 410 RATES_EXPIRED:

{
  "success": false,
  "error": {
    "code": "RATES_EXPIRED",
    "message": "Shipping rates have expired. Please refresh rates and select again.",
    "details": {
      "shipmentId": "clxq1w2e3r4t5y6u7i8o9p0a",
      "hint": "GET /v1/shipments/clxq1w2e3r4t5y6u7i8o9p0a/rates"
    }
  }
}

Refresh, pick a new rateId, and buy again. You’ll also see this error if you use a rateId belonging to a different shipment.

Quote without creating a shipment

For checkout widgets or pre-purchase estimates, use the standalone endpoint:

Body parameters

PropType
originobject

The origin. It needs at least { postalCode }.

Typeobject
destinationobject

The destination. It needs at least { postalCode }.

Typeobject
parcelobject

The package: length, width, height (cm) and weight (kg).

Typeobject
curl -X POST https://api.sendit.mx/v1/rates \
  -H "X-API-Key: sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "origin": { "postalCode": "03940" },
    "destination": { "postalCode": "45050" },
    "parcel": { "weight": 1.5, "length": 20, "width": 15, "height": 10 }
  }'

The response returns rates[] (the same rate object above) and its validity:

{
  "success": true,
  "data": {
    "rates": [
      { "id": "DHL_standard_a1b2c3", "carrierCode": "DHL", "serviceCode": "EXPRESS_WORLDWIDE", "serviceLevel": "standard", "totalPrice": 88.40, "currency": "MXN", "isInsured": false }
    ],
    "expiresAt": "2026-07-18T14:30:00.000Z"
  }
}

These rates are display-only: they can’t be used to buy a label. To buy, create the shipment first. You can limit to one carrier (POST /v1/rates/carrier/DHL) or sort with ?sortBy=price or ?sortBy=speed.

Sort rates

const byPrice = [...rates].sort((a, b) => a.totalPrice - b.totalPrice);
const bySpeed = [...rates].sort(
  (a, b) => a.estimatedDays.min - b.estimatedDays.min || a.totalPrice - b.totalPrice
);

¿Te ha resultado útil esta página?