Responseformaten

Inzicht in API-responstructuren

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

Standaard Responseformaat

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

Succesvolle Response

{
  "data": {
    // Primaire responsdata
  },
  "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
  }
}

Foutresponse

{
  "error": {
    "code": "validation_failed",
    "message": "Verificatie van de aanvraag mislukt",
    "details": {
      "field": "datasetId",
      "reason": "Ongeldig GUID-formaat"
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Responstypen

Succesvolle Responses

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

Foutresponses

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

Paginering

Consistent pagineringsformaat voor antwoorden op grote datasets.

HTTP Statuscodes

Succes Codes (2xx)

Code Status Beschrijving Gebruik
200 OK Verzoek succesvol, data geretourneerd GET-verzoeken, succesvolle operaties
201 Created Bron succesvol aangemaakt POST-verzoeken die nieuwe bronnen aanmaken
202 Accepted Verzoek geaccepteerd voor asynchrone verwerking Langdurige operaties, wachtrijtaken
204 No Content Verzoek succesvol, geen data geretourneerd DELETE-verzoeken, updates zonder retourdata

Clientfout Codes (4xx)

Code Status Beschrijving Veelvoorkomende oorzaken
400 Bad Request Ongeldig aanvraagformaat of parameters Ontbrekende headers, ongeldige JSON, verkeerd gevormde data
401 Unauthorized Authenticatie vereist of mislukt Ontbrekende/ongeldige token, verlopen inloggegevens
403 Forbidden Geldige authenticatie maar onvoldoende rechten Beperkte gebruikersrechten, verkeerde tenant/project
404 Not Found Opgevraagde bron bestaat niet Ongeldig eindpunt, niet-bestaande resource-ID
422 Unprocessable Entity Geldig formaat maar businesslogica validatie mislukt Ongeldige bedrijfsregels, schendingen van beperkingen
429 Too Many Requests Toegangslimiet overschreden Te veel API-aanroepen in een tijdsvenster

Serverfout Codes (5xx)

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

Veelvoorkomende Responsepatronen

Response van één bron

{
  "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": "Verwerking datasetanalyse..."
}

Details van Foutresponses

Validatiefout

{
  "error": {
    "code": "validation_failed",
    "message": "Verificatie van de aanvraag mislukt",
    "details": {
      "errors": [
        {
          "field": "datasetId",
          "code": "invalid_format",
          "message": "Moet een geldig GUID zijn"
        },
        {
          "field": "parameters.timeout",
          "code": "out_of_range",
          "message": "Moet tussen 1 en 3600 seconden zijn"
        }
      ]
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Authenticatiefout

{
  "error": {
    "code": "invalid_token",
    "message": "De opgegeven toegangstoken is ongeldig of verlopen",
    "details": {
      "tokenType": "bearer",
      "expiresAt": "2024-01-15T09:00:00Z",
      "suggestion": "Ververs uw toegangstoken alstublieft"
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345"
  }
}

Rate Limiting Fout

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit overschreden voor dit eindpunt",
    "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 verzoek-ID req_12345678
X-Response-Time Server verwerkingstijd 145ms
X-API-Version Gebruikte API-versie 1.0.0

Rate Limiting Headers

Header Beschrijving Voorbeeld
X-RateLimit-Limit Maximaal aantal verzoeken per venster 100
X-RateLimit-Remaining Resterende verzoeken in venster 95
X-RateLimit-Reset Timestamp wanneer venster reset 1642251600
Retry-After Seconden te wachten voor opnieuw proberen 3600

Best Practices 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('Authenticatie mislukt');
      case 403:
        throw new AuthorizationError('Onvoldoende rechten');
      case 404:
        throw new NotFoundError('Bron niet gevonden');
      case 429:
        const retryAfter = response.headers.get('Retry-After');
        throw new RateLimitError(`Rate limit bereikt. Probeer opnieuw over ${retryAfter} seconden`);
      case 500:
      case 502:
      case 503:
      case 504:
        throw new ServerError('Er is een serverfout opgetreden. Probeer opnieuw.');
      default:
        throw new APIError(`Onverwachte fout: ${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 limit bereikt. Probeer opnieuw over {retry_after} seconden",
                      response.status_code, details)

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

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

    raise APIError(f"Onverwachte fout: {message}", response.status_code, details)

def api_call_with_retry(url: str, method: str = 'GET', max_retries: int = 3, **kwargs) -> Dict[str, Any]:
    """Maak API-aanroep 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"Maximaal aantal retries ({max_retries}) overschreden")

API Data Transfer Objecten (DTO's)

Hieronder staan de belangrijkste DTO's die gebruikt worden in mindzieAPI-eindpunten.

Tenant DTO's

TenantListItemDto

{
  "tenantId": "12345678-1234-1234-1234-123456789012",
  "name": "acme-corp",
  "displayName": "Acme Corporation",
  "description": "Hoofdtenant",
  "caseCount": 50000,
  "maxUserCount": 100,
  "maxAnalystCount": 20,
  "analystCount": 12,
  "userCount": 45,
  "preRelease": false,
  "isAcademic": false,
  "autoload": true,
  "dateCreated": "2024-01-15T10:30:00Z",
  "isDisabled": false
}

TenantDetailDto

{
  "tenantId": "12345678-1234-1234-1234-123456789012",
  "name": "acme-corp",
  "displayName": "Acme Corporation",
  "description": "Hoofdtenant",
  "isAcademic": false,
  "preRelease": false,
  "maxUserCount": 100,
  "maxAnalystCount": 20,
  "maxCases": 100000,
  "dateCreated": "2024-01-15T10:30:00Z",
  "isDisabled": false
}

TenantUpdatedDto

{
  "tenantId": "12345678-1234-1234-1234-123456789012",
  "name": "acme-corp",
  "displayName": "Acme Corporation Bijgewerkt",
  "message": "Tenant 'acme-corp' succesvol bijgewerkt",
  "isDisabled": false
}

User DTO's

UserListItemDto

{
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "john.smith@example.com",
  "displayName": "John Smith",
  "firstName": "John",
  "lastName": "Smith",
  "roleName": "Analist",
  "disabled": false,
  "isServiceAccount": false,
  "homeTenantId": null,
  "homeTenantName": null,
  "lastLogin": "2024-01-15T10:30:00Z",
  "tenantCount": 2,
  "tenantNames": "acme-corp, globex-inc",
  "dateCreated": "2024-01-01T00:00:00Z"
}

UserCreatedDto

{
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "john.smith@example.com",
  "displayName": "John Smith",
  "message": "Gebruiker succesvol aangemaakt"
}

Project DTO's

ProjectReturn

{
  "projectId": "87654321-4321-4321-4321-210987654321",
  "tenantId": "12345678-1234-1234-1234-123456789012",
  "projectName": "Analyse van inkooporders",
  "projectDescription": "Process mining analyse van P2P workflow",
  "dateCreated": "2024-01-15T10:30:00Z",
  "dateModified": "2024-01-20T14:45:00Z",
  "createdBy": "user-guid",
  "modifiedBy": "user-guid",
  "isActive": true,
  "datasetCount": 3,
  "investigationCount": 5,
  "dashboardCount": 2,
  "userCount": 8
}

ProjectSummaryReturn

{
  "projectId": "87654321-4321-4321-4321-210987654321",
  "projectName": "Analyse van inkooporders",
  "projectDescription": "Process mining analyse",
  "dateCreated": "2024-01-15T10:30:00Z",
  "dateModified": "2024-01-20T14:45:00Z",
  "statistics": {
    "totalDatasets": 3,
    "totalInvestigations": 5,
    "totalDashboards": 2,
    "totalNotebooks": 12,
    "totalUsers": 8
  }
}

ProjectUserReturn

{
  "permissionId": "11111111-1111-1111-1111-111111111111",
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "john.smith@example.com",
  "displayName": "John Smith",
  "isOwner": true,
  "dateAssigned": "2024-01-15T10:30:00Z"
}

ProjectThumbnailReturn

{
  "projectId": "87654321-4321-4321-4321-210987654321",
  "hasThumbnail": true,
  "base64Image": "data:image/jpeg;base64,/9j/4AAQ..."
}

ProjectImportReturn

{
  "success": true,
  "projectId": "99999999-9999-9999-9999-999999999999",
  "projectName": "Geïmporteerd Project",
  "datasetsImported": 2,
  "investigationsImported": 3,
  "dashboardsImported": 1,
  "errorMessage": null,
  "message": "Project succesvol geïmporteerd"
}

Investigation DTO's

InvestigationReturn

{
  "investigationId": "11111111-2222-3333-4444-555555555555",
  "projectId": "87654321-4321-4321-4321-210987654321",
  "investigationName": "Order Analyse",
  "investigationDescription": "Process mining analyse van orderworkflow",
  "datasetId": "12345678-1234-1234-1234-123456789012",
  "dateCreated": "2024-01-15T10:30:00Z",
  "dateModified": "2024-01-20T14:45:00Z",
  "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "modifiedBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "investigationOrder": 1.0,
  "isUsedForOperationCenter": false,
  "investigationFolderId": null,
  "notebookCount": 3
}

InvestigationListReturn

{
  "investigations": [
    {
      "investigationId": "11111111-2222-3333-4444-555555555555",
      "projectId": "87654321-4321-4321-4321-210987654321",
      "investigationName": "Order Analyse",
      "datasetId": "12345678-1234-1234-1234-123456789012",
      "notebookCount": 3
    }
  ],
  "totalCount": 5,
  "page": 1,
  "pageSize": 50
}

CreateInvestigationRequest

{
  "investigationName": "Order Analyse",
  "investigationDescription": "Process mining analyse",
  "datasetId": "12345678-1234-1234-1234-123456789012",
  "isUsedForOperationCenter": false
}

UpdateInvestigationRequest

{
  "investigationName": "Bijgewerkte Analyse Naam",
  "investigationDescription": "Bijgewerkte beschrijving",
  "isUsedForOperationCenter": true
}

Notebook DTO's

NotebookReturn

{
  "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "investigationId": "11111111-2222-3333-4444-555555555555",
  "name": "Hoofd",
  "description": "Primaire analyse-notebook",
  "dateCreated": "2024-01-15T10:30:00Z",
  "dateModified": "2024-01-20T14:45:00Z",
  "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "modifiedBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "notebookType": 0,
  "notebookOrder": 1.0,
  "lastExecutionDuration": 2.5,
  "blockCount": 12
}

NotebookListReturn

{
  "notebooks": [
    {
      "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
      "investigationId": "11111111-2222-3333-4444-555555555555",
      "name": "Hoofd",
      "notebookOrder": 1.0,
      "blockCount": 12
    }
  ],
  "totalCount": 3
}

Volgende Stappen

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