Formats de Réponse

Comprendre les Structures de Réponse de l’API

Découvrez les formats de réponse mindzieAPI, les codes de statut, les modèles de gestion des erreurs et les structures de données pour construire des intégrations robustes.

Format de Réponse Standard

Toutes les réponses mindzieAPI suivent un format JSON cohérent avec des structures prévisibles :

Réponse Réussie

{
  "data": {
    // Données principales de la réponse
  },
  "metadata": {
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345",
    "version": "1.0.0"
  },
  "pagination": {
    // Présent pour les réponses paginées
    "currentPage": 1,
    "totalPages": 5,
    "totalItems": 100,
    "itemsPerPage": 20,
    "hasNext": true,
    "hasPrevious": false
  }
}

Réponse d’Erreur

{
  "error": {
    "code": "validation_failed",
    "message": "Échec de la validation de la requête",
    "details": {
      "field": "datasetId",
      "reason": "Format GUID invalide"
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Types de Réponses

Réponses Réussies

Codes de statut HTTP 2xx avec données JSON structurées et métadonnées.

Réponses d’Erreur

Codes de statut HTTP 4xx/5xx avec informations détaillées sur l’erreur.

Pagination

Format de pagination cohérent pour les réponses avec grands ensembles de données.

Codes de Statut HTTP

Codes de Succès (2xx)

Code Statut Description Usage
200 OK Requête réussie, données retournées Requêtes GET, opérations réussies
201 Créé Ressource créée avec succès Requêtes POST créant de nouvelles ressources
202 Accepté Requête acceptée pour traitement asynchrone Opérations longues, tâches en file d’attente
204 Pas de Contenu Requête réussie, pas de données retournées Requêtes DELETE, mises à jour sans données retournées

Codes d’Erreur Client (4xx)

Code Statut Description Causes Courantes
400 Mauvaise Requête Format ou paramètres de requête invalides En-têtes manquants, JSON invalide, données mal formées
401 Non Autorisé Authentification requise ou échouée Token manquant/invalide, identifiants expirés
403 Interdit Authentification valide mais permissions insuffisantes Accès utilisateur limité, mauvais tenant/projet
404 Non Trouvé Ressource demandée inexistante Point d’accès invalide, ID de ressource inexistant
422 Entité Non Traitée Format valide mais validation de logique métier échouée Règles métier invalides, violations de contraintes
429 Trop de Requêtes Limite de taux dépassée Trop d’appels API dans la fenêtre temporelle

Codes d’Erreur Serveur (5xx)

Code Statut Description Action
500 Erreur Interne Serveur Erreur serveur inattendue Réessayer avec backoff exponentiel
502 Mauvaise Passerelle Erreur du service en amont Vérifier le statut du service, réessayer plus tard
503 Service Indisponible Service temporairement indisponible Réessayer après délai, vérifier maintenance
504 Délai Passerelle Expiré Délai d’attente de la requête dépassé Augmenter le timeout, optimiser la requête

Modèles Courants de Réponse

Réponse d’une Ressource Unique

{
  "actionId": "87654321-4321-4321-4321-210987654321",
  "actionType": "analyze",
  "status": "completed",
  "startTime": "2024-01-15T10:30:00Z",
  "endTime": "2024-01-15T10:32:15Z",
  "duration": 135,
  "result": {
    "outputId": "98765432-8765-4321-4321-987654321098",
    "recordsProcessed": 10000
  }
}

Réponse de Collection avec Pagination

{
  "actions": [
    {
      "actionId": "87654321-4321-4321-4321-210987654321",
      "actionType": "analyze",
      "status": "completed"
    },
    {
      "actionId": "11111111-2222-3333-4444-555555555555",
      "actionType": "export",
      "status": "processing"
    }
  ],
  "pagination": {
    "currentPage": 1,
    "totalPages": 5,
    "totalItems": 100,
    "itemsPerPage": 20,
    "hasNext": true,
    "hasPrevious": false,
    "links": {
      "first": "/api/Action/history?page=1&limit=20",
      "next": "/api/Action/history?page=2&limit=20",
      "last": "/api/Action/history?page=5&limit=20"
    }
  }
}

Réponse d’Opération Asynchrone

{
  "operationId": "op_12345678-1234-1234-1234-123456789012",
  "status": "processing",
  "progress": {
    "percentage": 45,
    "currentStep": "data_analysis",
    "totalSteps": 5,
    "estimatedCompletion": "2024-01-15T10:35:00Z"
  },
  "trackingUrl": "/api/Execution/status/op_12345678-1234-1234-1234-123456789012",
  "message": "Analyse du jeu de données en cours..."
}

Détails des Réponses d’Erreur

Erreur de Validation

{
  "error": {
    "code": "validation_failed",
    "message": "Échec de la validation de la requête",
    "details": {
      "errors": [
        {
          "field": "datasetId",
          "code": "invalid_format",
          "message": "Doit être un GUID valide"
        },
        {
          "field": "parameters.timeout",
          "code": "out_of_range",
          "message": "Doit être compris entre 1 et 3600 secondes"
        }
      ]
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Erreur d’Authentification

{
  "error": {
    "code": "invalid_token",
    "message": "Le token d’accès fourni est invalide ou expiré",
    "details": {
      "tokenType": "bearer",
      "expiresAt": "2024-01-15T09:00:00Z",
      "suggestion": "Veuillez rafraîchir votre token d’accès"
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Erreur de Limitation de Taux

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Limite de taux dépassée pour ce point d’accès",
    "details": {
      "limit": 100,
      "remaining": 0,
      "resetTime": "2024-01-15T11:00:00Z",
      "retryAfter": 1800
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

En-têtes de Réponse

En-têtes Standards

En-tête Description Exemple
Content-Type Format de la réponse application/json; charset=utf-8
X-Request-Id Identifiant unique de la requête req_12345678
X-Response-Time Temps de traitement serveur 145ms
X-API-Version Version de l’API utilisée 1.0.0

En-têtes de Limitation de Taux

En-tête Description Exemple
X-RateLimit-Limit Nombre maximal de requêtes par fenêtre 100
X-RateLimit-Remaining Requêtes restantes dans la fenêtre 95
X-RateLimit-Reset Heure de réinitialisation de la fenêtre 1642251600
Retry-After Secondes à attendre avant de réessayer 3600

Bonnes Pratiques pour la Gestion des Erreurs

Exemple JavaScript

async function handleAPIResponse(response) {
  // Vérifie si la réponse est correcte
  if (!response.ok) {
    const errorData = await response.json();

    switch (response.status) {
      case 400:
        throw new ValidationError(errorData.error.message, errorData.error.details);
      case 401:
        throw new AuthenticationError('Échec d’authentification');
      case 403:
        throw new AuthorizationError('Permissions insuffisantes');
      case 404:
        throw new NotFoundError('Ressource non trouvée');
      case 429:
        const retryAfter = response.headers.get('Retry-After');
        throw new RateLimitError(`Limite de taux atteinte. Réessayer après ${retryAfter} secondes`);
      case 500:
      case 502:
      case 503:
      case 504:
        throw new ServerError('Erreur serveur survenue. Veuillez réessayer.');
      default:
        throw new APIError(`Erreur inattendue : ${response.status}`);
    }
  }

  return await response.json();
}

// Utilisation avec logique de retry
async function apiCallWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      return await handleAPIResponse(response);
    } catch (error) {
      if (error instanceof RateLimitError) {
        const retryAfter = parseInt(error.retryAfter) || Math.pow(2, attempt);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }

      if (error instanceof ServerError && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000; // Backoff exponentiel
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }

      throw error;
    }
  }
}

Exemple Python

import requests
import time
from typing import Dict, Any

class APIError(Exception):
    def __init__(self, message: str, status_code: int = None, details: Dict = None):
        super().__init__(message)
        self.status_code = status_code
        self.details = details

def handle_api_response(response: requests.Response) -> Dict[str, Any]:
    """Gère la réponse de l’API avec gestion appropriée des erreurs"""

    if response.ok:
        return response.json()

    try:
        error_data = response.json()
    except ValueError:
        error_data = {"error": {"message": response.text}}

    error_info = error_data.get("error", {})
    message = error_info.get("message", f"HTTP {response.status_code}")
    details = error_info.get("details", {})

    if response.status_code == 429:
        retry_after = response.headers.get('Retry-After', '60')
        raise APIError(f"Limite de taux atteinte. Réessayer après {retry_after} secondes",
                      response.status_code, details)

    elif response.status_code >= 500:
        raise APIError(f"Erreur serveur : {message}", response.status_code, details)

    elif response.status_code >= 400:
        raise APIError(f"Erreur client : {message}", response.status_code, details)

    raise APIError(f"Erreur inattendue : {message}", response.status_code, details)

def api_call_with_retry(url: str, method: str = 'GET', max_retries: int = 3, **kwargs) -> Dict[str, Any]:
    """Effectue un appel API avec logique de retry automatique"""

    for attempt in range(1, max_retries + 1):
        try:
            response = requests.request(method, url, **kwargs)
            return handle_api_response(response)

        except APIError as e:
            if e.status_code == 429:
                retry_after = int(e.details.get('retryAfter', 60))
                time.sleep(retry_after)
                continue

            elif e.status_code >= 500 and attempt < max_retries:
                delay = 2 ** attempt  # Backoff exponentiel
                time.sleep(delay)
                continue

            raise

    raise APIError(f"Nombre maximal de retries ({max_retries}) dépassé")

Étapes Suivantes

Maintenant que vous comprenez les formats de réponse, explorez des sections API spécifiques comme Actions, Blocs, ou Jeux de Données pour voir ces modèles en action.