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

bash
Authorization: Bearer YOUR_API_TOKEN

Puedes crear y administrar tus tokens API desde tu perfil. Administrar Tokens API

Ejemplo

bash
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:

http
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-RateLimit-Reset: 1612345678

Respuesta de Límite de Velocidad Excedido (429)

json
{
  "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

json
{
  "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 EstadoTipo de ErrorDescripción
400validation_errorInvalid request data or missing required fields
401authentication_errorInvalid or missing API token
402insufficient_creditsNot enough credits to complete operation
403permission_errorToken doesn't have permission for this resource
404not_foundResource not found (prompt, transaction, etc.)
415unsupported_media_typeUnsupported file format
429rate_limit_errorRate limit exceeded (requests per minute)
500internal_errorInternal 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

json
{
  "error": {
    "type": "validation_error",
    "message": "Missing required input field: THING",
    "code": "invalid_request",
    "param": "inputs"
  }
}

401 - Error de Autenticación

json
{
  "error": {
    "type": "authentication_error",
    "message": "Invalid or missing authentication credentials",
    "code": "invalid_token"
  }
}

402 - Créditos Insuficientes

json
{
  "error": {
    "type": "insufficient_credits",
    "message": "Insufficient credits to complete this operation",
    "code": "insufficient_credits"
  }
}

403 - Error de Permisos

json
{
  "error": {
    "type": "permission_error",
    "message": "This token is not authorized to execute this prompt",
    "code": "prompt_not_allowed"
  }
}

415 - Tipo de Medio No Soportado

json
{
  "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

GET/tokens/current

Obtiene información sobre el token API actual.

Respuesta

json
{
  "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

python
import requests

response = requests.get(
    "https://api.maidepot.com/api/v1/tokens/current",
    headers={"Authorization": "Bearer maid_..."}
)

print(response.json())

Prompts

GET/prompts

Lista todos los prompts disponibles para el token actual.

Respuesta

json
{
  "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

python
import requests

response = requests.get(
    "https://api.maidepot.com/api/v1/prompts",
    headers={"Authorization": "Bearer maid_..."}
)

prompts = response.json()["data"]
print(prompts)
GET/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

json
{
  "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

python
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']})")
POST/prompts/{prompt_id}/run

Ejecuta 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

json
{
  "inputs": {
    "field_id": "value"
  },
  "webhook_url": "https://your-domain.com/webhook"
}

Tipos de Valores de Entrada:

1. Entrada de texto simple:

json
{
  "inputs": {
    "THING": "a beautiful sunset"
  }
}

2. Entrada de archivo (imágenes, documentos, audio, video):

json
{
  "inputs": {
    "DOCUMENT": {
      "file_url": "gs://bucket/path/file.pdf",
      "content_type": "application/pdf",
      "ocr_mode": "normal"
    }
  }
}

Respuesta (201 Created)

json
{
  "object": "execution",
  "id": "tx_abc123def456",
  "status": "in_progress",
  "created_at": 1644567890123
}

Ejemplo: Simple Text Input

python
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

GET/transactions

Lista todas las transacciones con paginación basada en cursor.

Parámetros de Consulta

NombreTipoRequeridoDescripción
limitintegerOpcionalNumber of results per page (1-100, default: 20)
afterstringOpcionalTransaction ID to start after (for next page)
beforestringOpcionalTransaction ID to start before (for previous page)
orderstringOpcionalSort order: "asc" or "desc" (default: "desc")
statusstringOpcionalFilter by status: "in_progress", "done", or "failed"
prompt_idstringOpcionalFilter by prompt ID

Important: No puedes usar ambos parámetros 'after' y 'before' en la misma solicitud.

Respuesta

json
{
  "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
}
GET/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)

json
{
  "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)

json
{
  "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)

json
{
  "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)

json
{
  "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

python
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")
POST/transactions/{transaction_id}/retry

Reintenta 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

json
{
  "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
DELETE/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

json
{
  "object": "transaction.deleted",
  "id": "tx_abc123",
  "deleted_at": 1644567900000
}

Subida de Archivos

POST/files/upload

Sube 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

bash
curl -X POST "https://api.maidepot.com/api/v1/files/upload" \
  -H "Authorization: Bearer maid_..." \
  -F "file=@document.pdf"

Respuesta (201 Created)

json
{
  "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

  1. Sube tu archivo usando POST /files/upload
  2. Recibe gs_path en la respuesta
  3. 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:

ModoVelocidadMejor Para
normalRápidoDocumentos simples con texto limpio
advancedMás lentoDiseños complejos, tablas, documentos multicolumna

Ejemplo

json
{
  "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

bash
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

Flujo de Trabajo 2: Subir Archivo y Ejecutar Prompt

bash
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

Flujo de Trabajo 3: Usar Webhooks

bash
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

Flujo de Trabajo 4: Listar y Reintentar Transacciones Fallidas

bash
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

Flujo de Trabajo 5: Paginación del Historial de Transacciones

bash
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

http
X-Webhook-Event: transaction.completed
X-Transaction-Id: tx_abc123
Content-Type: application/json

Carga de Webhook (Éxito)

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
}

Carga de Webhook (Fallido)

json
{
  "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)

python
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