Skip to content

Pricing & Costs API

API endpoints for operational costs and pricing tariffs. All endpoints require token_admin authentication.

Costs

MethodPathDescriptionPermission
GET/services/{id}/costsGet cost matrixplans-menu
PUT/services/{id}/costsUpdate cost matrixmanage-service-costs

GET /services/{id}/costs

Returns the full cost matrix with zones, weight ranges, extra weights, and metadata.

Response (200):

json
{
  "locale_id": 1,
  "currency": "MXN",
  "weight_unit_code": "KG",
  "weight_extra_cost": 1,
  "fuel_type": "flat",
  "fuel_percentage": 5,
  "zones": [
    { "label": "Zona - 1", "identifier": 1 },
    { "label": "Zona - 2", "identifier": 2 }
  ],
  "ranges": [
    { "label": "0 - 1", "data": ["120.00", "150.00"] },
    { "label": "1 - 5", "data": ["180.00", "220.00"] }
  ],
  "extra_weights": [
    { "label": "5", "data": ["15.00", "18.00"] }
  ]
}

Data structure:

  • zones: Array of zone objects. Each zone has a label (display name) and identifier (numeric ID).
  • ranges: Array of weight range rows. Each row has a label (e.g., "0 - 5") and a data array with one cost value per zone (same order as zones).
  • extra_weights: Same structure as ranges, but for per-unit extra weight costs. Typically a single row.

PUT /services/{id}/costs

Replaces the entire cost matrix for a service. Atomic operation — deletes existing data and inserts new records.

Request:

json
{
  "locale_id": 1,
  "fuel_type": "flat",
  "fuel_percentage": 5,
  "weight_unit_code": "KG",
  "weight_extra_cost": 1,
  "zones": [
    {
      "identifier": 1,
      "ranges": [
        { "start": 0, "end": 1, "cost": 120.00 },
        { "start": 1, "end": 5, "cost": 180.00 }
      ],
      "extra_cost": 15.00
    },
    {
      "identifier": 2,
      "ranges": [
        { "start": 0, "end": 1, "cost": 150.00 },
        { "start": 1, "end": 5, "cost": 220.00 }
      ],
      "extra_cost": 18.00
    }
  ]
}

Payload fields:

FieldTypeRequiredDescription
locale_idnumberYesLocale ID (determines currency)
fuel_typestringYesflat or dynamic
fuel_percentagenumberYesFuel surcharge percentage (min: 0)
weight_unit_codestringYesKG or LB
weight_extra_costnumberYesExtra weight unit step (min: 1)
zonesarrayYesZone data (see below)

Zone object:

FieldTypeRequiredDescription
identifiernumberYesZone numeric ID
rangesarrayYesWeight range objects
extra_costnumberYesPer-unit extra weight cost

Range object:

FieldTypeRequiredDescription
startnumberYesWeight range start
endnumberYesWeight range end (must be > 0)
costnumberYesCost value (must be > 0)

Max payload size: 10 MB (to support large matrices).


Pricing

MethodPathDescriptionPermission
GET/services/{id}/priceGet pricing matrix (all tariff types)plans-menu
PUT/services/{id}/priceUpdate pricing for one tariff typemanage-service-pricing

GET /services/{id}/price

Returns pricing data for all 4 tariff types in a single response.

Response (200):

json
{
  "locale_id": 1,
  "currency": "MXN",
  "weight_unit_code": "KG",
  "weight_extra_cost": 1,
  "operator": 1,
  "extended_zone": 50,
  "zones": [
    { "label": "Zona - 1", "identifier": 1 },
    { "label": "Zona - 2", "identifier": 2 }
  ],
  "ranges": {
    "basic": [
      { "label": "0 - 1", "data": ["180.00", "220.00"] },
      { "label": "1 - 5", "data": ["250.00", "300.00"] }
    ],
    "pro": [
      { "label": "0 - 1", "data": ["160.00", "200.00"] },
      { "label": "1 - 5", "data": ["230.00", "280.00"] }
    ],
    "enterprise": [...],
    "corporate": [...]
  },
  "extra_weights": {
    "basic": [{ "label": "5", "data": ["22.00", "26.00"] }],
    "pro": [...],
    "enterprise": [...],
    "corporate": [...]
  }
}

Key difference from costs: ranges and extra_weights are objects keyed by tariff type (basic, pro, enterprise, corporate), not flat arrays.

PUT /services/{id}/price

Updates pricing for one tariff type at a time. To update all 4, make 4 sequential calls.

Request:

json
{
  "locale_id": 1,
  "plan_type": "basic",
  "operator": 1,
  "weight_unit_code": "KG",
  "weight_extra_cost": 1,
  "extended_zone": 50,
  "zones": [
    {
      "identifier": 1,
      "ranges": [
        { "start": 0, "end": 1, "cost": 180.00 },
        { "start": 1, "end": 5, "cost": 250.00 }
      ],
      "extra_cost": 22.00
    },
    {
      "identifier": 2,
      "ranges": [
        { "start": 0, "end": 1, "cost": 220.00 },
        { "start": 1, "end": 5, "cost": 300.00 }
      ],
      "extra_cost": 26.00
    }
  ]
}

Payload fields:

FieldTypeRequiredDescription
locale_idnumberYesLocale ID
plan_typestringYesTariff type: basic, pro, enterprise, or corporate (lowercase)
operatornumberYesPricing operator: 1 (Flat) or 2 (Margin)
weight_unit_codestringYesKG or LB
weight_extra_costnumberYesExtra weight unit step (min: 1)
extended_zonenumberYesExtended zone surcharge amount
zonesarrayYesZone data (same structure as costs)

Note: In the zones[].ranges[].cost field, the value represents:

  • For Flat operator (1): the absolute selling price
  • For Margin operator (2): the markup percentage over graduated cost

Max payload size: 10 MB.


Common Error Responses

All errors follow the Boom format:

json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Descriptive error message"
}
StatusWhen
400Validation failed (Joi schema — e.g., missing locale, negative cost)
401Missing or invalid JWT
403Insufficient permissions
404Service not found

Envia Admin