Overview

The MAIDEPOT Public API allows you to programmatically execute AI prompts (apps, image generation, and mashups) using API tokens. All executions run asynchronously, and you can track their progress through transaction endpoints or receive notifications via webhooks.

Key Features

  • Execute any prompt type (app, image, mashup)
  • Asynchronous execution with status tracking
  • File upload support for documents, images, audio, and video
  • Webhook notifications for completed executions
  • Cursor-based pagination for transaction history
  • Retry failed transactions
  • Credit usage tracking

Requirements

  • API access requires a paid plan (Pro, Business, or Enterprise)
  • Valid API token with appropriate permissions

Authentication

All API requests require authentication using a Bearer token in the header. Authorization

bash
Authorization: Bearer YOUR_API_TOKEN

You can create and manage your API tokens from your profile. Manage API Tokens

Example

bash
curl https://api.maidepot.com/api/v1/prompts \
  -H "Authorization: Bearer maid_zzFC7on8-HxX_n-4PvAuTj_8OFvJYdYA3AzI4E57nSQVo2w9M6tF3aTtKp4VJ-bz"

Rate Limiting

Rate limits are applied per account and vary by endpoint type:

  • Execution endpoints: 120 requests/minute
  • Metadata read endpoints: 300 requests/minute
  • Polling endpoints: 600 requests/minute
  • Management operations: 180 requests/minute
  • File uploads: 60 requests/minute

Rate Limit Headers

Every response includes rate limit information in the headers:

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

Rate Limit Exceeded Response (429)

json
{
  "error": {
    "type": "rate_limit_error",
    "message": "Rate limit exceeded",
    "code": "rate_limit_exceeded"
  }
}

Error Handling

All API errors follow a standardized structure based on RFC 7807 Problem Details pattern.

Error Response Structure

json
{
  "error": {
    "type": "validation_error",
    "message": "Human-readable error message",
    "code": "invalid_request",
    "param": "inputs",
    "details": ["Additional context"]
  }
}

HTTP Status Codes

Status CodeError TypeDescription
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 is used when your account has exhausted its credit allocation, while 429 Rate Limit is used when you exceed the requests-per-minute limit. Both require different handling strategies (add credits vs. implement backoff).

Error Examples

400 - Validation Error

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

401 - Authentication Error

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

402 - Insufficient Credits

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

403 - Permission Error

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

415 - Unsupported Media Type

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

Token Management

GET/tokens/current

Get information about the current API token.

Response

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
}

Example

python
import requests

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

print(response.json())

Prompts

GET/prompts

List all prompts available to the current token.

Response

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: When an empty array is returned, it means the token has permission to execute any prompt.

Example

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}

Get detailed information about a specific prompt including input fields.

Request Parameters: prompt_id (string, required): The ID of the prompt

Response

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"
    }
  ]
}

Example

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

Execute a prompt with the provided inputs.

Request Parameters: prompt_id (string, required): The ID of the prompt to execute

Request Body

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

Input Value Types:

1. Simple text input:

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

2. File input (images, documents, audio, video):

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

Response (201 Created)

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

Example: 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}")

Transactions

GET/transactions

List all transactions with cursor-based pagination.

Query Parameters

NameTypeRequiredDescription
limitintegerOptionalNumber of results per page (1-100, default: 20)
afterstringOptionalTransaction ID to start after (for next page)
beforestringOptionalTransaction ID to start before (for previous page)
orderstringOptionalSort order: "asc" or "desc" (default: "desc")
statusstringOptionalFilter by status: "in_progress", "done", or "failed"
prompt_idstringOptionalFilter by prompt ID

Important: You cannot use both 'after' and 'before' parameters in the same request.

Response

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}

Get the status and result of a specific transaction.

Request Parameters: transaction_id (string, required): The ID of the transaction

Response (In Progress)

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
}

Response (Completed - Text)

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
}

Response (Completed - Image)

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
}

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

Retry a failed transaction using the same inputs and configuration.

Request Parameters: transaction_id (string, required): The ID of the failed transaction to retry

Response

json
{
  "object": "execution",
  "id": "tx_abc123",
  "status": "in_progress",
  "created_at": 1644567900000
}

How it works:

  • Retrieves stored input values from the original transaction
  • Re-executes the prompt with the same processed inputs (no file re-processing)
  • Increments the retry_count for tracking
  • Returns the same transaction_id (not a new one)
  • Can only retry transactions with status 'failed'

Restrictions:

  • Can only retry transactions with status "failed"
  • Cannot retry "in_progress" or "done" transactions
  • Requires sufficient credits
DELETE/transactions/{transaction_id}

Soft delete a transaction (only works for "done" or "failed" transactions).

Request Parameters: transaction_id (string, required): The ID of the transaction to delete

Response

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

File Upload

POST/files/upload

Upload a file to Firebase Storage for use in prompt inputs.

Request:

  • Method: POST
  • Content-Type: multipart/form-data
  • Body Parameter: file (file, Required) - The file to upload

Example

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

Response (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
}
File Limits
  • Max size: 100 MB
  • Audio/Video duration:
    • Basic/Standard plans: Max 1 hour
    • Premium+ plans: Max 5 hours
Supported Formats
  • Documents: PDF, DOCX, PPTX, XLSX, TXT, HTML, MD
  • Images: JPEG, PNG, JPG, GIF, WEBP, BMP
  • Audio: MP3, WAV, FLAC, OGG, M4A
  • Video: MP4, WEBM, MKV, AVI, MOV, WMV, FLV

Working with Files

Upload Flow

  1. Upload your file using POST /files/upload
  2. Receive gs_path in the response
  3. Use the gs_path in your prompt execution inputs

File Processing Options

When using files in prompts, you can control how documents are processed:

ModeSpeedBest For
normalFastSimple documents with clean text
advancedSlowerComplex layouts, tables, multi-column documents

Example

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

Common Workflows

Workflow 1: Execute Simple Text Prompt

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

Workflow 2: Upload File and Execute 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

Workflow 3: Using 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

Workflow 4: List and Retry Failed Transactions

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

Workflow 5: Pagination Through Transaction History

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

Webhooks provide real-time notifications when transactions complete. Specify a webhook_url when executing a prompt.

Requirements

  • Must use HTTPS protocol
  • Cannot point to localhost or private networks
  • Endpoint must respond with 2xx status code

Webhook Headers

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

Webhook Payload (Success)

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
}

Webhook Payload (Failed)

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
}

Example Webhook Endpoint (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