Skip to main content

Format des erreurs

Toutes les erreurs de l’API suivent un format JSON standardisé :
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Description lisible de l'erreur",
    "details": {
      "field": "Information contextuelle"
    }
  }
}

Codes de statut HTTP

L’API utilise les codes de statut HTTP standards :
CodeSignificationDescription
200OKRequête réussie
201CreatedRessource créée avec succès
400Bad RequestRequête invalide (paramètres incorrects)
401UnauthorizedAuthentification requise ou invalide
402Payment RequiredCrédits insuffisants
403ForbiddenAccès refusé à la ressource
404Not FoundRessource non trouvée
429Too Many RequestsLimite de taux dépassée
500Internal Server ErrorErreur serveur
503Service UnavailableService temporairement indisponible

Codes d’erreur courants

Authentification

MISSING_API_KEY

{
  "error": {
    "code": "MISSING_API_KEY",
    "message": "API key is required",
    "details": {
      "header": "X-API-Key"
    }
  }
}
Solution : Ajoutez votre clé API dans l’en-tête X-API-Key

INVALID_API_KEY

{
  "error": {
    "code": "INVALID_API_KEY",
    "message": "Invalid API key",
    "details": {}
  }
}
Solution : Vérifiez que votre clé API est correcte et active

Limites et quotas

INSUFFICIENT_CREDITS

{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Insufficient credits",
    "details": {
      "required": 50,
      "available": 10
    }
  }
}
Solution : Rechargez vos crédits ou passez à un plan supérieur

Validation des données

VALIDATION_ERROR

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": {
      "job_title": "This field is required",
      "contract_type": "Invalid value. Must be one of: CDI, CDD, Stage"
    }
  }
}
Solution : Corrigez les champs indiqués dans details

INVALID_PHONE_NUMBER

{
  "error": {
    "code": "INVALID_PHONE_NUMBER",
    "message": "Invalid phone number format",
    "details": {
      "phone": "0612345678",
      "reason": "Must be a French mobile number (06 or 07)"
    }
  }
}
Solution : Utilisez un numéro de téléphone français valide

Limites et quotas

RATE_LIMIT_EXCEEDED

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded",
    "details": {
      "retry_after": 30
    }
  }
}
Solution : Attendez le nombre de secondes indiqué avant de réessayer

Ressources

RESOURCE_NOT_FOUND

{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "Campaign not found",
    "details": {
      "campaign_id": "abc123def456"
    }
  }
}
Solution : Vérifiez l’ID de la ressource

RESOURCE_CONFLICT

{
  "error": {
    "code": "RESOURCE_CONFLICT",
    "message": "Candidate already exists",
    "details": {
      "phone": "0612345678"
    }
  }
}
Solution : Le candidat existe déjà, utilisez un autre numéro

Gestion des erreurs

Exemple Python

import requests

def create_campaign(data):
    try:
        response = requests.post(
            "https://app.voicehire.io/api/v1/campaigns/create",
            headers={"X-API-Key": API_KEY},
            json=data
        )
        
        # Vérifier le statut HTTP
        if response.status_code == 201:
            return response.json()
        
        # Gérer les erreurs
        error_data = response.json()
        error_code = error_data['error']['code']
        
        if error_code == 'INSUFFICIENT_CREDITS':
            # Notifier l'utilisateur de recharger
            send_low_credits_notification()
        elif error_code == 'VALIDATION_ERROR':
            # Afficher les erreurs de validation
            for field, message in error_data['error']['details'].items():
                print(f"Erreur sur {field}: {message}")
        
        raise Exception(f"API Error: {error_data['error']['message']}")
        
    except requests.exceptions.RequestException as e:
        # Gérer les erreurs réseau
        print(f"Network error: {e}")
        raise

Exemple JavaScript

async function addCandidates(campaignId, candidates) {
  try {
    const response = await fetch(
      `https://app.voicehire.io/api/v1/campaigns/${campaignId}/candidates`,
      {
        method: 'POST',
        headers: {
          'X-API-Key': API_KEY,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ candidates })
      }
    );
    
    const data = await response.json();
    
    if (!response.ok) {
      // Traiter l'erreur selon le code
      switch (data.error.code) {
        case 'INSUFFICIENT_CREDITS':
          alert('Crédits insuffisants. Veuillez recharger votre compte.');
          break;
          
        case 'VALIDATION_ERROR':
          // Afficher les erreurs de validation
          Object.entries(data.error.details).forEach(([field, message]) => {
            console.error(`${field}: ${message}`);
          });
          break;
          
        case 'RATE_LIMIT_EXCEEDED':
          // Attendre et réessayer
          const retryAfter = data.error.details.retry_after;
          console.log(`Rate limited. Retrying in ${retryAfter} seconds...`);
          setTimeout(() => addCandidates(campaignId, candidates), retryAfter * 1000);
          return;
          
        default:
          throw new Error(data.error.message);
      }
    }
    
    return data;
    
  } catch (error) {
    if (error instanceof TypeError) {
      // Erreur réseau
      console.error('Network error:', error.message);
    } else {
      // Autres erreurs
      console.error('Error:', error.message);
    }
    throw error;
  }
}

Stratégie de retry

import time
from functools import wraps

def retry_on_rate_limit(max_retries=3):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except RateLimitError as e:
                    if attempt == max_retries - 1:
                        raise
                    
                    wait_time = e.retry_after or (2 ** attempt)
                    print(f"Rate limited. Waiting {wait_time} seconds...")
                    time.sleep(wait_time)
            
        return wrapper
    return decorator

@retry_on_rate_limit()
def get_campaign_status(campaign_id):
    # Votre code API ici
    pass

Erreurs par endpoint

POST /api/v1/campaigns/create

Code d’erreurDescriptionSolution
VALIDATION_ERRORChamps requis manquantsFournir tous les champs obligatoires
INSUFFICIENT_CREDITSPas assez de créditsRecharger le compte
INVALID_CONTRACT_TYPEType de contrat invalideUtiliser: CDI, CDD, Stage, etc.

POST /api/v1/campaigns//candidates

Code d’erreurDescriptionSolution
CAMPAIGN_NOT_FOUNDCampagne inexistanteVérifier l’ID de campagne
INVALID_PHONE_NUMBERFormat de téléphone invalideUtiliser format français
TOO_MANY_CANDIDATESPlus de 100 candidatsDiviser en plusieurs requêtes
DUPLICATE_CANDIDATECandidat déjà existantIgnorer ou mettre à jour

Conseils de débogage

  1. Loggez toujours les réponses d’erreur complètes pour avoir tous les détails
  2. Vérifiez les headers de réponse pour des informations supplémentaires
  3. Utilisez un outil comme Postman pour tester vos requêtes isolément
  4. Activez les logs détaillés dans votre client HTTP
  5. Contactez le support avec l’ID de requête pour les erreurs 500