API de cotizaciones de envío

POST /v1/fulfillment/shipping/quotes estima el envío internacional a partir de un destino, peso, dimensiones, atributos de artículos y servicios.

Utilice el atajo de paquete único cuando el fraccionamiento en almacén sea desconocido. Utilice packages[] cuando ya conozca el número de paquetes y las medidas de cada uno.

Este endpoint usa la misma terminología de canal, región, servicio, facturación y dinero que la API de canales de envío.

POSThttps://api.hiobuy.com/v1/fulfillment/shipping/quotes

Las cotizaciones son presupuestos, no precios bloqueados. El pesaje en almacén, la medición de volumen, el reembalaje y la revisión de servicios pueden cambiar el importe final. Una cotización COMPLETE sigue sin ser un bloqueo de precio.

Alias de compatibilidad: POST /v1/fulfillment/shipments/freight/estimate (mismo comportamiento). Prefiera /v1/fulfillment/shipping/quotes.

Dinero y unidades {#units}

  • Todos los valores monetarios amount son enteros en fen de CNY. 5000 significa ¥50.00.
  • El monetary_unit de primer nivel es siempre CNY_minor.
  • Los objetos monetarios usan { "amount": 5000, "currency": "CNY" }.
  • El peso de la solicitud es siempre KG. Las dimensiones de paquete son siempre CM.
  • Identifique canales y servicios por code estable, no por name.

Encabezados de solicitud {#request}

POST /v1/fulfillment/shipping/quotes
Authorization: Bearer hio_live_xxx
Content-Type: application/json
Language: en

El idioma de visualización es únicamente el encabezado Language. Valores admitidos: en (predeterminado), en-US, zh, zh-CN, zh-TW, cn, hk. No coloque language en el cuerpo JSON ni en la cadena de consulta.

Dos formatos de solicitud {#request-formats}

No combine los campos del atajo de paquete único (weight_kg, length_cm, width_cm, height_cm) con packages[]. La API rechaza una solicitud mixta con 400 VALIDATION_ERROR.

Formato A — atajo de paquete único {#format-a}

Utilice este formato cuando conozca el destino y el peso total estimado, pero no cómo el almacén fraccionará las cajas.

Solicitud mínima:

{
  "destination": {
    "country_code": "KR"
  },
  "weight_kg": 2.05
}

Paquete único con dimensiones:

{
  "destination": {
    "country_code": "KR",
    "postal_code": "04524"
  },
  "weight_kg": 2.05,
  "length_cm": 30,
  "width_cm": 20,
  "height_cm": 10,
  "attributes": []
}
  • weight_kg es el peso estimado del envío en KG.
  • length_cm, width_cm y height_cm están en CM. Proporcione los tres u omita los tres.
  • Prefiera este formato cuando el fraccionamiento final en almacén sea desconocido. Dimensiones faltantes pueden producir PARTIAL o REVIEW_REQUIRED en canales volumétricos.

Formato B — paquetes conocidos {#format-b}

Utilice packages[] cuando ya conozca el número de cajas y los datos de cada caja.

Paquete declarado único:

{
  "destination": {
    "country_code": "KR"
  },
  "packages": [
    {
      "reference": "box-1",
      "weight": {
        "value": 2.05,
        "unit": "KG"
      },
      "dimensions": {
        "length": 30,
        "width": 20,
        "height": 10,
        "unit": "CM"
      }
    }
  ]
}

Varios paquetes:

{
  "destination": {
    "country_code": "KR",
    "postal_code": "04524"
  },
  "packages": [
    {
      "reference": "box-1",
      "weight": {
        "value": 1.25,
        "unit": "KG"
      },
      "dimensions": {
        "length": 30,
        "width": 20,
        "height": 10,
        "unit": "CM"
      }
    },
    {
      "reference": "box-2",
      "weight": {
        "value": 0.8,
        "unit": "KG"
      },
      "dimensions": {
        "length": 20,
        "width": 15,
        "height": 8,
        "unit": "CM"
      }
    }
  ]
}

Reglas de packages[] (OpenAPI):

  • 1–200 paquetes.
  • Un elemento es un paquete único explícito. Varios elementos constituyen un envío multi-paquete explícito.
  • reference es opcional, pero debe ser único dentro de la solicitud.
  • packages[].weight es obligatorio. packages[].weight.unit debe ser KG.
  • packages[].dimensions es opcional. Cuando está presente, length, width, height y unit son todos obligatorios. unit debe ser CM.

El Gateway mapea el formato A a un paquete de almacén único. El formato B se valida y se mapea tal como se declaró. El fraccionamiento final y las dimensiones medidas se determinan todavía después del procesamiento en almacén.

Campos de solicitud compartidos {#shared-fields}

Ambos formatos pueden incluir lo siguiente.

destination

CampoObligatorioDescripción
country_codeSíISO 3166-1 alpha-2, dos letras
subdivision_codeNoPor ejemplo US-CA. El prefijo de país debe coincidir con country_code.
regionNoNombre de visualización de la subdivisión. Un subdivision_code válido tiene prioridad.
postal_codeNoCadena. Conserve los ceros iniciales.

declared_value

{
  "amount": 5000,
  "currency": "CNY"
}

Valor declarado a nivel de envío en fen de CNY enteros. Omita el campo cuando sea desconocido. No envíe 0 para significar desconocido.

attributes

Array de códigos de atributos de artículo estables de GET /v1/fulfillment/shipments/item-attributes. Cadenas únicas, máximo 100.

Las cotizaciones se limitan primero a los canales aplicables a destination.country_code; se omiten los canales de otros países. Cada canal restante evalúa por separado los atributos declarados. Un atributo no admitido produce UNAVAILABLE con ATTRIBUTE_NOT_SUPPORTED, mientras que otros canales aplicables aún pueden devolver cotizaciones.

services

{
  "services": {
    "channel": [
      {
        "code": "LINE_INSURANCE",
        "quantity": 1
      }
    ],
    "outbound": [
      {
        "code": "VACUUM_PACKING",
        "quantity": 1
      }
    ],
    "inbound": [
      {
        "code": "PHOTO",
        "quantity": 3
      }
    ]
  }
}
GrupoSignificado
channelServicios de valor añadido del canal. Los códigos provienen de canales value_added_services[].code.
outboundProcesamiento de salida en almacén
inboundProcesamiento de entrada en almacén

Cada elemento exige code y quantity. OpenAPI: quantity es un entero de 1 a 999. Los códigos deben ser únicos dentro de cada grupo.

channel_codes

Códigos de canal estables que restringen el conjunto de cotizaciones. Omita para cotizar todos los canales candidatos. No envíe un array vacío. Un código desconocido o inaccesible devuelve 400 INVALID_SHIPPING_CHANNEL para toda la solicitud.

Ejemplo de solicitud completa {#complete-request}

Formato A con destino, dimensiones, valor declarado, atributos, servicios y un filtro de canal:

{
  "destination": {
    "country_code": "US",
    "subdivision_code": "US-CA",
    "region": "California",
    "postal_code": "90001"
  },
  "weight_kg": 2.05,
  "length_cm": 30,
  "width_cm": 20,
  "height_cm": 10,
  "declared_value": {
    "amount": 5000,
    "currency": "CNY"
  },
  "attributes": [
    "GENERAL_CARGO"
  ],
  "services": {
    "channel": [
      {
        "code": "LINE_INSURANCE",
        "quantity": 1
      }
    ],
    "outbound": [
      {
        "code": "VACUUM_PACKING",
        "quantity": 1
      }
    ],
    "inbound": [
      {
        "code": "PHOTO",
        "quantity": 3
      }
    ]
  },
  "channel_codes": [
    "US-SEA"
  ]
}

Respuesta {#response}

{
  "success": true,
  "estimate_type": "DECLARED",
  "completeness": {
    "level": "HIGH",
    "destination": "COMPLETE",
    "package_dimensions": "COMPLETE",
    "package_split": "DECLARED",
    "declared_value": "PROVIDED",
    "attributes": "DECLARED",
    "services": "REQUESTED_ONLY"
  },
  "warnings": [
    {
      "code": "WAREHOUSE_REVIEW_REQUIRED",
      "message": "Final charges require warehouse measurement, packing and service review.",
      "affects": [
        "FINAL_CHARGES"
      ]
    }
  ],
  "quotes": [
    {
      "channel": {
        "code": "US-SEA",
        "name": "US Ocean",
        "description": "General cargo line",
        "tags": [
          "GREAT_VALUE"
        ],
        "capabilities": {
          "delivery_methods": [
            "DOOR_DELIVERY",
            "PICKUP"
          ]
        }
      },
      "available": true,
      "quote_status": "COMPLETE",
      "unavailable_reason": null,
      "attribute_evaluation": {
        "status": "SUPPORTED",
        "declared_attributes": [
          {
            "code": "GENERAL",
            "name": "General cargo"
          }
        ],
        "accepted_attributes": [
          {
            "code": "GENERAL",
            "name": "General cargo"
          }
        ],
        "unsupported_attributes": []
      },
      "matched_region": {
        "code": "US-WEST",
        "name": "US West",
        "match_type": "COUNTRY_REGION"
      },
      "packages": [
        {
          "reference": "box-1",
          "weight": {
            "value": 2.05,
            "unit": "KG"
          },
          "dimensions": {
            "length": 30,
            "width": 20,
            "height": 10,
            "unit": "CM"
          },
          "weights": {
            "actual": {
              "value": 2.05,
              "unit": "KG"
            },
            "volumetric": {
              "value": 1,
              "unit": "KG"
            },
            "chargeable": {
              "value": 2.5,
              "unit": "KG"
            }
          }
        }
      ],
      "weights": {
        "actual": {
          "value": 2.05,
          "unit": "KG"
        },
        "volumetric": {
          "value": 1,
          "unit": "KG"
        },
        "chargeable": {
          "value": 2.5,
          "unit": "KG"
        }
      },
      "billing_quantity": {
        "value": 2.5,
        "unit": "KG"
      },
      "pricing_selector": {
        "type": "WEIGHT",
        "value": 2.5,
        "unit": "KG",
        "scope": "SHIPMENT"
      },
      "transit_time": {
        "text": "15-18 business days",
        "min_business_days": 15,
        "max_business_days": 18
      },
      "charges": {
        "base_freight": {
          "amount": 10000,
          "currency": "CNY"
        },
        "channel_services": {
          "amount": 550,
          "currency": "CNY",
          "known_amount": 550,
          "calculation_status": "CALCULATED",
          "items": []
        },
        "channel_rules": {
          "amount": 0,
          "currency": "CNY",
          "known_amount": 0,
          "calculation_status": "CALCULATED",
          "items": [],
          "aggregation": "SUM_ALL",
          "cap": null
        },
        "outbound_services": {
          "amount": 800,
          "currency": "CNY",
          "known_amount": 800,
          "calculation_status": "CALCULATED",
          "items": []
        },
        "inbound_services": {
          "amount": 300,
          "currency": "CNY",
          "known_amount": 300,
          "calculation_status": "CALCULATED",
          "items": []
        },
        "adjustments": {
          "amount": 0,
          "currency": "CNY",
          "known_amount": 0,
          "calculation_status": "CALCULATED",
          "items": []
        }
      },
      "display_charges": {
        "addition": {
          "amount": 0,
          "currency": "CNY",
          "included_in_total": false
        },
        "floor": {
          "amount": 0,
          "currency": "CNY",
          "included_in_total": false
        }
      },
      "total": {
        "amount": 11650,
        "currency": "CNY"
      },
      "known_total": {
        "amount": 11650,
        "currency": "CNY"
      },
      "warnings": [],
      "service_adjustment_possible": true
    }
  ],
  "monetary_unit": "CNY_minor",
  "generated_at": "2026-09-07T08:00:00Z",
  "request_id": "req_xxx",
  "disclaimer": "Estimated charges based on declared data."
}

Campos de primer nivel

CampoDescripción
successtrue en una estimación correcta, incluso cuando algunas cotizaciones son UNAVAILABLE.
estimate_typeDECLARED — basado en datos declarados, no en medición de almacén.
completenessQué tan completa es la entrada. No es una garantía de entregabilidad.
warningsAdvertencias a nivel de envío.
quotesResultados por canal: completos primero, luego parciales/revisión, luego no disponibles.
monetary_unitSiempre CNY_minor.
generated_atMarca de tiempo de la respuesta.
request_idCorrelacione con x-request-id.
disclaimerDescargo de responsabilidad legible de la estimación.

completeness

CampoSignificado
levelCobertura global de la entrada, por ejemplo HIGH.
destinationQué tan completo está el destino (COMPLETE cuando el país está presente).
package_dimensionsSi se proporcionaron longitud/anchura/altura.
package_splitDECLARED cuando envió packages[]; el atajo supone un paquete único.
declared_valuePROVIDED u omitido/desconocido.
attributesSi se declararon atributos de artículo.
servicesREQUESTED_ONLY cuando envió servicios seleccionados; el almacén aún puede añadir más.

Estado de la cotización {#quote-status}

No decida solo a partir de available. Lea siempre quote_status.

quote_statusavailabletotalSignificado
COMPLETEtrueObjeto monetarioPresupuesto completo que puede mostrar. Sigue sin estar bloqueado.
PARTIALtruegeneralmente nullFaltan entradas. Lea las advertencias y añada dimensiones, código postal o valor declarado.
REVIEW_REQUIREDtruegeneralmente nullSe requiere medición de almacén o revisión humana.
UNAVAILABLEfalsenullEste canal no puede cotizar. La solicitud HTTP igualmente se completó.
  • total es el presupuesto completo cuando se conoce.
  • known_total es la suma de los cargos que se pueden calcular ahora.
  • Cuando total es null, no trate known_total como una cotización completa.
  • unavailable_reason.code es para el manejo programático.
  • unavailable_reason.message es solo para visualización.

UNAVAILABLE en una cotización no es un error HTTP.

Objeto de cotización {#quotes}

CampoDescripción
channel{ code, name, description, tags, capabilities } — misma identidad que el catálogo de canales.
channel.capabilities.delivery_methodsArray opcional y compatible de códigos estables de entrega: DOOR_DELIVERY, PICKUP, POST_OFFICE_PICKUP. Puede aparecer con cualquier estado; los clientes existentes pueden ignorarlo.
availableSi este canal produjo una estimación usable. Combínelo con quote_status.
quote_statusCOMPLETE · PARTIAL · REVIEW_REQUIRED · UNAVAILABLE.
unavailable_reason{ code, message } o null.
attribute_evaluationResultado opcional por canal: SUPPORTED, UNSUPPORTED o NOT_DECLARED, con listas de atributos declarados, aceptados y no admitidos.
matched_region{ code, name, match_type } o null.
packagesPaquetes declarados o mapeados más pesos por paquete.
weightsactual / volumetric / chargeable a nivel de envío, en KG.
billing_quantityCantidad que el canal factura realmente, con unidad KG, M3 o KG_PER_M3.
pricing_selectorCómo esa cantidad alcanzó una banda de tarifa (type, value, unit, scope).
transit_timeTiempo de tránsito de referencia.
chargesGrupos de cargos. Véase más abajo.
display_chargesFilas opcionales solo para UI. Si included_in_total es false, no las sume a total.
total / known_totalPresupuesto completo vs cargos actualmente conocidos.
warningsAdvertencias a nivel de canal.
service_adjustment_possibletrue si el procesamiento en almacén aún puede cambiar servicios y cargos.

Pesos y cantidad facturable {#weights}

  • actual — peso declarado o medido.
  • volumetric — peso volumétrico.
  • chargeable — peso usado para el flete.
  • billing_quantity — cantidad que el canal factura (puede ser peso, volumen o densidad).
  • pricing_selector — cómo esa cantidad seleccionó una fila tarifaria. Los tipos coinciden con el catálogo WEIGHT / VOLUME / DENSITY.
  • Los canales multi-paquete pueden redondear por caja y luego sumar. Cuando pricing_selector.scope es PER_PACKAGE, lea cada packages[].pricing_selector.

Cargos {#charges}

GrupoSignificado
base_freightFlete internacional base
channel_servicesServicios de canal obligatorios y seleccionados por el desarrollador
channel_rulesSobredimensión, sobrepeso, valor declarado y otras reglas de ruta
outbound_servicesServicios de valor añadido durante la preparación y salida del envío
inbound_servicesServicios de valor añadido durante la recepción y entrada en almacén
adjustmentsAjustes

Servicios de entrada y salida

inbound_services y outbound_services corresponden a etapas distintas de los servicios de valor añadido del almacén. Los servicios de entrada se realizan durante la recepción, como fotos del paquete, grabación de vídeo o inspección. Los servicios de salida se realizan al preparar el envío, como refuerzo, envasado al vacío o embalaje con marco/caja de madera. Ambas etapas pueden aplicarse y cobrarse legítimamente al mismo paquete o envío.

Los importes de la cotización son solo estimaciones; solicitar una cotización no crea un cargo de servicio adicional. Los cargos definitivos dependen de los servicios realmente realizados y de su precio y liquidación finales. Use ambos grupos para estimar el coste total y concilie cada estimación con su cargo real correspondiente. No vuelva a sumar la estimación de un servicio individual sobre su cargo final.

Ejemplo en unidades menores de CNY: fotos del paquete 50 fen (¥0,50), inspección 100 fen (¥1,00), envasado al vacío 150 fen (¥1,50) y refuerzo del paquete 200 fen (¥2,00). Los cuatro pueden coexistir porque son servicios distintos realizados en etapas diferentes.

Cada grupo suele incluir:

CampoSignificado
amountTotal del grupo en fen, o null si es desconocido
currencyCNY
known_amountSuma de los elementos que se pueden calcular ahora
calculation_statusPor ejemplo CALCULATED
itemsLíneas de detalle

channel_rules también puede incluir aggregation y cap. Use el subtotal del grupo: no lo sustituya sumando las líneas de reglas en bruto.

SUM_ALL suma todos los cargos coincidentes. HIGHEST_ONLY selecciona solo el mayor tras ordenar por importe descendente; las reglas con el mismo precio son equivalentes. cap=null significa sin límite. reason es solo para mostrar. Para lógica use condition_match, matched_conditions, rule_type, charge_mode, charge_value, outcome y missing_fields. Las reglas PENDING_INPUT, REVIEW_REQUIRED y otras no calculadas se excluyen del total conocido. amount=null no es cero y un charge_value configurado no es un cargo real.

Ítems de cargo

CampoSignificado
codeCódigo estable de cargo o servicio
nameNombre de visualización localizado
categoryCategoría de cargo
sourceMANDATORY · DEVELOPER_SELECTED · RULE_ENGINE
pricing_basisCómo se tarifó la línea
quantityCantidad facturable de la línea
unit_pricePrecio unitario en fen cuando se conoce
amountTotal de la línea. null significa desconocido, no cero.
estimatedSi la línea sigue siendo una estimación
calculation_statusEstado del cálculo
affected_by_packagesSi el número/tamaño de paquetes puede cambiar esta línea
included_in_totalSi es false, no la sume de nuevo a total

display_charges puede existir solo para la presentación frontend.

Motivos de no disponibilidad {#unavailable-reasons}

Valores comunes de unavailable_reason.code:

OUTSIDE_PRICING_RANGE
POSTAL_CODE_REQUIRED
POSTAL_CODE_NOT_SUPPORTED
DESTINATION_NOT_SUPPORTED
ATTRIBUTE_NOT_SUPPORTED
SERVICE_NOT_SUPPORTED
DIMENSIONS_REQUIRED
DECLARED_VALUE_REQUIRED
MULTI_PACKAGE_NOT_SUPPORTED
PRICING_MODE_UNSUPPORTED
CHANNEL_RULE_REJECTED
CHANNEL_PRICING_ERROR

Los canales no disponibles permanecen en quotes[] para que pueda explicar por qué se rechazaron.

Terminología del catálogo {#catalog-terminology}

Canales de envíoEsta APISignificado
items[].code/name/description/tagsquotes[].channel.*El mismo canal
regions[].code/name/match_typequotes[].matched_region.*Región seleccionada por la cotización
value_added_services[].codeservices.channel[].code y code del cargoCódigo de servicio estable
billing.quantity_unitbilling_quantity.unit / pricing_selector.unitUnidad de facturación
rule_summary.aggregationcharges.channel_rules.aggregationAgregación de reglas
rule_summary.capcharges.channel_rules.capLímite tras la agregación; null significa sin límite

Atributos de artículo {#item-attributes}

GET /v1/fulfillment/shipments/item-attributes devuelve los códigos attributes[] válidos para las cotizaciones.

Errores {#errors}

HTTPerror.codeCuándo
400VALIDATION_ERROREstructura inválida, formatos de solicitud mixtos, unidades KG/CM, códigos duplicados o channel_codes vacío
400INVALID_SHIPPING_CHANNELUn valor de channel_codes solicitado es desconocido o no visible para la app
401INVALID_API_KEYToken Bearer ausente o inválido
403FULFILLMENT_MODE_NOT_SUPPORTEDLa app usa self fulfillment
403WAREHOUSE_AUTH_INVALIDLa autorización del almacén falta, fue rechazada o expiró
422INVALID_COUNTRY_CODEEl país de destino es inválido
422INVALID_ITEM_ATTRIBUTEUn código de atributo es inválido
502WAREHOUSE_UPSTREAM_ERROREl servicio del almacén falló; reintente con backoff

No hay un código público distinto AUTHENTICATION_ERROR, WAREHOUSE_AUTH_REQUIRED ni WAREHOUSE_SERVICE_UNAVAILABLE. Use 401 INVALID_API_KEY, 403 WAREHOUSE_AUTH_INVALID y 502 WAREHOUSE_UPSTREAM_ERROR.

Un canal que no puede transportar este envío es una cotización UNAVAILABLE, no un fallo HTTP.

Get Support

Need integration help? Contact Developer Support at support@hiobuy.com · Response within 1–2 business days

Email support