Responseformaten

Begrip van API-responsstructuren

Leer over mindzieAPI-responsformaten, statuscodes, foutafhandelingspatronen en datastructuren om robuuste integraties te bouwen.

Standaardresponseformaat

Alle mindzieAPI-responses volgen een consistente JSON-indeling met voorspelbare structuren:

Succesvolle respons

{
  "data": {
    // Primaire responsgegevens
  },
  "metadata": {
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345",
    "version": "1.0.0"
  },
  "pagination": {
    // Aanwezig bij gepagineerde responses
    "currentPage": 1,
    "totalPages": 5,
    "totalItems": 100,
    "itemsPerPage": 20,
    "hasNext": true,
    "hasPrevious": false
  }
}

Foutrespons

{
  "error": {
    "code": "validation_failed",
    "message": "Request validation failed",
    "details": {
      "field": "datasetId",
      "reason": "Invalid GUID format"
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Responstypen

Succesvolle responses

HTTP 2xx-statuscodes met gestructureerde JSON-gegevens en metadata.

Foutresponses

HTTP 4xx/5xx-statuscodes met gedetailleerde foutinformatie.

Paginering

Consistent pagineringsformaat voor responses met grote datasets.

HTTP-statuscodes

Succescodes (2xx)

Code Status Beschrijving Gebruik
200 OK Verzoek succesvol, data geretourneerd GET-verzoeken, succesvolle bewerkingen
201 Created Resource succesvol aangemaakt POST-verzoeken die nieuwe resources creëren
202 Accepted Verzoek geaccepteerd voor asynchrone verwerking Langdurige bewerkingen, in wachtrij geplaatste taken
204 No Content Verzoek succesvol, geen data geretourneerd DELETE-verzoeken, updates zonder retourdata

Clientfoutcodes (4xx)

Code Status Beschrijving Veelvoorkomende oorzaken
400 Bad Request Ongeldig verzoekformaat of parameters Ontbrekende headers, ongeldige JSON, verkeerd gevormde data
401 Unauthorized Authenticatie vereist of mislukt Ontbrekende/ongeldige token, verlopen credentials
403 Forbidden Geldige authenticatie maar onvoldoende rechten Beperkte gebruikersrechten, verkeerde tenant/project
404 Not Found Gevraagde resource bestaat niet Ongeldig endpoint, niet-bestaand resource-ID
422 Unprocessable Entity Geldig formaat maar zakelijke validatie mislukt Ongeldige zakelijke regels, constraint-violaties
429 Too Many Requests Rate limit overschreden Te veel API-aanroepen binnen tijdsvenster

Serverfoutcodes (5xx)

Code Status Beschrijving Actie
500 Internal Server Error Onverwachte serverfout Opnieuw proberen met exponentiële backoff
502 Bad Gateway Fout bij upstream service Controleer servicestatus, probeer later opnieuw
503 Service Unavailable Service tijdelijk niet beschikbaar Probeer na vertraging opnieuw, controleer onderhoud
504 Gateway Timeout Verzoekstime-out Verhoog time-out, optimaliseer verzoek

Veelvoorkomende responspatronen

Respons met één resource

{
  "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
  }
}

Collectie-response met paginering

{
  "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"
    }
  }
}

Asynchrone operatie-response

{
  "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": "Processing dataset analysis..."
}

Foutresponsdetails

Validatiefout

{
  "error": {
    "code": "validation_failed",
    "message": "Request validation failed",
    "details": {
      "errors": [
        {
          "field": "datasetId",
          "code": "invalid_format",
          "message": "Must be a valid GUID"
        },
        {
          "field": "parameters.timeout",
          "code": "out_of_range",
          "message": "Must be between 1 and 3600 seconds"
        }
      ]
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Authenticatiefout

{
  "error": {
    "code": "invalid_token",
    "message": "The provided access token is invalid or expired",
    "details": {
      "tokenType": "bearer",
      "expiresAt": "2024-01-15T09:00:00Z",
      "suggestion": "Please refresh your access token"
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Rate-limiting fout

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded for this endpoint",
    "details": {
      "limit": 100,
      "remaining": 0,
      "resetTime": "2024-01-15T11:00:00Z",
      "retryAfter": 1800
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Response-headers

Standaardheaders

Header Beschrijving Voorbeeld
Content-Type Responseformaat application/json; charset=utf-8
X-Request-Id Unieke verzoekidentificatie req_12345678
X-Response-Time Verwerkingstijd server 145ms
X-API-Version Gebruikte API-versie 1.0.0

Rate-limiting headers

Header Beschrijving Voorbeeld
X-RateLimit-Limit Maximale verzoeken per venster 100
X-RateLimit-Remaining Resterende verzoeken in venster 95
X-RateLimit-Reset Timestamp vensterreset 1642251600
Retry-After Seconden wachten vóór nieuwe poging 3600

Beste praktijken voor foutafhandeling

JavaScript-voorbeeld

async function handleAPIResponse(response) {
  // Controleer of response ok is
  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('Authentication failed');
      case 403:
        throw new AuthorizationError('Insufficient permissions');
      case 404:
        throw new NotFoundError('Resource not found');
      case 429:
        const retryAfter = response.headers.get('Retry-After');
        throw new RateLimitError(`Rate limited. Retry after ${retryAfter} seconds`);
      case 500:
      case 502:
      case 503:
      case 504:
        throw new ServerError('Server error occurred. Please retry.');
      default:
        throw new APIError(`Unexpected error: ${response.status}`);
    }
  }

  return await response.json();
}

// Gebruik met retry-logica
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; // Exponentiële backoff
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }

      throw error;
    }
  }
}

Python-voorbeeld

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]:
    """Verwerk API-response met correcte foutafhandeling"""

    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"Rate limited. Retry after {retry_after} seconds",
                      response.status_code, details)

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

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

    raise APIError(f"Unexpected error: {message}", response.status_code, details)

def api_call_with_retry(url: str, method: str = 'GET', max_retries: int = 3, **kwargs) -> Dict[str, Any]:
    """Voer API-aanroep uit met automatische retry-logica"""

    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  # Exponentiële backoff
                time.sleep(delay)
                continue

            raise

    raise APIError(f"Max retries ({max_retries}) exceeded")

Volgende stappen

Nu je de responseformaten begrijpt, verken je specifieke API-secties zoals Actions, Blocks of Datasets om deze patronen in actie te zien.