Errors
Toutes les réponses d'erreur utilisent la même forme. Le code HTTP indique la grande catégorie ; le error.code donne la raison précise.
Format d'erreur
json
{
"error": {
"code": "validation_failed",
"message": "The request body did not match the expected schema.",
"request_id": "req_8f3a1c2d4e5b6a7f",
"details": {
"field": "variants[0].price",
"reason": "must be a number"
}
}
}| Champ | Type | Toujours présent | Rôle |
|---|---|---|---|
code | string | Oui | Identifiant d'erreur machine-readable. Utilisez-le pour le branching dans votre client. La liste complète est dans Humind error codes. |
message | string | Oui | Résumé human-readable. Court, en anglais. Ne l'affichez pas brut aux end users, c'est écrit pour les développeurs. |
request_id | string | Oui | Identifiant unique de cette requête. Joignez-le à vos tickets support pour qu'on puisse retrouver les logs serveur correspondants. |
details | object | Non | Contexte par erreur : quel champ a échoué la validation, quels scopes manquaient, quel champ a causé un conflit d'idempotency, etc. La forme dépend de code. |
Codes HTTP
| Code | Signification | Quand il est renvoyé |
|---|---|---|
200 OK | Succès | GET, PUT, PATCH, POST upserts qui ont mis à jour une ressource existante. |
201 Created | Ressource créée | POST qui a créé une nouvelle ressource. |
204 No Content | Succès, pas de body | DELETE. |
207 Multi-Status | Statuts par item dans un batch | POST /products/batch. Le top-level est 207 ; chaque item dans la réponse porte son propre code. Voir Batch upsert. |
400 Bad Request | Requête malformée ou invalide | Le body n'est pas du JSON valide (invalid_json), la validation de schéma échoue (validation_failed), ou un header requis est absent / trop long (idempotency_key_required, idempotency_key_too_long). |
401 Unauthorized | Échec auth | Clé API manquante, malformée, invalide, révoquée ou expirée. |
403 Forbidden | Auth réussie mais interdit | La clé est valide mais n'a pas le scope requis pour cet endpoint. |
404 Not Found | Ressource inexistante ou appartient à un autre tenant | Inclut « existe mais appartient à une autre company », Humind ne révèle jamais l'existence cross-tenant. |
409 Conflict | Réutilisation d'idempotency avec body différent | L'Idempotency-Key a déjà été utilisé avec un body différent. |
413 Payload Too Large | Body au-dessus de 5 MB | Réduisez le payload ou splittez en batches. Renvoie payload_too_large. |
415 Unsupported Media Type | Content-Type absent ou incorrect | Une requête d'écriture (POST, PUT, PATCH) n'a pas envoyé Content-Type: application/json. Renvoie unsupported_media_type. |
422 Unprocessable Entity | Invariant ressource violé | Utilisé pour cannot_delete_last_variant, wrong_type, file_not_uploaded, invalid_lang_format, tag_resolution_failed, et les erreurs des state-machines imports / webhooks. Les erreurs « champ X invalide » classiques renvoient 400 validation_failed. |
429 Too Many Requests | Throttlé | Rate limit par clé API (rate_limited) ou throttle par IP de la couche d'auth (too_many_failures). |
500 Internal Server Error | Erreur inattendue de notre côté | Inclut le request_id. Safe à retenter avec le même Idempotency-Key. |
502 / 503 / 504 | Problème upstream / capacité | Transitoire. Retentez avec backoff en utilisant le même Idempotency-Key. |
Codes d'erreur Humind
| Code | HTTP | Signification | Comment résoudre |
|---|---|---|---|
missing_credentials | 401 | Pas de header Authorization, ou il ne commence pas par Bearer . | Ajoutez Authorization: Bearer hmd_live_... à la requête. |
invalid_key_format | 401 | Le token ne match pas hmd_(live|test)_<22>_<8>. | Vérifiez les espaces de bord, caractères manquants ou points de suspension collés. Voir Format de clé. |
invalid_checksum | 401 | Le checksum 8 caractères en fin de token ne match pas le reste. Presque toujours une typo de copier-coller. | Recopiez la clé depuis le dashboard, ou régénérez-la si vous n'avez plus accès à l'originale. |
invalid_key | 401 | Le token a la bonne forme mais ne correspond à aucune clé active (inconnue, révoquée ou expirée). | Vérifiez la clé dans votre dashboard. Si elle a été révoquée, créez-en une nouvelle. |
revoked | 401 | La clé a été révoquée manuellement ou via « regenerate ». | Créez une nouvelle clé et mettez à jour votre secret store. |
expired | 401 | La clé a un expires_at dans le passé. | Créez une nouvelle clé ; envisagez de ne pas mettre d'expiry, ou de la mettre plus loin. |
insufficient_scope | 403 | La clé est valide mais n'a pas un scope que cet endpoint requiert. details.required liste les scopes requis ; details.missing liste ceux qui manquent. | Créez une nouvelle clé avec les scopes manquants. Les scopes sont immuables, vous ne pouvez pas en ajouter à une clé existante. Voir Scopes. |
validation_failed | 400 | Le body a parsé mais ne match pas le schéma de la ressource ; details.issues liste chaque champ fautif avec son path, message et code. | Corrigez les champs et renvoyez. Le même Idempotency-Key n'est safe à réutiliser sur la requête corrigée que si le changement de body est la fix de validation ; en pratique, générez un nouveau UUID. |
invalid_json | 400 | Le body de la requête n'est pas du JSON valide. | Vérifiez votre sérialisation. Le header Content-Type: application/json est requis et le body doit parser avec JSON.parse. |
payload_too_large | 413 | Le body de la requête dépasse la limite de 5 MB. | Splittez en payloads plus petits. Pour les backfills de catalogue, utilisez POST /products/batch (jusqu'à 500 items par appel) ou la pipeline async Imports. |
unsupported_media_type | 415 | La requête a omis Content-Type: application/json sur un POST, PUT ou PATCH (ou a envoyé un autre content-type). | Mettez Content-Type: application/json sur chaque requête d'écriture. |
not_found | 404 | La ressource n'existe pas, ou appartient à une autre company. | Vérifiez l'id que vous avez passé. Si vous utilisez api:<external_id>, confirmez que l'external_id existe pour cette company. |
idempotency_conflict | 409 | Un Idempotency-Key a été réutilisé avec un body différent. | Générez un UUID frais pour cette requête. Réutilisez la clé seulement quand vous retentez la même requête. |
idempotency_key_required | 400 | Un appel state-changing (POST, PUT, PATCH, DELETE) a été fait sans header Idempotency-Key sur un endpoint qui en demande maintenant un. | Ajoutez un header Idempotency-Key: <uuid>. Voir Idempotency. |
idempotency_key_too_long | 400 | Le header Idempotency-Key dépasse 255 caractères. | Utilisez un UUID v4 (36 caractères) ou n'importe quelle valeur unique courte. |
idempotency_in_progress | 409 | Le même Idempotency-Key est en train d'être traité par une autre requête concurrente. | Attendez que la requête originale finisse, puis retentez avec la même clé, la réponse cachée sera rejouée. |
duplicate_external_id_in_batch | - | Le même external_id est apparu plus d'une fois dans un payload batch (POST /products/batch, POST /collections/batch, POST /knowledge/batch). La première occurrence est traitée normalement ; les doublons suivants reviennent avec status: "failed" dans le résultat par item. Remonté à l'intérieur du body 207, pas comme une erreur HTTP top-level. | Dédupliquez les external_id dans votre payload batch avant l'envoi. |
handle_already_used | 409 | Un POST / PUT / PATCH sur /collections a positionné un handle qui appartient déjà à une autre collection de cette company (matched sur un autre external_id). details.handle contient la valeur fautive. | Choisissez un handle différent, ou faites un PATCH sur la collection existante (matched par external_id) au lieu d'en créer une nouvelle. |
tag_resolution_failed | 422 | Un nom de tag dans tags n'a pas pu être résolu ou créé (rare). details.tag porte le nom fautif. | Retentez avec le même body. Si ça persiste, partagez le request_id avec le support. |
translation_not_found | 404 | Un GET sur une sub-resource translations cible un {lang} qui n'a pas de traduction stockée sur la ressource. Le DELETE est idempotent et ne lève pas ce code. | Vérifiez le code de locale, ou utilisez le champ translations de la ressource parente pour voir quelles locales existent. |
variant_not_found | 404 | Le {variant_external_id} sur un appel à la sub-resource variants ne correspond à aucun variant du produit. Le DELETE est idempotent et ne lève pas ce code. | Vérifiez l'external_id du variant contre l'array variants du produit parent. |
invalid_lang_format | 422 | Le segment {lang} d'une URL de sub-resource translations ne match pas ^[a-z]{2}(-[A-Z]{2})?$. | Utilisez un tag court BCP 47 comme en, fr, de, pt-BR. |
webpage_fetch_failed | - | Le fetch de l'URL d'une entrée knowledge webpage a échoué. Remonté via le status='failed' de l'entrée, pas une erreur HTTP top-level. | Vérifiez que l'URL est publiquement joignable et HTML, puis PATCH l'entrée pour re-mettre en file. Voir Le type webpage. |
wrong_type | 400 | Un endpoint knowledge type-spécifique (e.g. /file-upload-url, /file-upload-completed) a été appelé sur une entrée dont le discriminateur ne match pas. Le message d'erreur reprend le type réel. | Soit reciblez l'appel sur une entrée qui match, soit utilisez le bon endpoint pour le type de l'entrée. Voir Le type file. |
file_not_uploaded | 422 | POST /knowledge/{id}/file-upload-completed a été appelé avant que le merchant n'ait PUT le payload du fichier vers l'URL SAS générée par /file-upload-url. | Complétez le PUT d'upload en premier, puis retentez. Voir Le type file. |
too_many_failures | 429 | Une IP a accumulé trop de tentatives d'auth en échec dans une fenêtre courte. | Arrêtez de prober. Vérifiez votre clé, puis retentez après une minute. |
import_not_pending | 422 | start ou cancel a été appelé sur un import qui n'est pas dans le bon état pour cette transition (par exemple start sur un import déjà processing / done / failed / cancelled). | Vérifiez status d'abord via GET /imports/{sync_id}. Chaque transition du cycle de vie est à sens unique. |
import_blob_missing | 422 | start a été appelé sur un import pour lequel aucun fichier NDJSON n'a encore été uploadé (le blob derrière upload_url renvoie 404). | PUT le fichier sur upload_url d'abord, puis appelez start. Voir Imports. |
webhook_endpoint_not_found | 404 | Le :id d'endpoint webhook ne correspond pas à un endpoint qui appartient à votre company. | Vérifiez l'id. Les lookups cross-tenant renvoient aussi 404. Voir Webhooks. |
invalid_event_type | 422 | Une entrée dans events sur POST / PATCH /webhooks/endpoints n'est pas un type d'event connu. | Utilisez une des valeurs listées dans Events disponibles. |
invalid_url | 422 | L'url d'un endpoint webhook n'est pas une URL HTTPS valide, ou pointe sur un host privé (localhost, 127.0.0.1, RFC1918) en mode live. | Utilisez une URL https:// publiquement joignable. Pour le dev local, utilisez une clé hmd_test_* avec un tunnel. |
webhook_disabled | 422 | Une tentative d'interaction avec un endpoint webhook disabled qui demande qu'il soit actif. | Réactivez via PATCH /webhooks/endpoints/:id avec { "status": "active" }. |
internal_error | 500 | Échec serveur inattendu. | Retentez avec backoff. Si ça persiste, contactez le support avec le request_id. |
Conseils de debug
- Loggez toujours le
request_idà côté du code de statut et de l'error.codedans votre client. L'inclure dans un ticket support fait passer notre triage de « chercher une aiguille dans 500k lignes de logs » à « regarder un seul record ». - Ne bouclez pas sur les 401. Un 401 veut dire qu'il faut une intervention humaine (vérifier la clé, la rotater, fixer le header). Retenter une mauvaise clé déclenche juste le cooldown too_many_failures.
- Traitez les 5xx comme transitoires. Retentez avec backoff exponentiel et le même
Idempotency-Key. On logge chaque 5xx avec lerequest_id; si vous voyez un pattern, partagez les IDs avec le support. - 400 vs 422. Un 400 couvre tout ce qui ne va pas avec l'enveloppe de la requête ou le schéma : JSON invalide, headers manquants/oversized, champ avec un mauvais type ou hors range. Un 422 est réservé aux invariants ressource que le schéma seul ne peut pas exprimer — par exemple « tu ne peux pas retirer le dernier variant d'un produit », ou « le
typede cette knowledge entry ne match pas l'endpoint que tu as appelé ». La majorité des erreurs de validation sont en 400 ; si vous voyez du 422, regardez le code spécifique dans le tableau ci-dessus.
Pour aller plus loin
- Authentication : liste complète des codes liés à l'auth (
missing_credentials,invalid_checksum,revoked, …) en contexte. - Conventions : format des requêtes et idempotency, source de la majorité des erreurs de validation.
- Products : tables d'erreurs par endpoint.