Antwortformate

Verständnis der API-Antwortstrukturen

Erfahren Sie mehr über die Antwortformate von mindzieAPI, Statuscodes, Fehlerbehandlungsmuster und Datenstrukturen, um robuste Integrationen zu erstellen.

Standard-Antwortformat

Alle Antworten von mindzieAPI folgen einem konsistenten JSON-Format mit vorhersehbaren Strukturen:

Erfolgreiche Antwort

{
  "data": {
    // Primäre Antwortdaten
  },
  "metadata": {
    "timestamp": "2024-01-15T10:30:00Z",
    "requestId": "req_12345",
    "version": "1.0.0"
  },
  "pagination": {
    // Vorhanden bei paginierten Antworten
    "currentPage": 1,
    "totalPages": 5,
    "totalItems": 100,
    "itemsPerPage": 20,
    "hasNext": true,
    "hasPrevious": false
  }
}

Fehlerantwort

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

Antworttypen

Erfolgsantworten

HTTP 2xx-Statuscodes mit strukturierten JSON-Daten und Metadaten.

Fehlerantworten

HTTP 4xx/5xx-Statuscodes mit detaillierten Fehlerinformationen.

Paginierung

Konsistentes Paginierungsformat für Antworten mit großen Datensätzen.

HTTP-Statuscodes

Erfolgs-Codes (2xx)

Code Status Beschreibung Verwendung
200 OK Anfrage erfolgreich, Daten zurückgegeben GET-Anfragen, erfolgreiche Operationen
201 Created Ressource erfolgreich erstellt POST-Anfragen zur Ressourcenerstellung
202 Accepted Anfrage für asynchrone Verarbeitung akzeptiert Langlaufende Vorgänge, eingereihte Aufgaben
204 No Content Anfrage erfolgreich, keine Daten zurückgegeben DELETE-Anfragen, Updates ohne Rückgabedaten

Client-Fehler-Codes (4xx)

Code Status Beschreibung Häufige Ursachen
400 Bad Request Ungültiges Anfrageformat oder Parameter Fehlende Header, ungültiges JSON, fehlerhafte Daten
401 Unauthorized Authentifizierung erforderlich oder fehlgeschlagen Fehlendes/ungültiges Token, abgelaufene Zugangsdaten
403 Forbidden Gültige Authentifizierung, aber unzureichende Berechtigungen Eingeschränkter Benutzerzugang, falscher Mandant/Projekt
404 Not Found Angeforderte Ressource existiert nicht Ungültiger Endpunkt, nicht existente Ressourcen-ID
422 Unprocessable Entity Gültiges Format, aber Validierung der Geschäftslogik fehlgeschlagen Ungültige Geschäftsregeln, Verletzung von Einschränkungen
429 Too Many Requests Rate-Limit überschritten Zu viele API-Aufrufe innerhalb eines Zeitfensters

Server-Fehler-Codes (5xx)

Code Status Beschreibung Aktion
500 Internal Server Error Unerwarteter Serverfehler Erneut versuchen mit exponentiellem Backoff
502 Bad Gateway Fehler im vorgelagerten Dienst Dienststatus prüfen, später erneut versuchen
503 Service Unavailable Dienst vorübergehend nicht verfügbar Nach Verzögerung erneut versuchen, Wartung prüfen
504 Gateway Timeout Zeitüberschreitung bei Anfrage Timeout erhöhen, Anfrage optimieren

Häufige Antwortmuster

Einzelressourcen-Antwort

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

Sammlung-Antwort mit Paginierung

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

Async-Operations-Antwort

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

Details zur Fehlerantwort

Validierungsfehler

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

Authentifizierungsfehler

{
  "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-Limit-Fehler

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

Antwort-Header

Standard-Header

Header Beschreibung Beispiel
Content-Type Antwortformat application/json; charset=utf-8
X-Request-Id Eindeutige Anfrage-ID req_12345678
X-Response-Time Server-Verarbeitungszeit 145ms
X-API-Version Verwendete API-Version 1.0.0

Rate-Limit-Header

Header Beschreibung Beispiel
X-RateLimit-Limit Maximale Anfragen pro Zeitfenster 100
X-RateLimit-Remaining Verbleibende Anfragen im Fenster 95
X-RateLimit-Reset Zeitstempel für Fensterzurücksetzung 1642251600
Retry-After Sekunden bis zum erneuten Versuch 3600

Best Practices für Fehlerbehandlung

JavaScript-Beispiel

async function handleAPIResponse(response) {
  // Prüfen, ob Antwort ok ist
  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();
}

// Verwendung mit Retry-Logik
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; // Exponentieller Backoff
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }

      throw error;
    }
  }
}

Python-Beispiel

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]:
    """API-Antwort mit entsprechender Fehlerbehandlung verarbeiten"""

    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]:
    """API-Aufruf mit automatischer Retry-Logik"""

    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  # Exponentieller Backoff
                time.sleep(delay)
                continue

            raise

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

API-Datenübertragungsobjekte (DTOs)

Nachfolgend sind die wichtigsten DTOs aufgeführt, die über die mindzieAPI-Endpunkte verwendet werden.

Tenant-DTOs

TenantListItemDto

{
  "tenantId": "12345678-1234-1234-1234-123456789012",
  "name": "acme-corp",
  "displayName": "Acme Corporation",
  "description": "Main tenant",
  "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": "Main tenant",
  "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 Updated",
  "message": "Tenant 'acme-corp' updated successfully",
  "isDisabled": false
}

User-DTOs

UserListItemDto

{
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "john.smith@example.com",
  "displayName": "John Smith",
  "firstName": "John",
  "lastName": "Smith",
  "roleName": "Analyst",
  "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": "User created successfully"
}

Project-DTOs

ProjectReturn

{
  "projectId": "87654321-4321-4321-4321-210987654321",
  "tenantId": "12345678-1234-1234-1234-123456789012",
  "projectName": "Purchase Order Analysis",
  "projectDescription": "Process mining analysis of 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": "Purchase Order Analysis",
  "projectDescription": "Process mining analysis",
  "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": "Imported Project",
  "datasetsImported": 2,
  "investigationsImported": 3,
  "dashboardsImported": 1,
  "errorMessage": null,
  "message": "Project imported successfully"
}

Investigation-DTOs

InvestigationReturn

{
  "investigationId": "11111111-2222-3333-4444-555555555555",
  "projectId": "87654321-4321-4321-4321-210987654321",
  "investigationName": "Order Analysis",
  "investigationDescription": "Process mining analysis of order workflow",
  "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 Analysis",
      "datasetId": "12345678-1234-1234-1234-123456789012",
      "notebookCount": 3
    }
  ],
  "totalCount": 5,
  "page": 1,
  "pageSize": 50
}

CreateInvestigationRequest

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

UpdateInvestigationRequest

{
  "investigationName": "Updated Analysis Name",
  "investigationDescription": "Updated description",
  "isUsedForOperationCenter": true
}

Notebook-DTOs

NotebookReturn

{
  "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "investigationId": "11111111-2222-3333-4444-555555555555",
  "name": "Main",
  "description": "Primary analysis 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": "Main",
      "notebookOrder": 1.0,
      "blockCount": 12
    }
  ],
  "totalCount": 3
}

Nächste Schritte

Nachdem Sie die Antwortformate verstanden haben, erkunden Sie spezifische API-Bereiche wie Actions, Blocks oder Datasets, um diese Muster in der Praxis zu sehen.