レスポンスフォーマット
APIレスポンス構造の理解
mindzieAPIのレスポンスフォーマット、ステータスコード、エラー処理パターン、およびデータ構造について学び、堅牢な連携を構築するための基礎を理解しましょう。
標準レスポンスフォーマット
すべてのmindzieAPIレスポンスは、一貫したJSON形式で予測可能な構造を持ちます。
成功レスポンス
{
"data": {
// 主なレスポンスデータ
},
"metadata": {
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345",
"version": "1.0.0"
},
"pagination": {
// ページネーションがあるレスポンスの場合に存在
"currentPage": 1,
"totalPages": 5,
"totalItems": 100,
"itemsPerPage": 20,
"hasNext": true,
"hasPrevious": false
}
}
エラーレスポンス
{
"error": {
"code": "validation_failed",
"message": "リクエスト検証に失敗しました",
"details": {
"field": "datasetId",
"reason": "無効なGUID形式です"
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345"
}
}
レスポンスタイプ
成功レスポンス
HTTP 2xxステータスコード、構造化されたJSONデータとメタデータを含みます。
エラーレスポンス
HTTP 4xx/5xxステータスコード、詳細なエラー情報が含まれます。
ページネーション
大きなデータセットレスポンスに対して一貫したページネーション形式を適用しています。
HTTPステータスコード
成功コード (2xx)
| コード | ステータス | 説明 | 用途 |
|---|---|---|---|
200 |
OK | リクエスト成功、データ返却 | GETリクエスト、成功した操作 |
201 |
Created | リソースが正常に作成された | 新規リソース作成のPOSTリクエスト |
202 |
Accepted | リクエストが非同期処理のため受理された | 長時間処理、キューイングされたタスク |
204 |
No Content | リクエスト成功、返却データなし | DELETEリクエスト、返却データなしの更新 |
クライアントエラーコード (4xx)
| コード | ステータス | 説明 | 主な原因 |
|---|---|---|---|
400 |
Bad Request | リクエストの形式またはパラメータが無効 | ヘッダー不足、無効なJSON、不正なデータ形式 |
401 |
Unauthorized | 認証が必要または認証失敗 | トークン欠如/無効、資格情報の期限切れ |
403 |
Forbidden | 有効な認証だが権限不足 | ユーザーアクセス制限、誤ったテナントやプロジェクト |
404 |
Not Found | 指定リソースが存在しない | 無効なエンドポイント、存在しないリソースID |
422 |
Unprocessable Entity | フォーマットは正しいがビジネスロジック検証に失敗 | ビジネスルール違反、制約違反 |
429 |
Too Many Requests | レート制限超過 | 所定時間内のAPIコール過多 |
サーバーエラーコード (5xx)
| コード | ステータス | 説明 | 対応 |
|---|---|---|---|
500 |
Internal Server Error | 予期しないサーバーエラー | 指数的バックオフでリトライ |
502 |
Bad Gateway | 上流サービスのエラー | サービス状態の確認、後で再試行 |
503 |
Service Unavailable | サービス一時的に利用不可 | 遅延後リトライ、メンテナンス確認 |
504 |
Gateway Timeout | リクエストタイムアウト | タイムアウト延長、最適化 |
共通レスポンスパターン
単一リソースレスポンス
{
"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
}
}
ページネーション付きコレクションレスポンス
{
"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"
}
}
}
非同期処理レスポンス
{
"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": "データセット分析を処理中..."
}
エラーレスポンス詳細
バリデーションエラー
{
"error": {
"code": "validation_failed",
"message": "リクエスト検証に失敗しました",
"details": {
"errors": [
{
"field": "datasetId",
"code": "invalid_format",
"message": "有効なGUIDである必要があります"
},
{
"field": "parameters.timeout",
"code": "out_of_range",
"message": "1秒から3600秒の間である必要があります"
}
]
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345"
}
}
認証エラー
{
"error": {
"code": "invalid_token",
"message": "提供されたアクセストークンが無効または期限切れです",
"details": {
"tokenType": "bearer",
"expiresAt": "2024-01-15T09:00:00Z",
"suggestion": "アクセストークンを更新してください"
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345"
}
}
レートリミットエラー
{
"error": {
"code": "rate_limit_exceeded",
"message": "このエンドポイントのレート制限を超えました",
"details": {
"limit": 100,
"remaining": 0,
"resetTime": "2024-01-15T11:00:00Z",
"retryAfter": 1800
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_12345"
}
}
レスポンスヘッダー
標準ヘッダー
| ヘッダー | 説明 | 例 |
|---|---|---|
Content-Type |
レスポンスフォーマット | application/json; charset=utf-8 |
X-Request-Id |
ユニークなリクエスト識別子 | req_12345678 |
X-Response-Time |
サーバー処理時間 | 145ms |
X-API-Version |
利用中のAPIバージョン | 1.0.0 |
レートリミット関連ヘッダー
| ヘッダー | 説明 | 例 |
|---|---|---|
X-RateLimit-Limit |
ウィンドウ内の最大リクエスト数 | 100 |
X-RateLimit-Remaining |
ウィンドウ内の残りリクエスト数 | 95 |
X-RateLimit-Reset |
リセットタイムスタンプ | 1642251600 |
Retry-After |
再試行までの待機秒数 | 3600 |
エラー処理のベストプラクティス
JavaScript例
async function handleAPIResponse(response) {
// レスポンスが正常か確認
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('認証に失敗しました');
case 403:
throw new AuthorizationError('権限が不足しています');
case 404:
throw new NotFoundError('リソースが見つかりません');
case 429:
const retryAfter = response.headers.get('Retry-After');
throw new RateLimitError(`レート制限に達しました。${retryAfter}秒後に再試行してください`);
case 500:
case 502:
case 503:
case 504:
throw new ServerError('サーバーエラーが発生しました。再試行してください。');
default:
throw new APIError(`予期しないエラー: ${response.status}`);
}
}
return await response.json();
}
// リトライロジック付きのAPI呼び出し
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; // 指数的バックオフ
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}
Python例
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レスポンスの処理"""
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"レート制限に達しました。{retry_after}秒後に再試行してください。",
response.status_code, details)
elif response.status_code >= 500:
raise APIError(f"サーバーエラー: {message}", response.status_code, details)
elif response.status_code >= 400:
raise APIError(f"クライアントエラー: {message}", response.status_code, details)
raise APIError(f"予期しないエラー: {message}", response.status_code, details)
def api_call_with_retry(url: str, method: str = 'GET', max_retries: int = 3, **kwargs) -> Dict[str, Any]:
"""自動リトライロジック付きAPI呼び出し"""
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 # 指数的バックオフ
time.sleep(delay)
continue
raise
raise APIError(f"最大リトライ回数({max_retries})に達しました")
APIデータ転送オブジェクト(DTO)
以下は、mindzieAPI各エンドポイントで使用される主要なDTO一覧です。
テナントDTO
TenantListItemDto
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation",
"description": "メインテナント",
"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": "メインテナント",
"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": "テナント 'acme-corp' が正常に更新されました",
"isDisabled": false
}
ユーザーDTO
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": "ユーザーが正常に作成されました"
}
プロジェクトDTO
ProjectReturn
{
"projectId": "87654321-4321-4321-4321-210987654321",
"tenantId": "12345678-1234-1234-1234-123456789012",
"projectName": "Purchase Order Analysis",
"projectDescription": "P2Pワークフローのプロセスマイニング分析",
"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": "プロセスマイニング分析",
"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": "インポートされたプロジェクト",
"datasetsImported": 2,
"investigationsImported": 3,
"dashboardsImported": 1,
"errorMessage": null,
"message": "プロジェクトが正常にインポートされました"
}
調査DTO
InvestigationReturn
{
"investigationId": "11111111-2222-3333-4444-555555555555",
"projectId": "87654321-4321-4321-4321-210987654321",
"investigationName": "Order Analysis",
"investigationDescription": "注文ワークフローのプロセスマイニング分析",
"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": "プロセスマイニング分析",
"datasetId": "12345678-1234-1234-1234-123456789012",
"isUsedForOperationCenter": false
}
UpdateInvestigationRequest
{
"investigationName": "更新された分析名",
"investigationDescription": "更新された説明",
"isUsedForOperationCenter": true
}
ノートブックDTO
NotebookReturn
{
"notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"investigationId": "11111111-2222-3333-4444-555555555555",
"name": "Main",
"description": "主要分析ノートブック",
"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
}
次のステップ
レスポンスフォーマットを理解したら、Actions、Blocks、またはDatasetsなどの特定のAPIセクションを探索し、これらのパターンがどのように実際に適用されているかを確認しましょう。