boxioo Developers

Erreurs

Enveloppe d'erreur, codes stables, et catalogue complet.

Chaque réponse d'erreur de l'API a la même forme :

{
  "error": {
    "type": "validation_error",
    "code": "unknown_field",
    "message": "Field 'foo' does not exist on object 'contact'.",
    "requestId": "req_8a4f2e10bb55",
    "docUrl": "https://docs.boxioo/errors/unknown_field"
  }
}
ChampSignification
typeFamille générale. Branchez dessus pour la logique de retry/UX.
codeCode lisible machine. Contrat stable — branchez dessus pour l'UI.
messageExplication lisible. Le format peut changer entre versions.
requestIdCorrèle avec le header X-Request-Id. À citer dans les tickets support.
docUrlLien direct vers cette section.

Types

typePlage de statutRéessayable ?
authentication_error401Non — corrigez votre clé
permission_error403Non — obtenez une clé avec le bon scope
validation_error400Non — corrigez la requête
not_found_error404Non
conflict_error409Peut-être — selon le code
rate_limit_error429Oui — respectez Retry-After
api_error5xxOui — backoff exponentiel

Catalogue des codes

400 · Validation

CodeSignification
invalid_requestCorps mal formé ou paramètre obligatoire manquant.
unknown_fieldLe systemName envoyé n'existe pas sur cet objet.
field_not_editableLe champ existe mais isEditable: false.
invalid_field_valueType incorrect (string là où un nombre est attendu, etc.).
invalid_optionL'id d'option SELECT n'est pas dans l'ensemble du champ.
invalid_relationL'id de l'enregistrement lié n'existe pas dans ce tenant ou mauvais objet cible.
invalid_userL'utilisateur référencé n'est pas membre de ce tenant.
missing_required_fieldUn champ isRequired: true est absent sur un POST.
unsupported_field_typeFILE / IMAGE / OUTLINE — pas encore exposés via l'API publique.
payload_too_largeLe corps de requête dépasse 256 Ko.

401 · Authentification

CodeSignification
unauthorizedGénérique — pas de clé, ou clé non reconnue.
invalid_api_keyHeader mal formé, ou clé n'ayant jamais existé.
api_key_revokedLa clé a été révoquée dans le dashboard.
api_key_expiredLa clé a dépassé son expiresAt.

403 · Permission

CodeSignification
forbiddenÉchec de permission générique.
insufficient_scopeLa clé est valide mais n'a pas le scope requis.
tenant_mismatchLe header X-Tenant-Id ne correspond pas au tenant de la clé.
quota_exceededUn quota par tenant (objets, champs) est atteint.

404 · Introuvable

CodeSignification
resource_not_foundL'id d'objet / enregistrement / champ est inconnu dans ce tenant.

409 · Conflit

CodeSignification
conflictConflit générique.
duplicate_valueUn champ unique a déjà cette valeur.
idempotency_key_conflictLa clé d'idempotence a été réutilisée avec un corps différent.

429 · Limite de débit

CodeSignification
rate_limitedTrop de requêtes sur une fenêtre. Lisez Limitation de débit.

5xx · Serveur

CodeSignification
internal_errorUn problème de notre côté. Réessayez, puis alertez-nous.

Stratégie de retry

Pseudo-code pour un client robuste :

async function call<T>(req: Request): Promise<T> {
  for (let attempt = 0; attempt < 5; attempt++) {
    const res = await fetch(req);
    if (res.ok) return res.json();
 
    const err = await res.json();
 
    // Échecs permanents — on abandonne
    if (err.error.type === 'validation_error') throw err;
    if (err.error.type === 'permission_error') throw err;
    if (err.error.type === 'authentication_error') throw err;
    if (err.error.type === 'not_found_error') throw err;
 
    // Transitoires — backoff
    if (res.status === 429) {
      const retryAfter = Number(res.headers.get('Retry-After') ?? 1);
      await sleep(retryAfter * 1000);
      continue;
    }
    if (res.status >= 500) {
      await sleep(Math.pow(2, attempt) * 1000);
      continue;
    }
    throw err;
  }
  throw new Error('Retries épuisés');
}

On this page