Comment sont structurées les réponses d’erreur de l’API LinkHarbor, ce que signifient les principaux codes et comment votre code doit y réagir.
Chaque réponse d’erreur de l’API a le même format. Votre code doit se fier au code d’erreur du champ error, pas au texte de message – le code reste stable, alors que le texte peut changer et est traduit dans la langue du compte.
Structure d’une réponse d’erreur
{
"error": "validation_failed",
"message": "Some of the information provided is invalid. Please check and try again.",
"details": [
{ "field": "title", "reason": "minLength", "message": "…" }
],
"request_id": "6b1f0c2e-…"
} - error
- Code lisible par machine, par exemple not_found. Pour la plupart des erreurs, il figure aussi dans l’en-tête X-Error-Code – mais fiez-vous au champ du corps.
- message
- Description lisible par un humain dans la langue du compte : avec une clé API, celle du propriétaire de l’espace de travail ; avec une application connectée, celle de la personne qui l’a connectée. Sans jeton valide – par exemple pour le 401 du contrôle de jeton –, la langue suit Accept-Language, sinon c’est l’anglais. L’en-tête Content-Language indique la langue utilisée.
- details
- Présent uniquement s’il y a plus à dire. Pour un 422 issu de la validation des saisies, une liste avec field, reason et message pour chaque problème ; pour un 422 issu de la logique métier et toutes les autres erreurs, un objet, par exemple avec reason, retry_after_sec ou une liste issues. En cas de dépassement de taille, il contient field, reason et limit, et pour 413 request_too_large max_bytes et max_kb. Vérifiez donc si details est une liste.
- request_id
- L’ID de la requête. Il figure aussi dans l’en-tête X-Request-Id. Indiquez-le quand vous contactez le support.
Exceptions : la réponse 429 rate_limited a le champ retry_after_sec au lieu de details ; avec 429 et 403 insufficient_scope, request_id manque dans le corps. Le 401 du contrôle de jeton et le 422 du contrôle de schéma n’ont pas d’en-tête X-Error-Code ; avec le contrôle de schéma, seul le message de premier niveau est traduit, les textes de details restent en anglais. L’en-tête X-Request-Id est toujours présent.
Les codes les plus importants
| HTTP | error | Signification | Que faire |
|---|---|---|---|
| 400 | invalid_json | Le corps n’est pas du JSON valide | Vérifiez le JSON |
| 400 | bad_request | Content-Type erroné ou requête mal formée | Définissez Content-Type: application/json |
| 401 | missing_bearer_token | Pas de jeton dans l’en-tête Authorization | Définissez l’en-tête Authorization: Bearer … |
| 401 | invalid_token | Jeton expiré ou invalide, ou clé supprimée | Récupérez un nouveau jeton ; si cela ne suffit pas, vérifiez la clé |
| 401 | invalid_api_key | ID ou secret de clé erroné lors de l’échange de jeton | Vérifiez les identifiants |
| 402 | plan_limit_reached | Limite de l’offre atteinte, par exemple pour les liens courts | Passez à une offre supérieure ou supprimez des éléments |
| 403 | insufficient_scope | Portée manquante ou endpoint non ouvert aux clés API | Créez une clé avec la bonne portée |
| 403 | forbidden | Pas de droit pour cette action | Faites-le dans le tableau de bord |
| 403 | feature_not_available | Fonction non incluse dans l’offre | Vérifiez l’offre |
| 403 | block_type_requires_plan | Type de bloc disponible uniquement dans une offre supérieure | Choisissez un autre type de bloc ou passez à une offre supérieure |
| 403 | template_locked | Modèle premium non disponible dans l’offre actuelle | Choisissez un modèle dans GET /v1/templates/available |
| 403 | workspace_suspended, workspace_read_only, workspace_grace_expired | Espace de travail bloqué ou en lecture seule à cause d’un paiement en attente | Réglez le paiement dans le tableau de bord |
| 404 | not_found | La ressource n’existe pas ou n’appartient pas à votre espace de travail | Vérifiez l’ID |
| 409 | conflict | Conflit général avec l’état actuel | Rechargez l’état, modifiez la saisie |
| 409 | workspace_template_in_use | Le modèle d’espace de travail est encore utilisé par des pages ; le nombre figure dans details.count | Passez les pages à un autre modèle, puis supprimez-le |
| 409 | handle_taken, slug_taken | Le handle ou le slug du lien court est déjà pris | Choisissez une autre valeur |
| 409 | form_in_use, page_not_private, page_not_published, never_published | Conflit avec l’état : formulaire encore sur une page, page non privée ou non publiée, jamais publiée | Modifiez l’état, puis réessayez |
| 409 | page_limit_reached, link_limit_reached, block_limit_reached, form_limit_reached, asset_limit_reached, asset_storage_limit_reached, workspace_template_limit_reached | Limite de quantité ou de stockage de l’offre atteinte | Supprimez des éléments ou passez à une offre supérieure |
| 409 | draft_not_publishable | Le brouillon a des problèmes ; la liste figure dans details.issues | Corrigez les problèmes, puis republiez |
| 413 | request_too_large | Corps plus grand que ce que permet cet endpoint (64 Ko, 1 Mo ou 2 Mo) ; la limite figure dans details.max_kb | Envoyez moins de données par requête, voir Limites de débit |
| 413 | payload_too_large | Fichier téléversé de plus de 10 Mo | Réduisez la taille du fichier |
| 422 | validation_failed | Saisie invalide ou champ inconnu ; précisions dans details | Corrigez les champs comme indiqué dans details |
| 422 | handle_reserved, target_url_invalid, target_url_scheme, target_url_host | Handle réservé, ou URL cible invalide ou non autorisée | Choisissez une autre valeur |
| 422 | workspace_template_disabled | Le modèle d’espace de travail sélectionné est désactivé | Activez le modèle sous « Domaines et modèles » ou choisissez-en un autre |
| 422 | template_css_external, template_section_invalid | Modèle d’espace de travail : le CSS charge depuis des serveurs externes, ou une section {{#if}}/{{#unless}}/{{#each}} est mal placée | Supprimez les adresses externes, ou fermez la section dans la même balise ou le même texte |
| 422 | custom_css_external | Le CSS personnalisé charge quelque chose depuis des serveurs externes | Supprimez les adresses externes du CSS |
| 429 | rate_limited, api_key_locked | Trop de requêtes, ou clé verrouillée après des échecs | Attendez le temps indiqué par Retry-After ou details.retry_after_sec |
| 500 | internal_error | Erreur inattendue | Réessayez plus tard, notez le request_id |
| 503 | service_unavailable | Service temporairement indisponible | Réessayez après une pause |
Lire les erreurs de saisie
Avec 422 validation_failed, details liste chaque problème séparément : field est le chemin du champ (avec des barres obliques pour les objets imbriqués, par exemple theme_config/button_style), reason est la règle enfreinte, comme required, minLength, maxLength, enum ou additionalProperties. Avec additionalProperties, le message indique quels champs sont inconnus – souvent une faute de frappe dans le nom du champ.
Gestion recommandée dans votre code
- 400, 413 et 422 : ne réessayez pas, corrigez plutôt la requête
- 401 invalid_token : récupérez une fois un nouveau jeton et réessayez
- 403 : ne réessayez pas ; vérifiez la portée, l’offre ou qui a le droit de faire cela
- 404 : vérifiez l’ID ; après une suppression, c’est normal
- 409 : rechargez l’état et décidez si l’action est encore nécessaire
- 429 : attendez le temps indiqué par Retry-After, puis réessayez – voir Limites de débit
- 500 et 503 : réessayez quelques fois avec des pauses croissantes
Cela pourrait aussi vous être utile
Vous n’avez rien trouvé ?
Dites-nous ce dont vous avez besoin, et notre équipe support vous aidera personnellement.