{
  "openapi": "3.0.3",
  "info": {
    "title": "Concurred API",
    "description": "AI Gateway with 9 text models (Claude, GPT, Grok, Gemini, DeepSeek, Kimi, Mistral, Llama, MiniMax) plus MiniMax media APIs (Speech, Music, Video). OpenAI-compatible gateway with fallback routing, caching, load balancing, guardrails, prompt templates, and BYOK.",
    "version": "2.1.0",
    "contact": {
      "name": "Concurred API Support",
      "url": "https://agent-heavy.vercel.app/docs/api"
    }
  },
  "servers": [
    {
      "url": "https://agent-heavy.vercel.app",
      "description": "Production server"
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "API health and status monitoring"
    },
    {
      "name": "Gateway",
      "description": "OpenAI-compatible chat completions with gateway features"
    },
    {
      "name": "Admin",
      "description": "Partner-facing admin provisioning API \u2014 mint, revoke, and read usage for ck_ and ck_pub_ keys. Requires an admin token."
    },
    {
      "name": "Keys",
      "description": "API key management (Unkey)"
    },
    {
      "name": "Usage",
      "description": "Usage analytics and cost tracking (Langfuse)"
    },
    {
      "name": "Provider Keys",
      "description": "BYOK \u2014 store your own provider API keys"
    },
    {
      "name": "Chat",
      "description": "Multi-model chat, battle, and fight modes"
    },
    {
      "name": "Search",
      "description": "Web search via Exa \u2014 authenticated with your Concurred API key"
    },
    {
      "name": "Themes",
      "description": "Curated design-system themes for AI-generated UI \u2014 proxied from October.dev"
    },
    {
      "name": "Vision",
      "description": "Standalone image analysis endpoint"
    },
    {
      "name": "Media",
      "description": "MiniMax media generation \u2014 speech, music, video"
    },
    {
      "name": "Fashion",
      "description": "AI-powered fashion image generation"
    }
  ],
  "paths": {
    "/api/health": {
      "get": {
        "tags": ["Health"],
        "summary": "Health check",
        "description": "Returns API health status and AI model availability. No authentication required.",
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "Health status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "status": "healthy",
                    "version": "1.0.0",
                    "timestamp": "2026-03-04T12:00:00.000Z",
                    "uptime": 86400,
                    "services": [
                      {
                        "name": "claude",
                        "status": "up"
                      },
                      {
                        "name": "gpt",
                        "status": "up"
                      },
                      {
                        "name": "grok",
                        "status": "up"
                      },
                      {
                        "name": "gemini",
                        "status": "up"
                      },
                      {
                        "name": "deepseek",
                        "status": "up"
                      },
                      {
                        "name": "kimi",
                        "status": "up"
                      },
                      {
                        "name": "mistral",
                        "status": "up"
                      },
                      {
                        "name": "llama",
                        "status": "up"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/chat/completions": {
      "post": {
        "tags": ["Gateway"],
        "summary": "Create chat completion",
        "description": "OpenAI-compatible chat completions endpoint with advanced gateway features: fallback routing, caching, load balancing, guardrails, prompt templates, and BYOK. Works as a drop-in replacement for the OpenAI SDK.",
        "operationId": "createChatCompletion",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Cache",
            "in": "header",
            "schema": {
              "type": "string",
              "enum": ["no-cache"]
            },
            "description": "Set to 'no-cache' to bypass response cache"
          },
          {
            "name": "X-Cache-TTL",
            "in": "header",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 86400
            },
            "description": "Cache TTL in seconds (default: 3600, max: 86400). Non-streaming only."
          },
          {
            "name": "X-Guardrails",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated guardrails to enable (alternative to body). Values: pii, content_moderation, schema_validation"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GatewayRequest"
              },
              "examples": {
                "simple": {
                  "summary": "Simple request",
                  "value": {
                    "model": "gpt",
                    "messages": [
                      {
                        "role": "user",
                        "content": "Hello!"
                      }
                    ]
                  }
                },
                "streaming": {
                  "summary": "Streaming",
                  "value": {
                    "model": "claude",
                    "messages": [
                      {
                        "role": "system",
                        "content": "You are a helpful assistant."
                      },
                      {
                        "role": "user",
                        "content": "Explain quantum computing"
                      }
                    ],
                    "stream": true,
                    "temperature": 0.7
                  }
                },
                "fallback": {
                  "summary": "With fallback models",
                  "value": {
                    "model": "claude",
                    "messages": [
                      {
                        "role": "user",
                        "content": "Hello!"
                      }
                    ],
                    "fallback": ["gpt", "gemini"]
                  }
                },
                "loadBalanced": {
                  "summary": "Load balanced",
                  "value": {
                    "model": "gpt",
                    "messages": [
                      {
                        "role": "user",
                        "content": "Hello!"
                      }
                    ],
                    "load_balance": {
                      "strategy": "weighted",
                      "targets": [
                        {
                          "model": "gpt",
                          "weight": 70
                        },
                        {
                          "model": "claude",
                          "weight": 30
                        }
                      ]
                    }
                  }
                },
                "withGuardrails": {
                  "summary": "With guardrails",
                  "value": {
                    "model": "gpt",
                    "messages": [
                      {
                        "role": "user",
                        "content": "My email is john@example.com"
                      }
                    ],
                    "guardrails": {
                      "enabled": ["pii", "content_moderation"]
                    }
                  }
                },
                "promptTemplate": {
                  "summary": "With Langfuse prompt template",
                  "value": {
                    "model": "claude",
                    "messages": [
                      {
                        "role": "user",
                        "content": "Review this code"
                      }
                    ],
                    "prompt_id": "code-review",
                    "prompt_variables": {
                      "language": "python"
                    }
                  }
                },
                "vision": {
                  "summary": "Multimodal with image",
                  "value": {
                    "model": "claude",
                    "messages": [
                      {
                        "role": "user",
                        "content": [
                          {
                            "type": "text",
                            "text": "What is in this image?"
                          },
                          {
                            "type": "image_url",
                            "image_url": {
                              "url": "https://example.com/photo.jpg"
                            }
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat completion response",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                },
                "description": "Unique request identifier"
              },
              "X-Model-Used": {
                "schema": {
                  "type": "string"
                },
                "description": "Actual model that served the request"
              },
              "X-Cache": {
                "schema": {
                  "type": "string",
                  "enum": ["HIT", "MISS"]
                },
                "description": "Cache status"
              },
              "X-Fallback-From": {
                "schema": {
                  "type": "string"
                },
                "description": "Original model if fallback was used"
              },
              "X-Retry-Count": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of retries attempted"
              },
              "X-Guardrail-Status": {
                "schema": {
                  "type": "string"
                },
                "description": "Guardrail results (e.g. 'pii:redact,content_moderation:pass')"
              },
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Max requests per minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Remaining requests"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Unix timestamp when window resets"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "SSE stream of chat completion chunks (when stream=true)"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ModelUnavailable"
          }
        }
      }
    },
    "/api/v1/models": {
      "get": {
        "tags": ["Gateway"],
        "summary": "List available models",
        "description": "Returns all available AI models with IDs, aliases, and provider information.",
        "operationId": "listModels",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Model list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "gpt-5.2",
                      "object": "model",
                      "created": 1706540000,
                      "owned_by": "concurred/openai",
                      "_concurred": {
                        "name": "GPT-5.2",
                        "aliases": ["chatgpt", "gpt", "gpt-4", "gpt-5.2"]
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/keys": {
      "post": {
        "tags": ["Keys"],
        "summary": "Create API key",
        "description": "Create a new API key via Unkey. The full key is shown only once in the response \u2014 store it securely. Requires authenticated Supabase session (dashboard).",
        "operationId": "createApiKey",
        "security": [
          {
            "CookieAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "default": "Default",
                    "description": "Friendly name for the key"
                  },
                  "rateLimit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000,
                    "description": "Per-key rate limit (requests/minute)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "keyId": {
                          "type": "string"
                        },
                        "key": {
                          "type": "string",
                          "description": "Full API key (ck_...) \u2014 shown only once"
                        },
                        "name": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "get": {
        "tags": ["Keys"],
        "summary": "List API keys",
        "description": "List all API keys for the authenticated user. Keys are masked \u2014 only metadata is returned.",
        "operationId": "listApiKeys",
        "security": [
          {
            "CookieAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Key list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "keys": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "enabled": {
                                "type": "boolean"
                              },
                              "rateLimit": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/keys/{id}": {
      "patch": {
        "tags": ["Keys"],
        "summary": "Update API key",
        "description": "Update an API key's name, rate limit, or enabled status.",
        "operationId": "updateApiKey",
        "security": [
          {
            "CookieAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Key ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "rateLimit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Key updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "keyId": {
                          "type": "string"
                        },
                        "updated": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Key not found"
          }
        }
      },
      "delete": {
        "tags": ["Keys"],
        "summary": "Revoke API key",
        "description": "Permanently revoke an API key. This action cannot be undone.",
        "operationId": "revokeApiKey",
        "security": [
          {
            "CookieAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Key ID"
          }
        ],
        "responses": {
          "204": {
            "description": "Key revoked"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Key not found"
          }
        }
      }
    },
    "/api/v1/usage": {
      "get": {
        "tags": ["Usage"],
        "summary": "Query usage data",
        "description": "Query request volume, token usage, and estimated costs from Langfuse. Returns per-model breakdown.",
        "operationId": "getUsage",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          },
          {
            "CookieAuth": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Start date (ISO 8601, e.g. 2026-03-01). Default: 30 days ago."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "End date (ISO 8601, e.g. 2026-03-21). Default: today."
          }
        ],
        "responses": {
          "200": {
            "description": "Usage data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "totalRequests": {
                          "type": "integer"
                        },
                        "totalTokens": {
                          "type": "integer"
                        },
                        "totalCost": {
                          "type": "number",
                          "description": "Estimated cost in USD"
                        },
                        "from": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "to": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "byModel": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "object",
                            "properties": {
                              "requests": {
                                "type": "integer"
                              },
                              "tokens": {
                                "type": "integer"
                              },
                              "cost": {
                                "type": "number"
                              }
                            }
                          },
                          "description": "Breakdown by model name"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "totalRequests": 142,
                    "totalTokens": 85000,
                    "totalCost": 0.47,
                    "from": "2026-02-19T00:00:00.000Z",
                    "to": "2026-03-21T00:00:00.000Z",
                    "byModel": {
                      "claude-sonnet-4-5-20250929": {
                        "requests": 45,
                        "tokens": 28000,
                        "cost": 0.18
                      },
                      "gpt-5.2": {
                        "requests": 52,
                        "tokens": 31000,
                        "cost": 0.15
                      },
                      "gemini-3-pro-preview": {
                        "requests": 45,
                        "tokens": 26000,
                        "cost": 0.14
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/provider-keys": {
      "post": {
        "tags": ["Provider Keys"],
        "summary": "Store provider API key",
        "description": "Store your own provider API key (BYOK). Keys are encrypted at rest with AES-256-GCM. When you make gateway requests, your stored key is used instead of the platform key.",
        "operationId": "createProviderKey",
        "security": [
          {
            "CookieAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["provider", "slug", "apiKey"],
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "openai",
                      "anthropic",
                      "google",
                      "x-ai",
                      "openrouter"
                    ],
                    "description": "AI provider"
                  },
                  "slug": {
                    "type": "string",
                    "pattern": "^[a-z0-9-]{2,50}$",
                    "description": "Unique slug (lowercase alphanumeric + hyphens)"
                  },
                  "displayName": {
                    "type": "string",
                    "description": "Friendly display name"
                  },
                  "apiKey": {
                    "type": "string",
                    "description": "Provider API key (encrypted at rest)"
                  }
                }
              },
              "example": {
                "provider": "openai",
                "slug": "my-openai-key",
                "displayName": "My OpenAI Key",
                "apiKey": "sk-..."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Provider key stored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderKeyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "get": {
        "tags": ["Provider Keys"],
        "summary": "List provider keys",
        "description": "List stored provider keys. Keys are masked \u2014 only the last 4 characters are shown.",
        "operationId": "listProviderKeys",
        "security": [
          {
            "CookieAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Provider key list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "keys": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ProviderKeyResponse"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/provider-keys/{id}": {
      "delete": {
        "tags": ["Provider Keys"],
        "summary": "Remove provider key",
        "description": "Permanently remove a stored provider API key.",
        "operationId": "deleteProviderKey",
        "security": [
          {
            "CookieAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Provider key ID"
          }
        ],
        "responses": {
          "204": {
            "description": "Provider key removed"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Key not found"
          }
        }
      }
    },
    "/api/v1/battle": {
      "post": {
        "tags": ["Chat"],
        "summary": "Battle \u2014 two models answer side-by-side",
        "description": "First-class v1 route for battle mode. The URL pins the mode, so the request body's `mode` field is not required and is ignored if sent. Same shape, auth, and credits as the legacy `/api/chat` with `\"mode\": \"battle\"`.\n\nRequires `models` \u2014 an array of exactly two model IDs (or a comma-separated string).",
        "operationId": "battle",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              },
              "examples": {
                "battle": {
                  "summary": "Two-model battle, non-streaming",
                  "value": {
                    "message": "Explain machine learning",
                    "models": ["claude", "gpt"],
                    "stream": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Both model responses returned together. SSE stream when `stream: true` (default), JSON object otherwise.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/fight": {
      "post": {
        "tags": ["Chat"],
        "summary": "Fight \u2014 multi-agent debate with voting (SSE)",
        "description": "First-class v1 route for fight mode. The URL pins the mode, so the request body's `mode` field is not required. Streaming only \u2014 `stream: false` returns 400 STREAMING_REQUIRED.\n\nFight style is selected via the optional `fightStyle` field:\n- `\"brawl\"` (default): sequential, peer-aware \u2014 each agent sees prior peers this round; every prior round's full transcript is replayed.\n- `\"blitz\"`: parallel \u2014 agents run on a frozen context; only the prior round's winning answer carries forward.",
        "operationId": "fight",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              },
              "examples": {
                "brawl": {
                  "summary": "Fight \u2014 Brawl (sequential, peer-aware, default)",
                  "value": {
                    "message": "What is the meaning of life?",
                    "models": "claude,gpt,grok,gemini",
                    "rounds": 2,
                    "fightStyle": "brawl"
                  }
                },
                "blitz": {
                  "summary": "Fight \u2014 Blitz (parallel, frozen context)",
                  "value": {
                    "message": "What is the meaning of life?",
                    "models": "claude,gpt,grok,gemini",
                    "rounds": 2,
                    "fightStyle": "blitz"
                  }
                },
                "multiInstance": {
                  "summary": "Multi-instance \u2014 4\u00d7 same model (Grok Heavy-style)",
                  "value": {
                    "message": "Best investment strategy?",
                    "agentMode": "multiple-grok",
                    "rounds": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Server-Sent Events stream. See [Chat docs](/docs/api/chat) for event schema.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/search": {
      "post": {
        "tags": ["Search"],
        "summary": "Web search \u2014 authenticated Exa passthrough",
        "description": "Run a web search with your Concurred API key. Thin wrapper over Exa's `/search` with a stable public shape. Use this when you want raw results to render yourself; use the Chat API's battle/fight modes if you want the model to drive search.",
        "operationId": "search",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["query"],
                "properties": {
                  "query": {
                    "type": "string",
                    "maxLength": 1000,
                    "description": "Search query"
                  },
                  "num_results": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 25,
                    "default": 10
                  },
                  "type": {
                    "type": "string",
                    "enum": ["neural", "keyword", "auto"],
                    "default": "neural"
                  },
                  "include_summary": {
                    "type": "boolean",
                    "default": true
                  },
                  "recency": {
                    "type": "string",
                    "description": "Recency filter. Format: <N><d|w|m|y>, e.g. '7d', '1m', '1y'."
                  }
                }
              },
              "examples": {
                "default": {
                  "summary": "Neural search with recency filter",
                  "value": {
                    "query": "latest AI research on mixture-of-experts",
                    "num_results": 10,
                    "recency": "1m"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search results from Exa, normalized to snake_case.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "query": {
                          "type": "string"
                        },
                        "results": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "url": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "snippet": {
                                "type": "string"
                              },
                              "score": {
                                "type": "number"
                              },
                              "published_date": {
                                "type": "string"
                              },
                              "author": {
                                "type": "string"
                              },
                              "favicon": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "auto_prompt": {
                          "type": "string"
                        },
                        "cost_usd": {
                          "type": "number"
                        },
                        "request_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "description": "Search is not configured on this deployment (missing EXA_API_KEY)"
          },
          "503": {
            "description": "Upstream search provider error"
          }
        }
      }
    },
    "/api/v1/themes": {
      "get": {
        "tags": ["Themes"],
        "summary": "Fetch a design-system theme (powered by October)",
        "description": "Authenticated proxy to October.dev's free public themes API. Returns a single curated design-system theme as markdown you can drop straight into an LLM prompt. With no query params, returns a random theme. Use `platform` to bias random selection, or `id` to fetch a specific slug.",
        "operationId": "getTheme",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Slug of a specific theme (e.g. `editorial-serif`). Takes precedence over random/platform."
          },
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["desktop-web", "mobile-app", "game"]
            },
            "description": "Filter random selection to a platform. Ignored when `id` is set."
          }
        ],
        "responses": {
          "200": {
            "description": "A single theme.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "platform": {
                          "type": "string"
                        },
                        "weight": {
                          "type": "number"
                        },
                        "content": {
                          "type": "string",
                          "description": "Markdown design-system spec wrapped in <design-system>\u2026</design-system>."
                        },
                        "source": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "url": {
                              "type": "string"
                            },
                            "theme_url": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No theme matches the given `id`"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "October themes upstream returned a non-2xx"
          }
        }
      }
    },
    "/api/chat": {
      "post": {
        "tags": ["Chat"],
        "summary": "[Legacy] Unified chat (chat/battle/fight modes)",
        "description": "**Legacy endpoint \u2014 kept for back-compat.** Prefer the v1 routes that name the operation in the URL:\n- `POST /api/v1/battle` \u2014 two models side-by-side\n- `POST /api/v1/fight` \u2014 2-8 models with voting\n- `POST /api/v1/chat/completions` \u2014 single-model, OpenAI-compatible\n\nBehaviour is unchanged: this route dispatches to the same handlers as the v1 routes via a body `mode` field (`chat` | `battle` | `fight`). Multi-instance mode is still available via `agentMode` on any of these.\n\nBattle and fight modes support autonomous web search with citations.",
        "operationId": "legacyChat",
        "deprecated": true,
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              },
              "examples": {
                "chat": {
                  "summary": "Chat mode (single model)",
                  "value": {
                    "message": "What is the best programming language?",
                    "mode": "chat",
                    "model": "claude",
                    "stream": false
                  }
                },
                "battle": {
                  "summary": "Battle mode (2 models)",
                  "value": {
                    "message": "Explain machine learning",
                    "mode": "battle",
                    "models": ["claude", "gpt"],
                    "stream": false
                  }
                },
                "fightBrawl": {
                  "summary": "Fight mode \u2014 Brawl (sequential, peer-aware, default)",
                  "value": {
                    "message": "What is the meaning of life?",
                    "mode": "fight",
                    "models": "claude,gpt,grok,gemini",
                    "rounds": 2,
                    "fightStyle": "brawl"
                  }
                },
                "fightBlitz": {
                  "summary": "Fight mode \u2014 Blitz (parallel, frozen context)",
                  "value": {
                    "message": "What is the meaning of life?",
                    "mode": "fight",
                    "models": "claude,gpt,grok,gemini",
                    "rounds": 2,
                    "fightStyle": "blitz"
                  }
                },
                "multiInstance": {
                  "summary": "Multi-instance mode (4x same model)",
                  "value": {
                    "message": "Best investment strategy?",
                    "mode": "fight",
                    "agentMode": "multiple-grok",
                    "rounds": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Response varies by mode. Chat/battle return JSON. Fight returns SSE stream.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ChatModeResponse"
                    },
                    {
                      "$ref": "#/components/schemas/BattleModeResponse"
                    }
                  ]
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "SSE stream for fight mode. Events: session_start, round_start, agent_start, agent_complete, search_start, search_complete, voting_start, vote_update, voting_complete, leaderboard_update, round_complete, session_complete, error"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/vision": {
      "get": {
        "tags": ["Vision"],
        "summary": "List vision models",
        "operationId": "listVisionModels",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Vision model list",
            "content": {
              "application/json": {
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "grok-4-1-fast",
                      "object": "model",
                      "owned_by": "x-ai",
                      "capabilities": ["vision", "image-understanding"]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Vision"],
        "summary": "Analyze image",
        "description": "Analyze an image using Grok Vision. Supports URL or base64 input.",
        "operationId": "analyzeImage",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VisionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vision analysis result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VisionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/media/speech": {
      "post": {
        "tags": ["Media"],
        "summary": "Text-to-speech",
        "description": "Generate speech audio from text using MiniMax Speech 2.6. Returns audio binary (mp3/wav/pcm/flac). Supports 300+ voices and 40 languages.",
        "operationId": "generateSpeech",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["text"],
                "properties": {
                  "model": {
                    "type": "string",
                    "default": "speech-2.6-hd",
                    "enum": ["speech-2.6-hd", "speech-2.6-turbo"]
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 10000,
                    "description": "Text to synthesize"
                  },
                  "voice_setting": {
                    "type": "object",
                    "properties": {
                      "voice_id": {
                        "type": "string",
                        "default": "female-shaonv"
                      },
                      "speed": {
                        "type": "number",
                        "default": 1.0
                      },
                      "vol": {
                        "type": "number",
                        "default": 1.0
                      },
                      "pitch": {
                        "type": "number"
                      }
                    }
                  },
                  "audio_setting": {
                    "type": "object",
                    "properties": {
                      "sample_rate": {
                        "type": "integer",
                        "enum": [16000, 24000, 32000, 44100],
                        "default": 44100
                      },
                      "bitrate": {
                        "type": "integer",
                        "default": 256000
                      },
                      "format": {
                        "type": "string",
                        "enum": ["mp3", "wav", "pcm", "flac"],
                        "default": "mp3"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Audio binary",
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/media/music": {
      "post": {
        "tags": ["Media"],
        "summary": "Generate music",
        "description": "Generate music from text prompt and/or lyrics using MiniMax Music 2.5. Supports instrumental mode, structure tags ([Verse], [Chorus], etc.), and custom audio settings.",
        "operationId": "generateMusic",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "model": {
                    "type": "string",
                    "default": "music-2.5",
                    "enum": ["music-2.5", "music-2.5+"]
                  },
                  "prompt": {
                    "type": "string",
                    "maxLength": 2000,
                    "description": "Music style/mood description"
                  },
                  "lyrics": {
                    "type": "string",
                    "maxLength": 3500,
                    "description": "Song lyrics with structure tags"
                  },
                  "is_instrumental": {
                    "type": "boolean",
                    "default": false
                  },
                  "lyrics_optimizer": {
                    "type": "boolean",
                    "default": false
                  },
                  "output_format": {
                    "type": "string",
                    "enum": ["url", "hex"],
                    "default": "url"
                  }
                }
              },
              "example": {
                "model": "music-2.5",
                "prompt": "Upbeat pop song about summer",
                "lyrics": "[Verse]\nSunshine on my face..."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Music generation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer"
                        },
                        "audio": {
                          "type": "string",
                          "description": "Audio URL or hex data"
                        },
                        "duration": {
                          "type": "number"
                        },
                        "sample_rate": {
                          "type": "integer"
                        },
                        "format": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/media/video": {
      "post": {
        "tags": ["Media"],
        "summary": "Submit video generation job",
        "description": "Submit a video generation job using MiniMax Hailuo 2.3. Returns a task_id for polling. Supports camera control via [command] syntax in prompts.",
        "operationId": "submitVideoJob",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["prompt"],
                "properties": {
                  "model": {
                    "type": "string",
                    "default": "MiniMax-Hailuo-2.3",
                    "enum": ["MiniMax-Hailuo-2.3", "MiniMax-Hailuo-2.3-Fast"]
                  },
                  "prompt": {
                    "type": "string",
                    "maxLength": 2000,
                    "description": "Video description. Use [command] for camera control."
                  },
                  "duration": {
                    "type": "integer",
                    "default": 6,
                    "description": "Duration in seconds"
                  },
                  "resolution": {
                    "type": "string",
                    "enum": ["720P", "768P", "1080P"],
                    "default": "1080P"
                  },
                  "prompt_optimizer": {
                    "type": "boolean",
                    "default": true
                  }
                }
              },
              "example": {
                "prompt": "A cinematic sunset over mountains [Push in]",
                "model": "MiniMax-Hailuo-2.3",
                "resolution": "1080P"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Job submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "task_id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "model": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/media/video/status": {
      "get": {
        "tags": ["Media"],
        "summary": "Poll video job status",
        "description": "Check video generation job status and retrieve download URL when complete.",
        "operationId": "getVideoStatus",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "task_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Task ID from video submission"
          }
        ],
        "responses": {
          "200": {
            "description": "Video status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "task_id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "file_id": {
                          "type": "string"
                        },
                        "download_url": {
                          "type": "string"
                        },
                        "error": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/fashion/run": {
      "post": {
        "tags": ["Fashion"],
        "summary": "Submit fashion generation job",
        "description": "Submit an AI fashion image generation job. Returns immediately with a prediction ID. Poll /api/v1/fashion/status/{id} for results, or use /api/v1/fashion/subscribe for SSE streaming.\n\nModels: tryon-v1.6, product-to-model, face-to-model, model-create, model-variation, model-swap, reframe, background-change, background-remove, image-to-video.",
        "operationId": "submitFashionJob",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FashionRunRequest"
              },
              "examples": {
                "tryon": {
                  "summary": "Virtual try-on",
                  "value": {
                    "model_name": "tryon-v1.6",
                    "inputs": {
                      "model_image": "https://example.com/person.jpg",
                      "garment_image": "https://example.com/shirt.jpg",
                      "category": "tops",
                      "mode": "quality"
                    }
                  }
                },
                "backgroundRemove": {
                  "summary": "Background removal",
                  "value": {
                    "model_name": "background-remove",
                    "inputs": {
                      "image": "https://example.com/product.jpg"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Job submitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FashionRunResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ModelUnavailable"
          }
        }
      }
    },
    "/api/v1/fashion/status/{id}": {
      "get": {
        "tags": ["Fashion"],
        "summary": "Poll job status",
        "description": "Check fashion generation job status. CDN URLs available for 72 hours.",
        "operationId": "getFashionStatus",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Prediction ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Job status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FashionStatusResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/fashion/subscribe": {
      "post": {
        "tags": ["Fashion"],
        "summary": "Submit and stream status via SSE",
        "description": "Submit job and stream real-time status updates. 2-minute timeout \u2014 use /run + /status for long-running jobs.",
        "operationId": "subscribeFashionJob",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FashionRunRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SSE stream. Events: job_submitted, status_update, completed, failed, error. Ends with 'data: [DONE]'.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/admin/keys": {
      "post": {
        "tags": ["Admin"],
        "summary": "Mint an API key (public or server)",
        "description": "Provision a new Concurred API key. Admin token required. Use type='public' for browser-bound keys with origin + spend-cap enforcement; type='server' for uncapped backend keys. Idempotent when externalId is supplied.",
        "operationId": "adminMintKey",
        "security": [
          {
            "AdminAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminMintRequest"
              },
              "example": {
                "type": "public",
                "name": "october-user-42-flutter",
                "externalId": "user-42",
                "allowed_origins": [
                  "https://user-42-web.example.com",
                  "http://localhost:*"
                ],
                "spend_cap_usd_monthly": 10.0,
                "rate_limits": {
                  "rpm": 30
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key minted. Retry with same externalId is idempotent and returns this same payload with X-Idempotent-Replay: true.",
            "headers": {
              "X-Idempotent-Replay": {
                "schema": {
                  "type": "string",
                  "enum": ["true"]
                },
                "description": "Present and 'true' when this response is a replay of a prior mint with the same externalId."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminMintResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Missing, invalid, or unconfigured admin token; or a client ck_ / ck_pub_ key was sent (admin endpoints reject client keys).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/keys/{keyId}": {
      "delete": {
        "tags": ["Admin"],
        "summary": "Revoke a key",
        "description": "Revokes the key in Unkey and deletes its key_metadata row. Any in-flight calls using the key will 401 immediately on their next Unkey verify. Cannot be undone \u2014 to rotate, mint a new key with the same externalId.",
        "operationId": "adminRevokeKey",
        "security": [
          {
            "AdminAuth": []
          }
        ],
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unkey's internal key ID returned from /admin/keys mint."
          }
        ],
        "responses": {
          "204": {
            "description": "Key revoked and metadata deleted."
          },
          "401": {
            "description": "Missing/invalid admin token, or client key sent."
          },
          "502": {
            "description": "Unkey delete call failed. Retry safe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/keys/{keyId}/usage": {
      "get": {
        "tags": ["Admin"],
        "summary": "Read key usage",
        "description": "Current-period spend, cap, percent-of-cap, and frozen state for a key. Poll at ~5-minute cadence to drive partner-side notifications (webhooks are deferred to v3).",
        "operationId": "adminKeyUsage",
        "security": [
          {
            "AdminAuth": []
          }
        ],
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUsageResponse"
                },
                "example": {
                  "keyId": "key_xxxxx",
                  "key_type": "public",
                  "externalId": "user-42",
                  "period": "2026-04",
                  "cap_usd": 10.0,
                  "current_spend_usd": 7.82,
                  "reserved_spend_usd": 0.04,
                  "percent_of_cap": 78.2,
                  "resets_at": "2026-05-01T00:00:00.000Z",
                  "frozen_until": null
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid admin token, or client key sent."
          },
          "404": {
            "description": "Key not found (never existed or was revoked).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/image/generate": {
      "post": {
        "tags": ["Media"],
        "summary": "Generate image",
        "description": "Unified image-generation endpoint spanning Google Imagen 4, BFL Flux, fal.ai (Recraft, Ideogram, SD 3.5, Qwen Image). Accepts ck_ server keys and ck_pub_ public keys \u2014 public keys enforce origin + spend cap.",
        "operationId": "generateImage",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["prompt"],
                "properties": {
                  "model": {
                    "type": "string",
                    "description": "Provider-native model ID. Default: flux-2-pro. See /docs/api/image for the full list."
                  },
                  "prompt": {
                    "type": "string"
                  },
                  "num_images": {
                    "type": "integer",
                    "minimum": 1,
                    "default": 1
                  },
                  "aspect_ratio": {
                    "type": "string"
                  },
                  "width": {
                    "type": "integer"
                  },
                  "height": {
                    "type": "integer"
                  },
                  "image_size": {
                    "type": "string"
                  },
                  "seed": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Image(s) generated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "model": {
                          "type": "string"
                        },
                        "provider": {
                          "type": "string"
                        },
                        "images": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "url": {
                                "type": "string"
                              },
                              "base64": {
                                "type": "string"
                              },
                              "mimeType": {
                                "type": "string"
                              },
                              "width": {
                                "type": "integer"
                              },
                              "height": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/OriginNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/SpendCapExceeded"
          }
        }
      }
    },
    "/api/v1/image/edit": {
      "post": {
        "tags": ["Media"],
        "summary": "Edit an image with a text prompt",
        "description": "Image-to-image editing via Flux Kontext (BFL), Qwen Image Edit (fal.ai), or Seedream 5 (fal.ai). Accepts the same key classes as /image/generate.",
        "operationId": "editImage",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["prompt", "image_url"],
                "properties": {
                  "model": {
                    "type": "string"
                  },
                  "prompt": {
                    "type": "string"
                  },
                  "image_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "seed": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Edited image(s)."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/OriginNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/SpendCapExceeded"
          }
        }
      }
    },
    "/api/v1/video/generate": {
      "post": {
        "tags": ["Media"],
        "summary": "Generate video (sync or async)",
        "description": "Unified video-generation endpoint. fal.ai models (Kling, Wan) block until complete. Google Veo returns an operation_id + poll_url \u2014 poll /api/v1/video/status. Async ops: the minting key is the only key authorized to poll that operation.",
        "operationId": "generateVideo",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["prompt"],
                "properties": {
                  "model": {
                    "type": "string"
                  },
                  "prompt": {
                    "type": "string"
                  },
                  "image_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "duration": {
                    "type": "string",
                    "enum": ["4", "6", "8"]
                  },
                  "aspect_ratio": {
                    "type": "string"
                  },
                  "resolution": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "For fal.ai: completed video_url. For Google Veo: operation_id + poll_url (status = processing).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "model": {
                          "type": "string"
                        },
                        "provider": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": ["processing", "completed"]
                        },
                        "operation_id": {
                          "type": "string"
                        },
                        "poll_url": {
                          "type": "string"
                        },
                        "video_url": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/OriginNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/SpendCapExceeded"
          }
        }
      }
    },
    "/api/v1/video/status": {
      "get": {
        "tags": ["Media"],
        "summary": "Poll async video job status",
        "description": "For public keys (ck_pub_): only the key that submitted the operation may poll it. Foreign polls return 403 NOT_YOUR_OPERATION. Settlement happens on the first terminal poll (idempotent \u2014 repeat polls are safe).",
        "operationId": "getVideoStatus",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "provider",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": ["google"]
            }
          },
          {
            "name": "operation_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Operation status \u2014 done=false means still processing; done=true with video_url means complete; done=true with error means failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "provider": {
                          "type": "string"
                        },
                        "operation_id": {
                          "type": "string"
                        },
                        "done": {
                          "type": "boolean"
                        },
                        "video_url": {
                          "type": "string"
                        },
                        "error": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NotYourOperation"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key as Bearer token: Authorization: Bearer <ck_... or ck_pub_...>. Server keys (ck_) are backend-only; public keys (ck_pub_) are browser-safe \u2014 origin-bound, spend-capped per UTC month, rate-limited per minute. See /docs/api/public-keys."
      },
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key via X-API-Key header. Accepts both ck_ server keys and ck_pub_ public keys. See /docs/api/public-keys for the public-key safety model."
      },
      "CookieAuth": {
        "type": "apiKey",
        "in": "cookie",
        "name": "sb-access-token",
        "description": "Supabase session cookie (dashboard authentication)"
      },
      "AdminAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Admin token as Bearer: Authorization: Bearer <admin-token>. Configured via CONCURRED_ADMIN_TOKEN (single) or CONCURRED_ADMIN_TOKENS (JSON map of token\u2192label). Distinct from client keys \u2014 ck_ and ck_pub_ keys are rejected on /api/v1/admin/* endpoints with 401."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Unauthorized \u2014 missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            },
            "example": {
              "error": {
                "code": "UNAUTHORIZED",
                "message": "Authentication required. Provide a valid API key."
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            },
            "example": {
              "error": {
                "code": "RATE_LIMIT_EXCEEDED",
                "message": "Rate limit exceeded. Try again later.",
                "details": {
                  "retryAfter": 60
                }
              }
            }
          }
        }
      },
      "ModelUnavailable": {
        "description": "Model or service temporarily unavailable",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            }
          }
        }
      },
      "OriginNotAllowed": {
        "description": "Public-key origin check failed. The request's Origin header did not match the key's allowed_origins list. Browser CORS also blocks JS from reading the body (A-C-A-O is set to https://concurred.ai, not the caller).",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": ["ORIGIN_NOT_ALLOWED"]
                    },
                    "message": {
                      "type": "string"
                    },
                    "origin": {
                      "type": "string"
                    },
                    "allowed": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "SpendCapExceeded": {
        "description": "Public key's monthly spend cap reached. Cumulative USD spent this UTC month \u2265 spend_cap_usd_monthly. Requests resume at the next UTC month rollover (see resets_at).",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": ["SPEND_CAP_EXCEEDED"]
                    },
                    "message": {
                      "type": "string"
                    },
                    "cap_usd": {
                      "type": "number"
                    },
                    "current_spend_usd": {
                      "type": "number"
                    },
                    "resets_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "NotYourOperation": {
        "description": "Poll-side ownership check failed. The authenticated key did not submit the operation (Veo / Hailuo / Fashn). Poll with the same key that submitted the job.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": ["NOT_YOUR_OPERATION"]
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "HealthResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": ["healthy", "degraded", "unhealthy"]
              },
              "version": {
                "type": "string"
              },
              "timestamp": {
                "type": "string",
                "format": "date-time"
              },
              "uptime": {
                "type": "integer",
                "description": "Uptime in seconds"
              },
              "services": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": ["up", "down", "unknown"]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "GatewayRequest": {
        "type": "object",
        "required": ["model", "messages"],
        "properties": {
          "model": {
            "type": "string",
            "description": "Model ID or alias. Available: claude, gpt, grok, gemini, deepseek, kimi, mistral, llama, minimax (plus version aliases like gpt-5.2, claude-sonnet-4-5, MiniMax-M2.7, M2-her, etc.)"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GatewayMessage"
            },
            "description": "Conversation messages. Supports text and multimodal content."
          },
          "stream": {
            "type": "boolean",
            "default": false,
            "description": "Enable SSE streaming"
          },
          "temperature": {
            "type": "number",
            "minimum": 0,
            "maximum": 2,
            "default": 0.7
          },
          "max_tokens": {
            "type": "integer",
            "description": "Maximum tokens to generate"
          },
          "top_p": {
            "type": "number"
          },
          "frequency_penalty": {
            "type": "number"
          },
          "presence_penalty": {
            "type": "number"
          },
          "stop": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Stop sequences"
          },
          "fallback": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fallback models if primary fails. Tried in order. Example: [\"gpt\", \"gemini\"]"
          },
          "timeout": {
            "type": "integer",
            "minimum": 1000,
            "maximum": 300000,
            "default": 60000,
            "description": "Request timeout in milliseconds"
          },
          "load_balance": {
            "type": "object",
            "description": "Load balance across multiple models",
            "properties": {
              "strategy": {
                "type": "string",
                "enum": ["weighted", "round-robin", "least-latency"]
              },
              "targets": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": ["model"],
                  "properties": {
                    "model": {
                      "type": "string"
                    },
                    "weight": {
                      "type": "number",
                      "description": "Weight for weighted strategy (0-100)"
                    }
                  }
                }
              }
            },
            "required": ["strategy", "targets"]
          },
          "guardrails": {
            "type": "object",
            "description": "Enable input/output guardrails",
            "properties": {
              "enabled": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": ["pii", "content_moderation", "schema_validation"]
                },
                "description": "Guardrails to enable"
              }
            },
            "required": ["enabled"]
          },
          "prompt_id": {
            "type": "string",
            "description": "Langfuse prompt template name"
          },
          "prompt_version": {
            "type": "integer",
            "description": "Prompt template version (default: production)"
          },
          "prompt_variables": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Variables to substitute in prompt template ({{variable}} syntax)"
          }
        }
      },
      "GatewayMessage": {
        "type": "object",
        "required": ["role", "content"],
        "properties": {
          "role": {
            "type": "string",
            "enum": ["system", "user", "assistant"]
          },
          "content": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "description": "Multimodal content array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["text"]
                        },
                        "text": {
                          "type": "string"
                        }
                      },
                      "required": ["type", "text"]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["image_url"]
                        },
                        "image_url": {
                          "type": "object",
                          "properties": {
                            "url": {
                              "type": "string",
                              "format": "uri"
                            },
                            "detail": {
                              "type": "string",
                              "enum": ["auto", "low", "high"]
                            }
                          },
                          "required": ["url"]
                        }
                      },
                      "required": ["type", "image_url"]
                    }
                  ]
                }
              }
            ]
          }
        }
      },
      "GatewayResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "chatcmpl-abc123"
          },
          "object": {
            "type": "string",
            "example": "chat.completion"
          },
          "created": {
            "type": "integer"
          },
          "model": {
            "type": "string"
          },
          "choices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "message": {
                  "type": "object",
                  "properties": {
                    "role": {
                      "type": "string"
                    },
                    "content": {
                      "type": "string"
                    }
                  }
                },
                "finish_reason": {
                  "type": "string"
                }
              }
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": {
                "type": "integer"
              },
              "completion_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              }
            }
          }
        }
      },
      "ModelList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "object": {
                  "type": "string",
                  "example": "model"
                },
                "created": {
                  "type": "integer"
                },
                "owned_by": {
                  "type": "string"
                },
                "_concurred": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "aliases": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "ProviderKeyResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "keyLast4": {
            "type": "string",
            "description": "Last 4 characters of the key (masked)"
          },
          "isActive": {
            "type": "boolean"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ChatRequest": {
        "type": "object",
        "required": ["message", "mode"],
        "properties": {
          "message": {
            "type": "string",
            "maxLength": 2000,
            "description": "Your question or prompt"
          },
          "mode": {
            "type": "string",
            "enum": ["chat", "battle", "fight"]
          },
          "model": {
            "type": "string",
            "description": "Model ID for chat mode"
          },
          "models": {
            "oneOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "string"
              }
            ],
            "description": "Models for battle (2) or fight (2-8). Omit in fight to use all 8."
          },
          "image_url": {
            "type": "string",
            "format": "uri",
            "description": "Image URL for vision analysis"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HistoryMessage"
            },
            "description": "Conversation history for multi-turn context"
          },
          "rounds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 1,
            "description": "Debate rounds for fight mode"
          },
          "agentMode": {
            "type": "string",
            "enum": [
              "multiple-grok",
              "multiple-claude",
              "multiple-gpt",
              "multiple-gemini",
              "multiple-deepseek",
              "multiple-kimi",
              "multiple-mistral",
              "multiple-llama"
            ],
            "description": "Multi-instance mode: 4 instances of the same model"
          },
          "fightStyle": {
            "type": "string",
            "enum": ["brawl", "blitz"],
            "default": "brawl",
            "description": "Fight mode only. 'brawl' (default) runs agents sequentially within a round, each seeing previous peer answers \u2014 a live debate. 'blitz' runs agents in parallel from a frozen context and only carries the previous round's winner forward between rounds."
          },
          "stream": {
            "type": "boolean",
            "default": true,
            "description": "SSE streaming. Must be true for fight mode."
          }
        }
      },
      "HistoryMessage": {
        "type": "object",
        "required": ["role", "content"],
        "properties": {
          "role": {
            "type": "string",
            "enum": ["user", "assistant", "system"]
          },
          "content": {
            "type": "string"
          }
        }
      },
      "ChatModeResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "example": "chat"
          },
          "response": {
            "type": "object",
            "properties": {
              "agent": {
                "type": "string"
              },
              "model": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          },
          "created_at": {
            "type": "integer"
          }
        }
      },
      "BattleModeResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "example": "battle"
          },
          "responses": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "agent": {
                  "type": "string"
                },
                "model": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "citations": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Citation"
                  }
                }
              }
            }
          },
          "created_at": {
            "type": "integer"
          }
        }
      },
      "Citation": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "snippet": {
            "type": "string"
          },
          "publishedDate": {
            "type": "string"
          },
          "favicon": {
            "type": "string"
          },
          "score": {
            "type": "number"
          }
        }
      },
      "VisionRequest": {
        "type": "object",
        "required": ["model", "image", "prompt"],
        "properties": {
          "model": {
            "type": "string"
          },
          "image": {
            "type": "object",
            "required": ["type"],
            "properties": {
              "type": {
                "type": "string",
                "enum": ["image_url", "image_base64"]
              },
              "image_url": {
                "type": "string"
              },
              "image_base64": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "string"
                  },
                  "media_type": {
                    "type": "string",
                    "enum": [
                      "image/png",
                      "image/jpeg",
                      "image/gif",
                      "image/webp"
                    ]
                  }
                }
              }
            }
          },
          "prompt": {
            "type": "string"
          },
          "stream": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "VisionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "vision.completion"
          },
          "model": {
            "type": "string"
          },
          "choices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "message": {
                  "type": "object",
                  "properties": {
                    "role": {
                      "type": "string"
                    },
                    "content": {
                      "type": "string"
                    }
                  }
                },
                "finish_reason": {
                  "type": "string"
                }
              }
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": {
                "type": "integer"
              },
              "completion_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              }
            }
          }
        }
      },
      "FashionRunRequest": {
        "type": "object",
        "required": ["model_name", "inputs"],
        "properties": {
          "model_name": {
            "type": "string",
            "enum": [
              "tryon-v1.6",
              "product-to-model",
              "face-to-model",
              "model-create",
              "model-variation",
              "model-swap",
              "reframe",
              "background-change",
              "background-remove",
              "image-to-video"
            ]
          },
          "inputs": {
            "type": "object",
            "description": "Model-specific inputs. All image params accept URLs or base64.",
            "additionalProperties": true
          }
        }
      },
      "FashionRunResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "prediction_id": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": ["starting"]
              },
              "model_name": {
                "type": "string"
              },
              "created_at": {
                "type": "integer"
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "requestId": {
                "type": "string"
              },
              "timestamp": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "FashionStatusResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "prediction_id": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "starting",
                  "in_queue",
                  "processing",
                  "completed",
                  "failed",
                  "canceled",
                  "time_out"
                ]
              },
              "output": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "nullable": true,
                "description": "CDN URLs when completed. Available for 72 hours."
              },
              "error": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "APIError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "UNAUTHORIZED",
                  "INVALID_API_KEY",
                  "FORBIDDEN",
                  "BAD_REQUEST",
                  "MISSING_REQUIRED_FIELD",
                  "INVALID_MODEL",
                  "INVALID_MESSAGE_LENGTH",
                  "STREAMING_REQUIRED",
                  "RATE_LIMIT_EXCEEDED",
                  "MODEL_UNAVAILABLE",
                  "GUARDRAIL_BLOCKED",
                  "INTERNAL_ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        }
      },
      "AdminMintRequest": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["public", "server"],
            "description": "Key class. Default 'public'. Server keys have no origin binding and no spend cap \u2014 only for backends where you control invocation."
          },
          "name": {
            "type": "string",
            "description": "User-friendly key name"
          },
          "externalId": {
            "type": "string",
            "description": "Partner-supplied stable ID. Enables idempotent retries: reposting the same externalId returns the original response with X-Idempotent-Replay: true."
          },
          "owner_user_id": {
            "type": "string",
            "description": "Optional Supabase user UUID to attribute ownership to (surfaces the key in the user's dashboard)."
          },
          "allowed_origins": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Required when type=public, must be an array (use [] for native-mobile-only keys). Exact origin URLs or single-port wildcard (http://localhost:*). Native mobile clients do not send Origin and are not gated by this list \u2014 the spend cap is their only protection. Browser clients with no matching entry get 403.",
            "minItems": 0
          },
          "spend_cap_usd_monthly": {
            "type": "number",
            "description": "Required when type=public. Positive USD ceiling on spend per UTC month."
          },
          "rate_limits": {
            "type": "object",
            "properties": {
              "rpm": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000
              }
            },
            "description": "Per-key rate limit. Defaults to 60 rpm for public keys, unlimited for server keys."
          }
        }
      },
      "AdminMintResponse": {
        "type": "object",
        "properties": {
          "keyId": {
            "type": "string",
            "description": "Unkey's internal key ID; used for /admin/keys/{keyId}/usage and DELETE"
          },
          "key": {
            "type": "string",
            "description": "The full key secret. SHOWN ONCE \u2014 store it immediately. Format: ck_... or ck_pub_..."
          },
          "type": {
            "type": "string",
            "enum": ["public", "server"]
          },
          "prefix": {
            "type": "string",
            "enum": ["ck", "ck_pub"]
          },
          "name": {
            "type": "string"
          },
          "externalId": {
            "type": "string",
            "nullable": true
          },
          "allowed_origins": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "spend_cap_usd_monthly": {
            "type": "number",
            "nullable": true
          },
          "rate_limits": {
            "type": "object",
            "properties": {
              "rpm": {
                "type": "integer"
              }
            },
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "AdminUsageResponse": {
        "type": "object",
        "properties": {
          "keyId": {
            "type": "string"
          },
          "key_type": {
            "type": "string",
            "enum": ["public", "server"]
          },
          "externalId": {
            "type": "string",
            "nullable": true
          },
          "period": {
            "type": "string",
            "description": "UTC billing month (YYYY-MM)"
          },
          "cap_usd": {
            "type": "number",
            "nullable": true,
            "description": "Monthly cap. null for server keys (uncapped)."
          },
          "current_spend_usd": {
            "type": "number",
            "description": "Confirmed spend this period (settled)."
          },
          "reserved_spend_usd": {
            "type": "number",
            "description": "Currently-reserved spend on in-flight requests. Held transiently during provider calls; released on completion."
          },
          "percent_of_cap": {
            "type": "number",
            "nullable": true,
            "description": "current_spend_usd / cap_usd \u00d7 100. null when key is uncapped."
          },
          "resets_at": {
            "type": "string",
            "format": "date-time",
            "description": "Start of the next UTC month \u2014 when the meter resets."
          },
          "frozen_until": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Non-null when the key has hit its cap and is frozen. Requests return 429 SPEND_CAP_EXCEEDED until this time passes."
          }
        }
      }
    }
  }
}
