Antwortformate
Verstehen der API-Antwortstrukturen
Erfahren Sie mehr über mindzieAPI-Antwortformate, Statuscodes, Fehlerbehandlungsmuster und Datenstrukturen, um robuste Integrationen zu entwickeln.
Standard-Antwortformat
Alle mindzieAPI-Antworten 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
}
}
Fehlerhafte Antwort
{
"error": {
"code": "validation_failed",
"message": "Anfragevalidierung fehlgeschlagen",
"details": {
"field": "datasetId",
"reason": "Ungültiges 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 Erstellung neuer Ressourcen |
202 |
Accepted | Anfrage zur asynchronen Verarbeitung akzeptiert | Lang andauernde Operationen, Warteschlangen-Aufgaben |
204 |
No Content | Anfrage erfolgreich, keine Daten zurückgegeben | DELETE-Anfragen, Updates ohne Rückgabedaten |
Client-Fehlercodes (4xx)
| Code | Status | Beschreibung | Häufige Ursachen |
|---|---|---|---|
400 |
Bad Request | Ungültiges Anforderungsformat 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 existierende 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 | Höchstgrenze für Anfragen überschritten | Zu viele API-Aufrufe innerhalb eines Zeitfensters |
Server-Fehlercodes (5xx)
| Code | Status | Beschreibung | Maßnahme |
|---|---|---|---|
500 |
Internal Server Error | Unerwarteter Serverfehler | Erneut mit exponentiellem Backoff versuchen |
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 der Anfrage | Timeout erhöhen, Anfrage optimieren |
Häufige Antwortmuster
Einzelne Ressource 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"
}
}
}
Antwort für asynchrone Operation
{
"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": "Verarbeitung der Datensatzanalyse..."
}
Fehlerantwortdetails
Validierungsfehler
{
"error": {
"code": "validation_failed",
"message": "Anfragevalidierung fehlgeschlagen",
"details": {
"errors": [
{
"field": "datasetId",
"code": "invalid_format",
"message": "Muss ein gültiger GUID sein"
},
{
"field": "parameters.timeout",
"code": "out_of_range",
"message": "Muss zwischen 1 und 3600 Sekunden liegen"
}
]
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345"
}
}
Authentifizierungsfehler
{
"error": {
"code": "invalid_token",
"message": "Der bereitgestellte Zugriffstoken ist ungültig oder abgelaufen",
"details": {
"tokenType": "bearer",
"expiresAt": "2024-01-15T09:00:00Z",
"suggestion": "Bitte aktualisieren Sie Ihren Zugriffstoken"
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345"
}
}
Fehler bei der Ratenbegrenzung
{
"error": {
"code": "rate_limit_exceeded",
"message": "Ratenlimit für diesen Endpunkt überschritten",
"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 Anfragekennung | req_12345678 |
X-Response-Time |
Server-Verarbeitungszeit | 145ms |
X-API-Version |
Verwendete API-Version | 1.0.0 |
Rate-Limiting-Header
| Header | Beschreibung | Beispiel |
|---|---|---|
X-RateLimit-Limit |
Maximale Anfragen pro Zeitfenster | 100 |
X-RateLimit-Remaining |
Verbleibende Anfragen im Zeitfenster | 95 |
X-RateLimit-Reset |
Zeitstempel des Fenster-Resets | 1642251600 |
Retry-After |
Sekunden bis zum erneuten Versuch | 3600 |
Empfehlungen zur Fehlerbehandlung
JavaScript-Beispiel
async function handleAPIResponse(response) {
// Prüfen, ob die 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('Authentifizierung fehlgeschlagen');
case 403:
throw new AuthorizationError('Unzureichende Berechtigungen');
case 404:
throw new NotFoundError('Ressource nicht gefunden');
case 429:
const retryAfter = response.headers.get('Retry-After');
throw new RateLimitError(`Ratenlimit erreicht. Erneut versuchen nach ${retryAfter} Sekunden`);
case 500:
case 502:
case 503:
case 504:
throw new ServerError('Serverfehler aufgetreten. Bitte erneut versuchen.');
default:
throw new APIError(`Unerwarteter Fehler: ${response.status}`);
}
}
return await response.json();
}
// Nutzung 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]:
"""Handhabt API-Antwort mit entsprechender Fehlerbehandlung"""
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"Ratenlimit erreicht. Erneut versuchen nach {retry_after} Sekunden",
response.status_code, details)
elif response.status_code >= 500:
raise APIError(f"Serverfehler: {message}", response.status_code, details)
elif response.status_code >= 400:
raise APIError(f"Client-Fehler: {message}", response.status_code, details)
raise APIError(f"Unerwarteter Fehler: {message}", response.status_code, details)
def api_call_with_retry(url: str, method: str = 'GET', max_retries: int = 3, **kwargs) -> Dict[str, Any]:
"""Führt API-Aufruf mit automatischer Retry-Logik aus"""
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"Maximale Anzahl von Versuchen ({max_retries}) überschritten")
Nächste Schritte
Jetzt, wo Sie die Antwortformate verstehen, erkunden Sie spezifische API-Bereiche wie Actions, Blocks oder Datasets, um diese Muster in Aktion zu sehen.