API des devis d’expédition

POST /v1/fulfillment/shipping/quotes estime l’expédition internationale à partir d’une destination, du poids, des dimensions, des attributs d’articles et des services.

Utilisez le raccourci colis unique lorsque le fractionnement en entrepôt est inconnu. Utilisez packages[] lorsque le nombre de colis et les mesures par colis sont déjà connus.

Cet endpoint utilise la même terminologie de canal, région, service, facturation et argent que l’API des canaux d’expédition.

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

Les devis sont des budgets, pas des prix verrouillés. Le pesage en entrepôt, la mesure du volume, le reconditionnement et la revue des services peuvent modifier le montant final. Un devis COMPLETE n’est toujours pas un verrouillage de prix.

Alias de compatibilité : POST /v1/fulfillment/shipments/freight/estimate (même comportement). Préférez /v1/fulfillment/shipping/quotes.

Argent et unités {#units}

  • Tous les amount monétaires sont des fen CNY entiers. 5000 signifie ¥50.00.
  • Le monetary_unit de premier niveau est toujours CNY_minor.
  • Les objets monétaires utilisent { "amount": 5000, "currency": "CNY" }.
  • Le poids de la requête est toujours KG. Les dimensions de colis sont toujours CM.
  • Identifiez les canaux et services par code stable, pas par name.

En-têtes de requête {#request}

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

La langue d’affichage est uniquement l’en-tête Language. Valeurs prises en charge : en (défaut), en-US, zh, zh-CN, zh-TW, cn, hk. Ne placez pas language dans le corps JSON ni dans la chaîne de requête.

Deux formats de requête {#request-formats}

Ne combinez pas les champs du raccourci colis unique (weight_kg, length_cm, width_cm, height_cm) avec packages[]. L’API rejette une requête mixte avec 400 VALIDATION_ERROR.

Format A — raccourci colis unique {#format-a}

Utilisez ce format lorsque vous connaissez la destination et le poids total estimé, mais pas comment l’entrepôt fractionnera les cartons.

Requête minimale :

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

Colis unique avec dimensions :

{
  "destination": {
    "country_code": "KR",
    "postal_code": "04524"
  },
  "weight_kg": 2.05,
  "length_cm": 30,
  "width_cm": 20,
  "height_cm": 10,
  "attributes": []
}
  • weight_kg est le poids estimé de l’expédition en KG.
  • length_cm, width_cm et height_cm sont en CM. Fournissez les trois ou omettez les trois.
  • Préférez ce format lorsque le fractionnement final en entrepôt est inconnu. Des dimensions manquantes peuvent produire PARTIAL ou REVIEW_REQUIRED pour les canaux volumétriques.

Format B — colis connus {#format-b}

Utilisez packages[] lorsque vous connaissez déjà le nombre de cartons et les données de chaque carton.

Colis déclaré unique :

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

Plusieurs colis :

{
  "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"
      }
    }
  ]
}

Règles packages[] (OpenAPI) :

  • 1 à 200 colis.
  • Un élément est un colis unique explicite. Plusieurs éléments constituent une expédition multi-colis explicite.
  • reference est optionnel, mais doit être unique dans la requête.
  • packages[].weight est obligatoire. packages[].weight.unit doit être KG.
  • packages[].dimensions est optionnel. Lorsqu’il est présent, length, width, height et unit sont tous obligatoires. unit doit être CM.

La Gateway mappe le format A vers un colis d’entrepôt unique. Le format B est validé et mappé tel que déclaré. Le fractionnement final et les dimensions mesurées sont encore déterminés après le traitement en entrepôt.

Champs de requête partagés {#shared-fields}

Les deux formats peuvent inclure les éléments suivants.

destination

ChampObligatoireDescription
country_codeOuiISO 3166-1 alpha-2, deux lettres
subdivision_codeNonPar exemple US-CA. Le préfixe pays doit correspondre à country_code.
regionNonNom d’affichage de la subdivision. Un subdivision_code valide a priorité.
postal_codeNonChaîne. Conservez les zéros initiaux.

declared_value

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

Valeur déclarée au niveau de l’expédition en fen CNY entiers. Omettez le champ lorsqu’elle est inconnue. N’envoyez pas 0 pour signifier « inconnu ».

attributes

Tableau de codes d’attributs d’article stables issus de GET /v1/fulfillment/shipments/item-attributes. Chaînes uniques, 100 max.

Les devis sont d’abord limités aux canaux applicables à destination.country_code ; les canaux des autres pays sont omis. Chaque canal restant évalue séparément les attributs déclarés. Un attribut non pris en charge produit UNAVAILABLE avec ATTRIBUTE_NOT_SUPPORTED, tandis que les autres canaux applicables peuvent toujours renvoyer un devis.

services

{
  "services": {
    "channel": [
      {
        "code": "LINE_INSURANCE",
        "quantity": 1
      }
    ],
    "outbound": [
      {
        "code": "VACUUM_PACKING",
        "quantity": 1
      }
    ],
    "inbound": [
      {
        "code": "PHOTO",
        "quantity": 3
      }
    ]
  }
}
GroupeSignification
channelServices à valeur ajoutée du canal. Les codes proviennent des canaux value_added_services[].code.
outboundTraitement sortant en entrepôt
inboundTraitement entrant en entrepôt

Chaque élément exige code et quantity. OpenAPI : quantity est un entier de 1 à 999. Les codes doivent être uniques au sein de chaque groupe.

channel_codes

Codes de canal stables qui restreignent l’ensemble des devis. Omettez-les pour coter tous les canaux candidats. N’envoyez pas un tableau vide. Un code inconnu ou inaccessible renvoie 400 INVALID_SHIPPING_CHANNEL pour toute la requête.

Exemple de requête complète {#complete-request}

Format A avec destination, dimensions, valeur déclarée, attributs, services et un filtre 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"
  ]
}

Réponse {#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."
}

Champs de premier niveau

ChampDescription
successtrue pour une estimation réussie, y compris lorsque certains devis sont UNAVAILABLE.
estimate_typeDECLARED — basé sur des données déclarées, pas sur une mesure d’entrepôt.
completenessDegré de complétude de l’entrée. Ce n’est pas une garantie de livrabilité.
warningsAvertissements au niveau de l’expédition.
quotesRésultats par canal : complets d’abord, puis partiels/revue, puis indisponibles.
monetary_unitToujours CNY_minor.
generated_atHorodatage de la réponse.
request_idCorréler avec x-request-id.
disclaimerClause de non-responsabilité lisible de l’estimation.

completeness

ChampSignification
levelCouverture globale de l’entrée, par exemple HIGH.
destinationDegré de complétude de la destination (COMPLETE lorsque le pays est présent).
package_dimensionsIndique si longueur/largeur/hauteur ont été fournies.
package_splitDECLARED lorsque vous avez envoyé packages[] ; le raccourci suppose un colis unique.
declared_valuePROVIDED ou omis/inconnu.
attributesIndique si les attributs d’article ont été déclarés.
servicesREQUESTED_ONLY lorsque vous avez envoyé des services sélectionnés ; l’entrepôt peut encore en ajouter.

Statut du devis {#quote-status}

Ne décidez pas à partir de available seul. Lisez toujours quote_status.

quote_statusavailabletotalSignification
COMPLETEtrueObjet monétaireBudget complet que vous pouvez afficher. Toujours non verrouillé.
PARTIALtruegénéralement nullEntrées manquantes. Lisez les avertissements et ajoutez dimensions, code postal ou valeur déclarée.
REVIEW_REQUIREDtruegénéralement nullUne mesure d’entrepôt ou une revue humaine est requise.
UNAVAILABLEfalsenullCe canal ne peut pas coter. La requête HTTP a tout de même réussi.
  • total est le budget complet lorsqu’il est connu.
  • known_total est la somme des frais calculables maintenant.
  • Lorsque total est null, ne traitez pas known_total comme un devis complet.
  • unavailable_reason.code est destiné au traitement programmatique.
  • unavailable_reason.message est uniquement destiné à l’affichage.

UNAVAILABLE sur un devis n’est pas une erreur HTTP.

Objet devis {#quotes}

ChampDescription
channel{ code, name, description, tags, capabilities } — même identité que le catalogue de canaux.
channel.capabilities.delivery_methodsTableau optionnel et rétrocompatible de codes de livraison stables : DOOR_DELIVERY, PICKUP, POST_OFFICE_PICKUP. Il peut être présent pour tout statut ; les clients existants peuvent l’ignorer.
availableIndique si ce canal a produit une estimation utilisable. À coupler avec quote_status.
quote_statusCOMPLETE · PARTIAL · REVIEW_REQUIRED · UNAVAILABLE.
unavailable_reason{ code, message } ou null.
attribute_evaluationRésultat facultatif par canal : SUPPORTED, UNSUPPORTED ou NOT_DECLARED, avec les attributs déclarés, acceptés et non pris en charge.
matched_region{ code, name, match_type } ou null.
packagesColis déclarés ou mappés plus poids par colis.
weightsactual / volumetric / chargeable au niveau de l’expédition, en KG.
billing_quantityQuantité réellement facturée par le canal, avec l’unité KG, M3 ou KG_PER_M3.
pricing_selectorComment cette quantité a atteint une tranche de grille (type, value, unit, scope).
transit_timeDélai de transit de référence.
chargesGroupes de frais. Voir ci-dessous.
display_chargesLignes optionnelles destinées uniquement à l’UI. Si included_in_total est false, ne les ajoutez pas à total.
total / known_totalBudget complet vs frais actuellement connus.
warningsAvertissements au niveau du canal.
service_adjustment_possibletrue si le traitement en entrepôt peut encore modifier les services et les frais.

Poids et quantité facturable {#weights}

  • actual — poids déclaré ou mesuré.
  • volumetric — poids volumétrique.
  • chargeable — poids utilisé pour le fret.
  • billing_quantity — quantité facturée par le canal (peut être le poids, le volume ou la densité).
  • pricing_selector — comment cette quantité a sélectionné une ligne tarifaire. Les types correspondent au catalogue WEIGHT / VOLUME / DENSITY.
  • Les canaux multi-colis peuvent arrondir par carton puis sommer. Lorsque pricing_selector.scope est PER_PACKAGE, lisez chaque packages[].pricing_selector.

Frais {#charges}

GroupeSignification
base_freightFret international de base
channel_servicesServices de canal obligatoires et sélectionnés par le développeur
channel_rulesRègles de surcharge, surpoids, valeur déclarée et autres règles d’itinéraire
outbound_servicesServices à valeur ajoutée lors de la préparation / sortie de l’expédition
inbound_servicesServices à valeur ajoutée lors de la réception / entrée en entrepôt
adjustmentsAjustements

Services entrants et sortants

inbound_services et outbound_services correspondent à deux étapes distinctes des services à valeur ajoutée de l’entrepôt. Les services entrants sont exécutés à la réception, par exemple les photos du colis, l’enregistrement vidéo ou l’inspection. Les services sortants sont exécutés pendant la préparation de l’expédition, par exemple le renforcement, l’emballage sous vide ou l’emballage sur cadre/en caisse en bois. Les deux étapes peuvent légitimement s’appliquer et être facturées au même colis ou à la même expédition.

Les montants du devis ne sont que des estimations ; demander un devis ne crée pas de frais de service supplémentaires. Les frais définitifs dépendent des services réellement exécutés et de leur tarification et règlement finaux. Utilisez les deux groupes pour estimer le coût total, puis rapprochez chaque estimation des frais réels correspondants. N’ajoutez pas de nouveau l’estimation d’un service individuel à ses frais définitifs.

Exemple en unités mineures CNY : photos du colis 50 fen (¥0,50), inspection 100 fen (¥1,00), emballage sous vide 150 fen (¥1,50) et renforcement du colis 200 fen (¥2,00). Les quatre peuvent coexister car il s’agit de services différents exécutés à des étapes différentes.

Chaque groupe inclut généralement :

ChampSignification
amountTotal du groupe en fen, ou null si inconnu
currencyCNY
known_amountSomme des éléments calculables maintenant
calculation_statusPar exemple CALCULATED
itemsLignes de détail

channel_rules peut aussi inclure aggregation et cap. Utilisez le sous-total du groupe — ne le remplacez pas en sommant les lignes de règles brutes.

SUM_ALL cumule tous les frais correspondants. HIGHEST_ONLY ne retient que le montant le plus élevé après tri décroissant ; les règles de même prix sont équivalentes. cap=null signifie sans plafond. reason est réservé à l’affichage. Pour la logique, utilisez condition_match, matched_conditions, rule_type, charge_mode, charge_value, outcome et missing_fields. Les règles PENDING_INPUT, REVIEW_REQUIRED et autres règles non calculées sont exclues du total connu. amount=null n’est pas zéro et un charge_value configuré n’est pas un frais réellement facturé.

Lignes de frais

ChampSignification
codeCode de frais ou de service stable
nameNom d’affichage localisé
categoryCatégorie de frais
sourceMANDATORY · DEVELOPER_SELECTED · RULE_ENGINE
pricing_basisComment la ligne a été tarifée
quantityQuantité facturable de la ligne
unit_pricePrix unitaire en fen lorsqu’il est connu
amountTotal de la ligne. null signifie inconnu, pas zéro.
estimatedIndique si la ligne est encore une estimation
calculation_statusÉtat du calcul
affected_by_packagesIndique si le nombre/la taille des colis peut modifier cette ligne
included_in_totalSi false, ne l’ajoutez pas une seconde fois à total

display_charges peut n’exister que pour la présentation frontend.

Motifs d’indisponibilité {#unavailable-reasons}

Valeurs courantes 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

Les canaux indisponibles restent dans quotes[] afin que vous puissiez expliquer pourquoi ils ont été rejetés.

Terminologie du catalogue {#catalog-terminology}

Canaux d’expéditionCette APISignification
items[].code/name/description/tagsquotes[].channel.*Même canal
regions[].code/name/match_typequotes[].matched_region.*Région sélectionnée par le devis
value_added_services[].codeservices.channel[].code et code des fraisCode de service stable
billing.quantity_unitbilling_quantity.unit / pricing_selector.unitUnité de facturation
rule_summary.aggregationcharges.channel_rules.aggregationAgrégation des règles
rule_summary.capcharges.channel_rules.capPlafond après agrégation ; null signifie sans plafond

Attributs d’article {#item-attributes}

GET /v1/fulfillment/shipments/item-attributes renvoie les codes attributes[] valides pour les devis.

Erreurs {#errors}

HTTPerror.codeQuand
400VALIDATION_ERRORStructure invalide, formats de requête mixtes, unités KG/CM, codes dupliqués ou channel_codes vide
400INVALID_SHIPPING_CHANNELUne valeur channel_codes demandée est inconnue ou non visible pour l’app
401INVALID_API_KEYJeton Bearer manquant ou invalide
403FULFILLMENT_MODE_NOT_SUPPORTEDL’app utilise le self fulfillment
403WAREHOUSE_AUTH_INVALIDL’autorisation d’entrepôt est manquante, rejetée ou expirée
422INVALID_COUNTRY_CODELe pays de destination est invalide
422INVALID_ITEM_ATTRIBUTEUn code d’attribut est invalide
502WAREHOUSE_UPSTREAM_ERRORLe service d’entrepôt a échoué ; réessayez avec backoff

Il n’existe pas de code public distinct AUTHENTICATION_ERROR, WAREHOUSE_AUTH_REQUIRED ou WAREHOUSE_SERVICE_UNAVAILABLE. Utilisez 401 INVALID_API_KEY, 403 WAREHOUSE_AUTH_INVALID et 502 WAREHOUSE_UPSTREAM_ERROR.

Un canal qui ne peut pas transporter cette expédition est un devis UNAVAILABLE, pas un échec HTTP.

Get Support

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

Email support