RefCampaign/docs

Gestion des erreurs

Forme de la réponse d'erreur, codes courants et stratégie de retry.

Chaque réponse d'erreur retournée par l'API suit la même forme. Les codes sont stables et machine-readable ; les messages sont human-readable et peuvent changer de formulation entre versions.

Forme de la réponse

{
  "success": false,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Validation failed.",
    "details": [
      {
        "path": ["amount"],
        "message": "Number must be greater than 0"
      }
    ]
  },
  "meta": {
    "timestamp": "2026-05-03T10:23:11.000Z"
  }
}
ChampTypeNotes
successfalseToujours false sur les erreurs.
error.codestringEnum stable — basez votre logique client sur ce champ.
error.messagestringHuman-readable. Adapté aux logs, pas aux end-users.
error.detailsunknownContexte libre. Pour VALIDATION_FAILED, un tableau d'issues Zod.
meta.timestampstringISO-8601 UTC. Utile pour les tickets support.

Le code HTTP miroir la catégorie d'échec (4xx pour erreurs client, 5xx pour erreurs serveur). error.code affine davantage.

Codes courants

HTTPerror.codeQuand vous le verrez
400VALIDATION_FAILEDLe body ou les query params ne matchent pas le schema. details liste les problèmes par champ.
400INVALID_REQUESTBody unparseable, ou shape de requête fondamentalement mauvaise (content-type manquant, etc.).
401UNAUTHORIZEDClé API manquante, mal formée ou révoquée.
403PERMISSION_DENIEDAuthentifié mais pas autorisé (mauvais compte, marchand verrouillé, abonnement expiré).
404NOT_FOUNDL'id de ressource n'existe pas ou n'appartient pas à votre compte.
409ALREADY_EXISTSCréation dupliquée (ex. un affilié avec le même email existe déjà dans cette campagne).
429RATE_LIMIT_EXCEEDEDLimite par IP ou par compte atteinte. Respectez Retry-After.
429LIMIT_EXCEEDEDQuota du tier d'abonnement atteint (ex. cap mensuel de conversions). Upgrade ou attente du reset.
500SERVER_ERRORÉchec upstream générique. Retry avec backoff.
503SERVICE_UNAVAILABLEUn service downstream (provider de paiement, queue) est dégradé. Retry.

La liste complète est dans la spec OpenAPI sous components.schemas.ApiErrorResponse.properties.error.code.enum.

Stratégie de retry

Pas de retry sur les 4xx

Les réponses 4xx (sauf 429) signifient que la requête elle-même est mauvaise. Retry sans changer le payload échouera à nouveau et grignote votre quota de rate limit. Corrigez l'appel, pas la boucle de retry.

Un client robuste distingue trois cas :

  1. Erreur client terminale (4xx sauf 429) — votre payload est mauvais. NE PAS retry. Logguez, corrigez le call site.
  2. Erreur serveur transitoire (5xx) — RefCampaign upstream est en difficulté. Retry avec backoff exponentiel (1s, 2s, 4s, 8s) jusqu'à environ 5 tentatives.
  3. Rate limited (429) — backoff selon le header Retry-After. Le serveur vous dit quand revenir.

Pseudocode :

async function callWithRetry(fetcher, maxAttempts = 5) {
  let attempt = 0
  while (attempt < maxAttempts) {
    const res = await fetcher()
    if (res.ok) return res
    if (res.status === 429) {
      const retryAfter = parseInt(res.headers.get('retry-after') ?? '5', 10)
      await sleep(retryAfter * 1000)
      attempt++
      continue
    }
    if (res.status >= 500) {
      await sleep(Math.min(2 ** attempt * 1000, 30_000))
      attempt++
      continue
    }
    throw await errorFromResponse(res) // 4xx — terminal
  }
  throw new Error('Exhausted retries')
}

Le SDK officiel @refcampaign/sdk gère tout cela pour vous.

Erreurs de validation

VALIDATION_FAILED renvoie error.details comme un tableau d'issues Zod :

{
  "success": false,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Validation failed.",
    "details": [
      { "path": ["currency"], "code": "invalid_string", "message": "currency must be a 3-letter ISO code" },
      { "path": ["amount"], "code": "too_small", "message": "Number must be greater than 0" }
    ]
  }
}

Le tableau path est le chemin pointé dans votre body de requête ou query params. Affichez ces données dans votre UI / logs pour pointer l'utilisateur sur le champ exact.

Idempotence et gestion des erreurs de duplication

Certains endpoints sont idempotents sur une clé (POST /api/v1/conversions/track sur sessionId dans une fenêtre de cinq minutes — voir postback). Si votre logique de retry déclenche un duplicate, vous obtenez la même réponse de succès, pas un 409. 409 ALREADY_EXISTS est réservé aux vraies tentatives de création dupliquées (ex. inscrire le même email à la même campagne deux fois).

Quand alerter

Considérez ces situations comme dignes d'astreinte :

  • Tout taux de 5xx soutenu au-dessus de ~1% sur 5 min — problème côté RefCampaign.
  • Tout 429 RATE_LIMIT_EXCEEDED inattendu — la forme de votre trafic a changé ; à investiguer.
  • 403 PERMISSION_DENIED en dehors des paths attendus — le statut de votre abonnement a peut-être changé.

401 UNAUTHORIZED après un déploiement signifie presque toujours que la clé API n'a pas été propagée au nouvel environnement.

Sur cette page