Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/plantasur-dev/ship-quote/llms.txt

Use this file to discover all available pages before exploring further.

This is the primary rate comparison endpoint. Submit a destination postal code, a country code, and a list of shipment items and Ship Quote will auto-resolve the postal code to its corresponding province, determine whether the shipment is national or international, fan out requests to every active agency that covers that scope in parallel, and return a normalized per-agency result array. Both static (database-backed) and API-integrated agencies are queried simultaneously, so you always receive the most complete picture in a single call.
The DEFAULT_COUNTRY environment variable controls which country code is treated as national. When the server is configured for Spain (DEFAULT_COUNTRY=ES), sending countryCode: "ES" triggers national agency matching; any other ISO-2 code triggers international agency matching.

Endpoint

POST /api/v1/rates/compareByPostalCode

Middleware chain

Requests pass through three middleware layers before reaching the controller:
OrderMiddlewareWhat it checks
1schemaValidationRequest body must be present and non-empty
2rateDestinationValidationdestinationPostalCode and countryCode must be non-null strings; when the country matches DEFAULT_COUNTRY, postal code must match the 5-digit format (\d{5})
3rateItemsValidationitems must be a non-empty array; each item must have a positive weight, positive large/width/height, and a valid typeServices value

Request body

destinationPostalCode
string
required
The destination postal code. Must be a 5-digit string when shipping within the default country (e.g. "18001" for Granada, Spain). For international destinations the format constraint is relaxed.
countryCode
string
required
ISO 3166-1 alpha-2 country code for the destination (e.g. "ES", "FR", "DE"). The value determines whether national or international agencies are queried.
items
array
required
List of shipment items to price. Must contain at least one entry.

Response body

The response is a flat JSON array. Each element represents one active agency and its computed services.
[]
array
Array of per-agency result objects.

Examples

curl -X POST http://localhost:3000/api/v1/rates/compareByPostalCode \
  -H "Content-Type: application/json" \
  -d '{
    "destinationPostalCode": "18001",
    "countryCode": "ES",
    "items": [
      {
        "typeServices": "pallet",
        "weight": 215,
        "large": 80,
        "width": 90,
        "height": 80
      }
    ]
  }'

HTTP status codes

CodeMeaning
200 OKRate comparison completed. The array always contains one entry per active agency in scope, even when available is false.
400 Bad RequestValidation failed. The response body contains a message field describing which field failed (e.g. "Postal Code invalid", "items cannot be empty", "Item 1: weight must be a number > 0").
404 Not FoundThe postal code could not be resolved to a known province for the default country, or no rate comparison result was produced.
500 Internal Server ErrorAn unhandled server-side error occurred.
A 200 response does not guarantee all agencies returned a price. Always check available on each result entry and inspect incidents for service-level warnings before presenting rates to end users.

How scope detection works

The controller calls getProvinceByPostalCode(destinationPostalCode) to resolve the province from an in-memory map loaded at server startup. If the country code matches DEFAULT_COUNTRY (default: ES) and no province is found, a 404 is returned immediately. For international shipments the province defaults to an empty string and international-scoped agencies are queried instead. The rates service then calls getScope(countryCode), which returns "national" when countryCode === DEFAULT_COUNTRY and "international" otherwise. Only agencies whose rules.coverage array includes the detected scope are included in the comparison.
If you already know the province code (e.g. from a prior call to GET /api/v1/locations/provinces), use compareByProvinceCode to skip the postal-code resolution step entirely and reduce latency.

Build docs developers (and LLMs) love