Understanding API Response Structures
Learn about mindzieAPI response formats, status codes, error handling patterns, and data structures to build robust integrations.
Standard Response Format
All mindzieAPI responses follow consistent JSON formatting with predictable structures:
Successful Response
{
"data": {
// Primary response data
},
"metadata": {
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345",
"version": "1.0.0"
},
"pagination": {
// Present for paginated responses
"currentPage": 1,
"totalPages": 5,
"totalItems": 100,
"itemsPerPage": 20,
"hasNext": true,
"hasPrevious": false
}
}
Error Response
{
"error": {
"code": "validation_failed",
"message": "Request validation failed",
"details": {
"field": "datasetId",
"reason": "Invalid GUID format"
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345"
}
}
Response Types
Success Responses
HTTP 2xx status codes with structured JSON data and metadata.
Error Responses
HTTP 4xx/5xx status codes with detailed error information.
Pagination
Consistent pagination format for large dataset responses.
HTTP Status Codes
Success Codes (2xx)
| Code | Status | Description | Usage |
|---|---|---|---|
200 |
OK | Request successful, data returned | GET requests, successful operations |
201 |
Created | Resource successfully created | POST requests creating new resources |
202 |
Accepted | Request accepted for async processing | Long-running operations, queued tasks |
204 |
No Content | Request successful, no data returned | DELETE requests, updates without return data |
Client Error Codes (4xx)
| Code | Status | Description | Common Causes |
|---|---|---|---|
400 |
Bad Request | Invalid request format or parameters | Missing headers, invalid JSON, malformed data |
401 |
Unauthorized | Authentication required or failed | Missing/invalid token, expired credentials |
403 |
Forbidden | Valid auth but insufficient permissions | Limited user access, wrong tenant/project |
404 |
Not Found | Requested resource doesn't exist | Invalid endpoint, non-existent resource ID |
422 |
Unprocessable Entity | Valid format but business logic validation failed | Invalid business rules, constraint violations |
429 |
Too Many Requests | Rate limit exceeded | Too many API calls in time window |
Server Error Codes (5xx)
| Code | Status | Description | Action |
|---|---|---|---|
500 |
Internal Server Error | Unexpected server error | Retry with exponential backoff |
502 |
Bad Gateway | Upstream service error | Check service status, retry later |
503 |
Service Unavailable | Service temporarily unavailable | Retry after delay, check maintenance |
504 |
Gateway Timeout | Request timeout | Increase timeout, optimize request |
Common Response Patterns
Single Resource Response
{
"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
}
}
Collection Response with 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"
}
}
}
Async Operation 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..."
}
Error Response Details
Validation Error
{
"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"
}
}
Authentication Error
{
"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 Error
{
"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
Standard Headers
| Header | Description | Example |
|---|---|---|
Content-Type |
Response format | application/json; charset=utf-8 |
X-Request-Id |
Unique request identifier | req_12345678 |
X-Response-Time |
Server processing time | 145ms |
X-API-Version |
API version used | 1.0.0 |
Rate Limiting Headers
| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit |
Maximum requests per window | 100 |
X-RateLimit-Remaining |
Remaining requests in window | 95 |
X-RateLimit-Reset |
Window reset timestamp | 1642251600 |
Retry-After |
Seconds to wait before retry | 3600 |
Best Practices for Error Handling
JavaScript Example
async function handleAPIResponse(response) {
// Check if response is ok
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();
}
// Usage with retry logic
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; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}
Python Example
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]:
"""Handle API response with proper error handling"""
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]:
"""Make API call with automatic retry logic"""
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 # Exponential backoff
time.sleep(delay)
continue
raise
raise APIError(f"Max retries ({max_retries}) exceeded")
Next Steps
Now that you understand response formats, explore specific API sections like Actions, Blocks, or Datasets to see these patterns in action.