Resumen
La API pública de MAIDEPOT te permite ejecutar programáticamente prompts de IA (aplicaciones, generación de imágenes y mashups) usando tokens API. Todas las ejecuciones se ejecutan de forma asíncrona y puedes rastrear su progreso a través de endpoints de transacciones o recibir notificaciones mediante webhooks.
Características Principales
- Ejecuta cualquier tipo de prompt (aplicación, imagen, mashup)
- Ejecución asíncrona con seguimiento de estado
- Soporte de carga de archivos para documentos, imágenes, audio y video
- Notificaciones webhook para ejecuciones completadas
- Paginación basada en cursor para el historial de transacciones
- Reintentar transacciones fallidas
- Seguimiento del uso de créditos
Requisitos
- El acceso a la API requiere un plan de pago (Pro, Business o Enterprise)
- Token API válido con los permisos apropiados
Autenticación
Todas las solicitudes API requieren autenticación usando un token Bearer en el encabezado. Authorization
Authorization: Bearer YOUR_API_TOKENPuedes crear y administrar tus tokens API desde tu perfil. Administrar Tokens API
Ejemplo
curl https://api.maidepot.com/api/v1/prompts \
-H "Authorization: Bearer maid_zzFC7on8-HxX_n-4PvAuTj_8OFvJYdYA3AzI4E57nSQVo2w9M6tF3aTtKp4VJ-bz"Límites de Velocidad
Los límites de velocidad se aplican por cuenta y varían según el tipo de endpoint:
- Endpoints de ejecución: 120 solicitudes/minuto
- Endpoints de lectura de metadatos: 300 solicitudes/minuto
- Endpoints de polling: 600 solicitudes/minuto
- Operaciones de gestión: 180 solicitudes/minuto
- Subidas de archivos: 60 solicitudes/minuto
Encabezados de Límite de Velocidad
Cada respuesta incluye información del límite de velocidad en los encabezados:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-RateLimit-Reset: 1612345678Respuesta de Límite de Velocidad Excedido (429)
{
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded",
"code": "rate_limit_exceeded"
}
}Manejo de Errores
Todos los errores de la API siguen una estructura estandarizada basada en el patrón RFC 7807 Problem Details.
Estructura de Respuesta de Error
{
"error": {
"type": "validation_error",
"message": "Human-readable error message",
"code": "invalid_request",
"param": "inputs",
"details": ["Additional context"]
}
}Códigos de Estado HTTP
| Código de Estado | Tipo de Error | Descripción |
|---|---|---|
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 se usa cuando tu cuenta ha agotado su asignación de créditos, mientras que 429 Rate Limit se usa cuando excedes el límite de solicitudes por minuto. Ambos requieren diferentes estrategias de manejo (agregar créditos vs. implementar backoff).
Ejemplos de Errores
400 - Error de Validación
{
"error": {
"type": "validation_error",
"message": "Missing required input field: THING",
"code": "invalid_request",
"param": "inputs"
}
}401 - Error de Autenticación
{
"error": {
"type": "authentication_error",
"message": "Invalid or missing authentication credentials",
"code": "invalid_token"
}
}402 - Créditos Insuficientes
{
"error": {
"type": "insufficient_credits",
"message": "Insufficient credits to complete this operation",
"code": "insufficient_credits"
}
}403 - Error de Permisos
{
"error": {
"type": "permission_error",
"message": "This token is not authorized to execute this prompt",
"code": "prompt_not_allowed"
}
}415 - Tipo de Medio No Soportado
{
"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"
]
}
}Endpoints
Gestión de Tokens
/tokens/currentObtiene información sobre el token API actual.
Respuesta
{
"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
}Ejemplo
import requests
response = requests.get(
"https://api.maidepot.com/api/v1/tokens/current",
headers={"Authorization": "Bearer maid_..."}
)
print(response.json())Prompts
/promptsLista todos los prompts disponibles para el token actual.
Respuesta
{
"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: Cuando se devuelve un array vacio, significa que el token tiene permiso para ejecutar cualquier prompt.
Ejemplo
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}Obtiene información detallada sobre un prompt específico incluyendo campos de entrada.
Parámetros de Solicitud: prompt_id (string, required): The ID of the prompt
Respuesta
{
"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"
}
]
}Ejemplo
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}/runEjecuta un prompt con las entradas proporcionadas.
Parámetros de Solicitud: prompt_id (string, required): The ID of the prompt to execute
Cuerpo de la Solicitud
{
"inputs": {
"field_id": "value"
},
"webhook_url": "https://your-domain.com/webhook"
}Tipos de Valores de Entrada:
1. Entrada de texto simple:
{
"inputs": {
"THING": "a beautiful sunset"
}
}2. Entrada de archivo (imágenes, documentos, audio, video):
{
"inputs": {
"DOCUMENT": {
"file_url": "gs://bucket/path/file.pdf",
"content_type": "application/pdf",
"ocr_mode": "normal"
}
}
}Respuesta (201 Created)
{
"object": "execution",
"id": "tx_abc123def456",
"status": "in_progress",
"created_at": 1644567890123
}Ejemplo: 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}")Transacciones
/transactionsLista todas las transacciones con paginación basada en cursor.
Parámetros de Consulta
| Nombre | Tipo | Requerido | Descripción |
|---|---|---|---|
limit | integer | Opcional | Number of results per page (1-100, default: 20) |
after | string | Opcional | Transaction ID to start after (for next page) |
before | string | Opcional | Transaction ID to start before (for previous page) |
order | string | Opcional | Sort order: "asc" or "desc" (default: "desc") |
status | string | Opcional | Filter by status: "in_progress", "done", or "failed" |
prompt_id | string | Opcional | Filter by prompt ID |
Important: No puedes usar ambos parámetros 'after' y 'before' en la misma solicitud.
Respuesta
{
"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}Obtiene el estado y resultado de una transacción específica.
Parámetros de Solicitud: transaction_id (string, required): The ID of the transaction
Respuesta (En Progreso)
{
"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
}Respuesta (Completada - Texto)
{
"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
}Respuesta (Completada - Imagen)
{
"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
}Ejemplo: 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}/retryReintenta una transacción fallida usando las mismas entradas y configuración.
Parámetros de Solicitud: transaction_id (string, required): The ID of the failed transaction to retry
Respuesta
{
"object": "execution",
"id": "tx_abc123",
"status": "in_progress",
"created_at": 1644567900000
}Cómo funciona:
- Recupera los valores de entrada almacenados de la transacción original
- Re-ejecuta el prompt con las mismas entradas procesadas (sin re-procesar archivos)
- Incrementa el retry_count para seguimiento
- Devuelve el mismo transaction_id (no uno nuevo)
- Solo puede reintentar transacciones con estado 'failed'
Restricciones:
- Solo puede reintentar transacciones con estado "failed"
- No puede reintentar transacciones "in_progress" o "done"
- Requiere créditos suficientes
/transactions/{transaction_id}Eliminación suave de una transacción (solo funciona para transacciones 'done' o 'failed').
Parámetros de Solicitud: transaction_id (string, required): The ID of the transaction to delete
Respuesta
{
"object": "transaction.deleted",
"id": "tx_abc123",
"deleted_at": 1644567900000
}Subida de Archivos
/files/uploadSube un archivo a Firebase Storage para usar en las entradas del prompt.
Solicitud:
- Método: POST
- Content-Type: multipart/form-data
- Parámetro del Cuerpo:
file(file, Requerido) - El archivo a subir
Ejemplo
curl -X POST "https://api.maidepot.com/api/v1/files/upload" \
-H "Authorization: Bearer maid_..." \
-F "file=@document.pdf"Respuesta (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
}Límites de Archivo
- Tamaño máximo: 100 MB
- Duración de Audio/Video:
- Basic/Standard plans: Max 1 hour
- Premium+ plans: Max 5 hours
Formatos Soportados
- Documentos: PDF, DOCX, PPTX, XLSX, TXT, HTML, MD
- Imágenes: JPEG, PNG, JPG, GIF, WEBP, BMP
- Audio: MP3, WAV, FLAC, OGG, M4A
- Video: MP4, WEBM, MKV, AVI, MOV, WMV, FLV
Trabajar con Archivos
Flujo de Subida
- Sube tu archivo usando POST /files/upload
- Recibe gs_path en la respuesta
- Usa el gs_path en las entradas de ejecución del prompt
Opciones de Procesamiento de Archivos
Al usar archivos en prompts, puedes controlar cómo se procesan los documentos:
| Modo | Velocidad | Mejor Para |
|---|---|---|
normal | Rápido | Documentos simples con texto limpio |
advanced | Más lento | Diseños complejos, tablas, documentos multicolumna |
Ejemplo
{
"inputs": {
"DOCUMENT": {
"file_url": "gs://bucket/path/document.pdf",
"content_type": "application/pdf",
"ocr_mode": "advanced"
}
}
}Flujos de Trabajo Comunes
Flujo de Trabajo 1: Ejecutar Prompt de Texto Simple
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
doneFlujo de Trabajo 2: Subir Archivo y Ejecutar Prompt
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
doneFlujo de Trabajo 3: Usar Webhooks
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 automaticallyFlujo de Trabajo 4: Listar y Reintentar Transacciones Fallidas
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')"
doneFlujo de Trabajo 5: Paginación del Historial de Transacciones
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')"Webhooks
Los webhooks proporcionan notificaciones en tiempo real cuando las transacciones se completan. Especifica un webhook_url al ejecutar un prompt.
Requisitos
- Debe usar protocolo HTTPS
- No puede apuntar a localhost o redes privadas
- El endpoint debe responder con código de estado 2xx
Encabezados de Webhook
X-Webhook-Event: transaction.completed
X-Transaction-Id: tx_abc123
Content-Type: application/jsonCarga de Webhook (Éxito)
{
"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
}Carga de Webhook (Fallido)
{
"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
}Ejemplo de Endpoint de Webhook (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