개요
MAIDEPOT Public API를 사용하면 API 토큰을 사용하여 프로그래밍 방식으로 AI 프롬프트(앱, 이미지 생성, 매쉬업)를 실행할 수 있습니다. 모든 실행은 비동기적으로 실행되며 트랜잭션 엔드포인트를 통해 진행 상황을 추적하거나 웹훅을 통해 알림을 받을 수 있습니다.
주요 기능
- 모든 프롬프트 유형 실행 (앱, 이미지, 매쉬업)
- 상태 추적이 가능한 비동기 실행
- 문서, 이미지, 오디오 및 비디오 파일 업로드 지원
- 완료된 실행에 대한 웹훅 알림
- 트랜잭션 기록에 대한 커서 기반 페이지네이션
- 실패한 트랜잭션 재시도
- 크레딧 사용량 추적
요구사항
- API 액세스에는 유료 플랜(Pro, Business 또는 Enterprise)이 필요합니다
- 적절한 권한이 있는 유효한 API 토큰
인증
모든 API 요청은 헤더에 Bearer 토큰을 사용한 인증이 필요합니다. Authorization
Authorization: Bearer YOUR_API_TOKEN프로필에서 API 토큰을 생성하고 관리할 수 있습니다. API 토큰 관리
예제
curl https://api.maidepot.com/api/v1/prompts \
-H "Authorization: Bearer maid_zzFC7on8-HxX_n-4PvAuTj_8OFvJYdYA3AzI4E57nSQVo2w9M6tF3aTtKp4VJ-bz"속도 제한
속도 제한은 계정당 적용되며 엔드포인트 유형에 따라 다릅니다:
- 실행 엔드포인트: 분당 120개 요청
- 메타데이터 읽기 엔드포인트: 분당 300개 요청
- 폴링 엔드포인트: 분당 600개 요청
- 관리 작업: 분당 180개 요청
- 파일 업로드: 분당 60개 요청
속도 제한 헤더
모든 응답에는 헤더에 속도 제한 정보가 포함됩니다:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-RateLimit-Reset: 1612345678속도 제한 초과 응답 (429)
{
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded",
"code": "rate_limit_exceeded"
}
}오류 처리
모든 API 오류는 RFC 7807 Problem Details 패턴을 기반으로 한 표준화된 구조를 따릅니다.
오류 응답 구조
{
"error": {
"type": "validation_error",
"message": "Human-readable error message",
"code": "invalid_request",
"param": "inputs",
"details": ["Additional context"]
}
}HTTP 상태 코드
| 상태 코드 | 오류 유형 | 설명 |
|---|---|---|
400 | validation_error | Invalid request data or missing required fields |
401 | authentication_error | Invalid or missing API token |
402 | insufficient_credits | Not enough credits to complete operation |
403 | permission_error | Token doesn't have permission for this resource |
404 | not_found | Resource not found (prompt, transaction, etc.) |
415 | unsupported_media_type | Unsupported file format |
429 | rate_limit_error | Rate limit exceeded (requests per minute) |
500 | internal_error | Internal server error |
Note: 402 Insufficient Credits는 계정의 크레딧 할당량이 소진되었을 때 사용되며, 429 Rate Limit는 분당 요청 제한을 초과했을 때 사용됩니다. 둘 다 다른 처리 전략이 필요합니다 (크레딧 추가 vs. 백오프 구현).
오류 예제
400 - 유효성 검사 오류
{
"error": {
"type": "validation_error",
"message": "Missing required input field: THING",
"code": "invalid_request",
"param": "inputs"
}
}401 - 인증 오류
{
"error": {
"type": "authentication_error",
"message": "Invalid or missing authentication credentials",
"code": "invalid_token"
}
}402 - 크레딧 부족
{
"error": {
"type": "insufficient_credits",
"message": "Insufficient credits to complete this operation",
"code": "insufficient_credits"
}
}403 - 권한 오류
{
"error": {
"type": "permission_error",
"message": "This token is not authorized to execute this prompt",
"code": "prompt_not_allowed"
}
}415 - 지원되지 않는 미디어 유형
{
"error": {
"type": "unsupported_media_type",
"message": "Unsupported file format '.exe'",
"code": "unsupported_format",
"details": [
"Supported formats: avi, docx, flac, html, jpeg, jpg, m4a, mkv, mov, mp3, mp4, ogg, pdf, png, pptx, txt, wav, webm, wmv, xlsx"
]
}
}엔드포인트
토큰 관리
/tokens/current현재 API 토큰에 대한 정보를 가져옵니다.
응답
{
"object": "token",
"id": 123,
"name": "Production API Token",
"token_prefix": "maid_zzFC7on8",
"allowed_prompts": ["prompt_1", "prompt_2"],
"monthly_limit": 1000.0,
"credits_used": 150.5,
"credits_remaining": 849.5,
"total_requests": 1234,
"expires_at": 1704067200000,
"created_at": 1640995200000
}예제
import requests
response = requests.get(
"https://api.maidepot.com/api/v1/tokens/current",
headers={"Authorization": "Bearer maid_..."}
)
print(response.json())프롬프트
/prompts현재 토큰에서 사용 가능한 모든 프롬프트를 나열합니다.
응답
{
"object": "list",
"data": [
{
"id": "KXJmXkjeUnh2ziK1JREA",
"name": "Image Generator",
"ai_model": "imagen-3-fast-generate",
"description": "Generate images from text descriptions"
},
{
"id": "dwFRshByvRrRhZD8xura",
"name": "Photo Mashup",
"ai_model": "vertex_ai",
"description": "Combine multiple images"
}
],
"has_more": false
}Note: 빈 배열이 반환되면 해당 토큰이 모든 프롬프트를 실행할 수 있는 권한이 있음을 의미합니다.
예제
import requests
response = requests.get(
"https://api.maidepot.com/api/v1/prompts",
headers={"Authorization": "Bearer maid_..."}
)
prompts = response.json()["data"]
print(prompts)/prompts/{prompt_id}입력 필드를 포함한 특정 프롬프트에 대한 자세한 정보를 가져옵니다.
요청 매개변수: prompt_id (string, required): The ID of the prompt
응답
{
"object": "prompt",
"id": "KXJmXkjeUnh2ziK1JREA",
"name": "Image Generator",
"ai_model": "imagen-3-fast-generate",
"description": "Generate images from text descriptions",
"input_fields": [
{
"id": "THING",
"label": "What to generate"
}
]
}예제
prompt_id = "KXJmXkjeUnh2ziK1JREA"
response = client.get(f"https://api.maidepot.com/api/v1/prompts/{prompt_id}")
prompt = response.json()
print(f"Prompt: {prompt['name']}")
print(f"Model: {prompt['ai_model']}")
print("Input fields:")
for field in prompt['input_fields']:
print(f" - {field['label']} (ID: {field['id']})")/prompts/{prompt_id}/run제공된 입력으로 프롬프트를 실행합니다.
요청 매개변수: prompt_id (string, required): The ID of the prompt to execute
요청 본문
{
"inputs": {
"field_id": "value"
},
"webhook_url": "https://your-domain.com/webhook"
}입력 값 유형:
1. 간단한 텍스트 입력:
{
"inputs": {
"THING": "a beautiful sunset"
}
}2. 파일 입력 (이미지, 문서, 오디오, 비디오):
{
"inputs": {
"DOCUMENT": {
"file_url": "gs://bucket/path/file.pdf",
"content_type": "application/pdf",
"ocr_mode": "normal"
}
}
}응답 (201 Created)
{
"object": "execution",
"id": "tx_abc123def456",
"status": "in_progress",
"created_at": 1644567890123
}예제: Simple Text Input
import requests
response = requests.post(
"https://api.maidepot.com/api/v1/prompts/KXJmXkjeUnh2ziK1JREA/run",
headers={"Authorization": "Bearer maid_..."},
json={"inputs": {"THING": "a beautiful sunset"}}
)
transaction_id = response.json()["id"]
print(f"Transaction ID: {transaction_id}")트랜잭션
/transactions커서 기반 페이지네이션으로 모든 트랜잭션을 나열합니다.
쿼리 매개변수
| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
limit | integer | 선택사항 | Number of results per page (1-100, default: 20) |
after | string | 선택사항 | Transaction ID to start after (for next page) |
before | string | 선택사항 | Transaction ID to start before (for previous page) |
order | string | 선택사항 | Sort order: "asc" or "desc" (default: "desc") |
status | string | 선택사항 | Filter by status: "in_progress", "done", or "failed" |
prompt_id | string | 선택사항 | Filter by prompt ID |
Important: 동일한 요청에서 'after'와 'before' 매개변수를 함께 사용할 수 없습니다.
응답
{
"object": "list",
"data": [
{
"id": "tx_abc123",
"status": "done",
"prompt_id": "KXJmXkjeUnh2ziK1JREA",
"prompt_name": "Image Generator",
"ai_model": "imagen-3-fast-generate",
"created_at": 1644567890123,
"updated_at": 1644567895456
}
],
"first_id": "tx_abc123",
"last_id": "tx_xyz789",
"has_more": true
}/transactions/{transaction_id}특정 트랜잭션의 상태와 결과를 가져옵니다.
요청 매개변수: transaction_id (string, required): The ID of the transaction
응답 (진행 중)
{
"object": "transaction",
"id": "tx_abc123",
"status": "in_progress",
"prompt_id": "KXJmXkjeUnh2ziK1JREA",
"prompt_name": "Image Generator",
"ai_model": "imagen-3-fast-generate",
"created_at": 1644567890123,
"updated_at": 1644567890123,
"result": null,
"error": null
}응답 (완료 - 텍스트)
{
"object": "transaction",
"id": "tx_abc123",
"status": "done",
"prompt_id": "KXJmXkjeUnh2ziK1JREA",
"prompt_name": "Text Generator",
"ai_model": "gpt-4",
"created_at": 1644567890123,
"updated_at": 1644567895456,
"result": {
"type": "text",
"content": "Generated text result...",
"content_preview": "First 1000 characters...",
"content_url": "https://storage.googleapis.com/...",
"image_url": null,
"image_format": null,
"size_bytes": 12345,
"truncated": false
},
"credits_used": 0.15,
"tokens_used": 1234,
"execution_time_ms": 4500,
"error": null
}응답 (완료 - 이미지)
{
"object": "transaction",
"id": "tx_abc123",
"status": "done",
"prompt_id": "KXJmXkjeUnh2ziK1JREA",
"prompt_name": "Image Generator",
"ai_model": "imagen-3-fast-generate",
"created_at": 1644567890123,
"updated_at": 1644567895456,
"result": {
"type": "image",
"content": null,
"content_preview": null,
"content_url": null,
"image_url": "https://storage.googleapis.com/signed-url-to-image.png",
"image_format": "png",
"size_bytes": 54321,
"truncated": false
},
"credits_used": 0.25,
"tokens_used": null,
"execution_time_ms": 3200,
"error": null
}Response (Failed)
{
"object": "transaction",
"id": "tx_abc123",
"status": "failed",
"prompt_id": "KXJmXkjeUnh2ziK1JREA",
"prompt_name": "Image Generator",
"ai_model": "imagen-3-fast-generate",
"created_at": 1644567890123,
"updated_at": 1644567950123,
"result": null,
"error": {
"type": "execution_error",
"message": "Model timeout after 60 seconds",
"code": "model_timeout"
},
"credits_used": 0.0,
"tokens_used": null,
"execution_time_ms": 60000
}예제: Poll Transaction Until Complete
import time
def poll_transaction(transaction_id, max_wait=300, interval=5):
"""Poll transaction until done or failed"""
start = time.time()
while time.time() - start < max_wait:
response = client.get(
f"https://api.maidepot.com/api/v1/transactions/{transaction_id}"
)
if response.status_code == 200:
data = response.json()
status = data["status"]
print(f"[{int(time.time() - start)}s] status={status}")
if status == "done":
print(f"✓ DONE | credits={data['credits_used']}")
return data
elif status == "failed":
print(f"✗ FAILED | error={data['error']}")
return data
time.sleep(interval)
return None
result = poll_transaction("tx_abc123")/transactions/{transaction_id}/retry동일한 입력과 구성을 사용하여 실패한 트랜잭션을 재시도합니다.
요청 매개변수: transaction_id (string, required): The ID of the failed transaction to retry
응답
{
"object": "execution",
"id": "tx_abc123",
"status": "in_progress",
"created_at": 1644567900000
}작동 방식:
- 원래 트랜잭션에서 저장된 입력 값을 검색합니다
- 동일한 처리된 입력으로 프롬프트를 다시 실행합니다 (파일 재처리 없음)
- 추적을 위해 retry_count를 증가시킵니다
- 동일한 transaction_id를 반환합니다 (새 ID가 아님)
- 상태가 'failed'인 트랜잭션만 재시도할 수 있습니다
제한사항:
- 상태가 "failed"인 트랜잭션만 재시도 가능
- "in_progress", "done" 트랜잭션은 재시도 불가
- 충분한 크레딧 필요
/transactions/{transaction_id}'done' 또는 'failed' 트랜잭션에서만 작동하는 소프트 삭제입니다.
요청 매개변수: transaction_id (string, required): The ID of the transaction to delete
응답
{
"object": "transaction.deleted",
"id": "tx_abc123",
"deleted_at": 1644567900000
}파일 업로드
/files/upload프롬프트 입력에 사용할 파일을 Firebase Storage에 업로드합니다.
요청:
- 메서드: POST
- Content-Type: multipart/form-data
- 본문 매개변수:
file(file, 필수) - 업로드할 파일
예제
curl -X POST "https://api.maidepot.com/api/v1/files/upload" \
-H "Authorization: Bearer maid_..." \
-F "file=@document.pdf"응답 (201 Created)
{
"object": "file",
"id": "abc123def456",
"gs_path": "gs://bucket/IO-users/acc_456/api-input-files/abc123def456.pdf",
"filename": "document.pdf",
"content_type": "application/pdf",
"size_bytes": 1048576
}파일 제한
- 최대 크기: 100 MB
- 오디오/비디오 길이:
- Basic/Standard plans: Max 1 hour
- Premium+ plans: Max 5 hours
지원되는 형식
- 문서: PDF, DOCX, PPTX, XLSX, TXT, HTML, MD
- 이미지: JPEG, PNG, JPG, GIF, WEBP, BMP
- 오디오: MP3, WAV, FLAC, OGG, M4A
- 비디오: MP4, WEBM, MKV, AVI, MOV, WMV, FLV
파일 작업
업로드 흐름
- POST /files/upload를 사용하여 파일 업로드
- 응답에서 gs_path 받기
- 프롬프트 실행 입력에 gs_path 사용
파일 처리 옵션
프롬프트에서 파일을 사용할 때 문서 처리 방법을 제어할 수 있습니다:
| 모드 | 속도 | 적합한 용도 |
|---|---|---|
normal | 빠름 | 깔끔한 텍스트가 있는 간단한 문서 |
advanced | 느림 | 복잡한 레이아웃, 표, 다단 문서 |
예제
{
"inputs": {
"DOCUMENT": {
"file_url": "gs://bucket/path/document.pdf",
"content_type": "application/pdf",
"ocr_mode": "advanced"
}
}
}일반적인 워크플로우
워크플로우 1: 간단한 텍스트 프롬프트 실행
API_TOKEN="maid_..."
BASE_URL="https://api.maidepot.com/api/v1"
# 1. Execute prompt
RESPONSE=$(curl -X POST "$BASE_URL/prompts/KXJmXkjeUnh2ziK1JREA/run" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"inputs": {"THING": "a beautiful sunset"}}')
TRANSACTION_ID=$(echo $RESPONSE | jq -r '.id')
# 2. Poll for result
while true; do
STATUS_RESPONSE=$(curl -s "$BASE_URL/transactions/$TRANSACTION_ID" \
-H "Authorization: Bearer $API_TOKEN")
STATUS=$(echo $STATUS_RESPONSE | jq -r '.status')
if [ "$STATUS" = "done" ]; then
echo "Result: $(echo $STATUS_RESPONSE | jq '.result')"
break
elif [ "$STATUS" = "failed" ]; then
echo "Error: $(echo $STATUS_RESPONSE | jq '.error')"
break
fi
sleep 5
done워크플로우 2: 파일 업로드 및 프롬프트 실행
API_TOKEN="maid_..."
BASE_URL="https://api.maidepot.com/api/v1"
PROMPT_ID="3l5gXVtFs4LS0eqk2Bmn"
# 1. Upload file
UPLOAD_RESPONSE=$(curl -X POST "$BASE_URL/files/upload" \
-H "Authorization: Bearer $API_TOKEN" \
-F "file=@document.pdf")
GS_PATH=$(echo $UPLOAD_RESPONSE | jq -r '.gs_path')
# 2. Execute prompt with file
EXEC_PAYLOAD=$(jq -n \
--arg gs_path "$GS_PATH" \
'{inputs: {DOCUMENT: {file_url: $gs_path, content_type: "application/pdf", ocr_mode: "advanced"}, LANGUAGE: "Spanish"}}')
RESPONSE=$(curl -X POST "$BASE_URL/prompts/$PROMPT_ID/run" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d "$EXEC_PAYLOAD")
TRANSACTION_ID=$(echo $RESPONSE | jq -r '.id')
# 3. Poll for result
while true; do
STATUS_RESPONSE=$(curl -s "$BASE_URL/transactions/$TRANSACTION_ID" \
-H "Authorization: Bearer $API_TOKEN")
STATUS=$(echo $STATUS_RESPONSE | jq -r '.status')
if [ "$STATUS" = "done" ]; then
echo "Result: $(echo $STATUS_RESPONSE | jq '.result')"
break
elif [ "$STATUS" = "failed" ]; then
echo "Error: $(echo $STATUS_RESPONSE | jq '.error')"
break
fi
sleep 5
done워크플로우 3: 웹훅 사용
API_TOKEN="maid_..."
BASE_URL="https://api.maidepot.com/api/v1"
PROMPT_ID="KXJmXkjeUnh2ziK1JREA"
# 1. Execute with webhook
curl -X POST "$BASE_URL/prompts/$PROMPT_ID/run" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"inputs": {"THING": "a sunset"}, "webhook_url": "https://your-domain.com/webhook"}'
# 2. Your webhook endpoint receives POST when done
# No polling needed - webhook is called automatically워크플로우 4: 실패한 트랜잭션 나열 및 재시도
API_TOKEN="maid_..."
BASE_URL="https://api.maidepot.com/api/v1"
# 1. Get failed transactions
FAILED_RESPONSE=$(curl -s "$BASE_URL/transactions?status=failed&limit=10" \
-H "Authorization: Bearer $API_TOKEN")
FAILED_TXS=$(echo $FAILED_RESPONSE | jq -r '.data[]')
# 2. Retry each failed transaction
echo "$FAILED_TXS" | jq -c '.' 2>/dev/null | while read -r tx; do
TX_ID=$(echo $tx | jq -r '.id')
echo "Retrying $TX_ID"
curl -X POST "$BASE_URL/transactions/$TX_ID/retry" \
-H "Authorization: Bearer $API_TOKEN"
sleep 10
STATUS_RESPONSE=$(curl -s "$BASE_URL/transactions/$TX_ID" \
-H "Authorization: Bearer $API_TOKEN")
echo " Status: $(echo $STATUS_RESPONSE | jq -r '.status')"
done워크플로우 5: 트랜잭션 기록 페이지네이션
API_TOKEN="maid_..."
BASE_URL="https://api.maidepot.com/api/v1"
fetch_all_transactions() {
local status=$1
all_transactions="[]"
after=""
while true; do
if [ -n "$after" ]; then
url="$BASE_URL/transactions?limit=100&order=desc&after=$after"
else
url="$BASE_URL/transactions?limit=100&order=desc"
fi
[ -n "$status" ] && url="$url&status=$status"
response=$(curl -s "$url" -H "Authorization: Bearer $API_TOKEN")
data=$(echo $response | jq -c '.')
all_transactions=$(echo $all_transactions | jq -s "add + ($data.data // [])")
has_more=$(echo $response | jq -r '.has_more')
if [ "$has_more" != "true" ]; then
break
fi
after=$(echo $response | jq -r '.last_id')
done
echo $all_transactions
}
DONE_TXS=$(fetch_all_transactions "done")
echo "Total done transactions: $(echo $DONE_TXS | jq 'length')"웹훅
웹훅은 트랜잭션이 완료되면 실시간 알림을 제공합니다. 프롬프트 실행 시 webhook_url을 지정하세요.
요구사항
- HTTPS 프로토콜을 사용해야 합니다
- localhost 또는 사설 네트워크를 가리킬 수 없습니다
- 엔드포인트는 2xx 상태 코드로 응답해야 합니다
웹훅 헤더
X-Webhook-Event: transaction.completed
X-Transaction-Id: tx_abc123
Content-Type: application/json웹훅 페이로드 (성공)
{
"object": "transaction",
"event": "transaction.completed",
"id": "tx_abc123",
"status": "done",
"prompt_id": "KXJmXkjeUnh2ziK1JREA",
"prompt_name": "Image Generator",
"ai_model": "imagen-3-fast-generate",
"result": {
"type": "text",
"content": "Full content here...",
"content_preview": "First 1000 chars...",
"content_url": "https://storage.googleapis.com/...",
"image_url": null,
"image_format": null,
"size_bytes": 12345,
"truncated": false
},
"credits_used": 0.15,
"tokens_used": 1234,
"execution_time_ms": 4500,
"error": null,
"created_at": 1644567890123,
"updated_at": 1644567895456
}웹훅 페이로드 (실패)
{
"object": "transaction",
"event": "transaction.completed",
"id": "tx_abc123",
"status": "failed",
"prompt_id": "KXJmXkjeUnh2ziK1JREA",
"prompt_name": "Image Generator",
"ai_model": "imagen-3-fast-generate",
"result": null,
"error": {
"type": "execution_error",
"message": "Model timeout",
"code": "model_timeout"
},
"credits_used": 0.0,
"tokens_used": null,
"execution_time_ms": 60000,
"created_at": 1644567890123,
"updated_at": 1644567950123
}웹훅 엔드포인트 예제 (Flask)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
event = request.headers.get('X-Webhook-Event')
transaction_id = request.headers.get('X-Transaction-Id')
payload = request.json
if event == 'transaction.completed':
status = payload['status']
if status == 'done':
result = payload['result']
print(f"✓ Transaction {transaction_id} completed")
print(f" Result type: {result['type']}")
print(f" Credits used: {payload['credits_used']}")
elif status == 'failed':
error = payload['error']
print(f"✗ Transaction {transaction_id} failed")
print(f" Error: {error['message']}")
return jsonify({"received": True}), 200