{
  "openapi": "3.1.0",
  "info": {
    "title": "Photo AI Studio Agent API",
    "version": "1.0.0",
    "summary": "Generate professional AI photos, edit images, and create video from a selfie — programmatically.",
    "description": "Machine-readable API surface for AI agents. Public discovery endpoints (capabilities, themes, products) require no authentication; generation and account endpoints use a Bearer token plus an X-Buyer-Email header identifying the end user. Also reachable over the Model Context Protocol at /api/mcp (manifest at /.well-known/mcp) and, for interactive checkout, the agentic-commerce endpoints under /api/commerce. Credits are the unit of spend (100 credits = 1 photo); prices and packages are in the product feed and at /pricing.\n\nVersioning: this is v1. Send an optional `API-Version` request header (date- or number-based, e.g. `2026-08-25` or `1`) to pin behavior; without it, the current stable version is used. Breaking changes ship under a new version value and, where structural, a new `/vN/` path.\n\nDeprecation & sunset policy: a version is supported for at least 6 months after its successor ships. When an endpoint or version is deprecated it returns a `Deprecation: true` header and a `Sunset: <HTTP-date>` header (RFC 8594) giving the earliest removal date, plus a `Link` header with `rel=\"deprecation\"` pointing to migration docs. Removal never happens before the advertised Sunset date.",
    "x-sunset-policy": {
      "minSupportWindowMonths": 6,
      "deprecationHeader": "Deprecation",
      "sunsetHeader": "Sunset",
      "docs": "https://www.photoaistudio.com/for-developers"
    },
    "contact": {
      "name": "Photo AI Studio Support",
      "email": "contact@photoaistudio.com",
      "url": "https://www.photoaistudio.com/contact"
    },
    "termsOfService": "https://www.photoaistudio.com/terms-conditions",
    "license": {
      "name": "Proprietary",
      "url": "https://www.photoaistudio.com/terms-conditions"
    }
  },
  "servers": [
    { "url": "https://www.photoaistudio.com", "description": "Production (v1)" }
  ],
  "externalDocs": {
    "description": "Developer guide, llms.txt, and MCP server",
    "url": "https://www.photoaistudio.com/for-developers"
  },
  "tags": [
    { "name": "Discovery", "description": "Unauthenticated read endpoints for capability, theme, and product discovery." },
    { "name": "Generation", "description": "Authenticated endpoints that spend credits to create or edit media." },
    { "name": "Account", "description": "Authenticated account and prediction-status endpoints." },
    { "name": "Commerce", "description": "Agentic-commerce product feed and checkout (ACP / UCP)." }
  ],
  "paths": {
    "/api/agent/capabilities": {
      "get": {
        "tags": ["Discovery"],
        "operationId": "getCapabilities",
        "summary": "List every operation, parameter, and credit cost",
        "description": "Unauthenticated. Returns the full machine-readable capability descriptor for the agent API.",
        "security": [],
        "parameters": [{ "$ref": "#/components/parameters/ApiVersion" }],
        "responses": {
          "200": { "description": "Capability descriptor", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Capabilities" } } } },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/agent/themes": {
      "get": {
        "tags": ["Discovery"],
        "operationId": "listThemes",
        "summary": "List available photo theme categories",
        "description": "Unauthenticated. Returns the live theme catalog.",
        "security": [],
        "parameters": [
          { "$ref": "#/components/parameters/ApiVersion" },
          { "name": "gender", "in": "query", "required": false, "schema": { "type": "string", "enum": ["male", "female", "unisex"] } },
          { "name": "tag", "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Theme catalog", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThemeList" } } } },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/commerce/products": {
      "get": {
        "tags": ["Discovery", "Commerce"],
        "operationId": "listProducts",
        "summary": "List buyable credit packages with live prices",
        "description": "Unauthenticated. Product feed for agentic commerce (ACP / UCP).",
        "security": [],
        "parameters": [{ "$ref": "#/components/parameters/ApiVersion" }],
        "responses": {
          "200": { "description": "Product feed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProductFeed" } } } },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/agent/account": {
      "get": {
        "tags": ["Account"],
        "operationId": "getAccount",
        "summary": "Get the buyer's account and credit balance",
        "parameters": [{ "$ref": "#/components/parameters/ApiVersion" }],
        "responses": {
          "200": { "description": "Account", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/agent/upload": {
      "post": {
        "tags": ["Generation"],
        "operationId": "uploadImage",
        "summary": "Upload a source selfie/image",
        "parameters": [{ "$ref": "#/components/parameters/ApiVersion" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["image"],
                "properties": { "image": { "type": "string", "description": "Publicly reachable image URL or base64 data URI." } }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Uploaded image reference", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UploadResult" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/agent/generate": {
      "post": {
        "tags": ["Generation"],
        "operationId": "generatePhotos",
        "summary": "Generate themed or custom AI photos from a selfie",
        "description": "Spends credits (100 credits per image). Returns a prediction to poll via /api/agent/predictions/{id}.",
        "parameters": [{ "$ref": "#/components/parameters/ApiVersion" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["images"],
                "properties": {
                  "images": { "type": "array", "items": { "type": "string" }, "description": "Uploaded image URL(s)." },
                  "theme": { "type": "string", "description": "Theme category slug, e.g. professional-headshot." },
                  "prompt": { "type": "string", "description": "Custom prompt when not using a preset theme." },
                  "num_images": { "type": "integer", "minimum": 1, "maximum": 8, "default": 4 }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Prediction created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Prediction" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/agent/edit": {
      "post": {
        "tags": ["Generation"],
        "operationId": "editImage",
        "summary": "AI-edit an image (background removal, retouch, upscale, face swap, and more)",
        "parameters": [{ "$ref": "#/components/parameters/ApiVersion" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["image", "operation"],
                "properties": {
                  "image": { "type": "string" },
                  "operation": { "type": "string", "description": "One of the 19 edit operations (e.g. remove-background, upscale, retouch, face-swap, clothes-try-on)." },
                  "params": { "type": "object", "additionalProperties": true }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Prediction created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Prediction" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/agent/video": {
      "post": {
        "tags": ["Generation"],
        "operationId": "generateVideo",
        "summary": "Create video (image-to-video, UGC, product-holder)",
        "parameters": [{ "$ref": "#/components/parameters/ApiVersion" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["type"],
                "properties": {
                  "type": { "type": "string", "enum": ["image-to-video", "ugc", "product-holder"] },
                  "image": { "type": "string" },
                  "prompt": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Prediction created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Prediction" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/agent/predictions": {
      "get": {
        "tags": ["Account"],
        "operationId": "listPredictions",
        "summary": "List the buyer's recent predictions",
        "parameters": [{ "$ref": "#/components/parameters/ApiVersion" }],
        "responses": {
          "200": { "description": "Predictions", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PredictionList" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/agent/predictions/{id}": {
      "get": {
        "tags": ["Account"],
        "operationId": "getPrediction",
        "summary": "Poll a prediction until state = succeeded",
        "parameters": [
          { "$ref": "#/components/parameters/ApiVersion" },
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Prediction status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Prediction" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "default": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "ApiVersion": {
        "name": "API-Version",
        "in": "header",
        "required": false,
        "description": "Optional API version to pin (date-based e.g. 2026-08-25, or number e.g. 1). Omit to use the current stable version.",
        "schema": { "type": "string", "default": "1" }
      }
    },
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "description": "Commerce API token. Send as: Authorization: Bearer <token>." },
      "buyerEmail": { "type": "apiKey", "in": "header", "name": "X-Buyer-Email", "description": "Email of the end user the agent is acting for. Users are auto-created." }
    },
    "schemas": {
      "Capabilities": {
        "type": "object",
        "properties": {
          "version": { "type": "string" },
          "service": { "type": "string" },
          "auth": { "type": "object", "additionalProperties": true },
          "operations": { "type": "object", "additionalProperties": true }
        }
      },
      "Theme": {
        "type": "object",
        "properties": {
          "slug": { "type": "string" },
          "name": { "type": "string" },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "ThemeList": {
        "type": "object",
        "properties": { "themes": { "type": "array", "items": { "$ref": "#/components/schemas/Theme" } } }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "description": { "type": "string" },
          "unit_amount": { "type": "integer", "description": "Price in the smallest currency unit." },
          "currency": { "type": "string" },
          "credits": { "type": "integer" },
          "photos_equivalent": { "type": "integer" },
          "availability_status": { "type": "string" }
        }
      },
      "ProductFeed": {
        "type": "object",
        "properties": {
          "merchant": { "type": "object", "additionalProperties": true },
          "products": { "type": "array", "items": { "$ref": "#/components/schemas/Product" } }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "email": { "type": "string", "format": "email" },
          "credits": { "type": "integer" }
        }
      },
      "UploadResult": {
        "type": "object",
        "properties": { "url": { "type": "string", "format": "uri" } }
      },
      "Prediction": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "state": { "type": "string", "enum": ["starting", "processing", "succeeded", "failed"] },
          "result_url": { "type": "string", "format": "uri" },
          "credits_spent": { "type": "integer" }
        }
      },
      "PredictionList": {
        "type": "object",
        "properties": { "predictions": { "type": "array", "items": { "$ref": "#/components/schemas/Prediction" } } }
      },
      "Error": {
        "type": "object",
        "description": "Structured JSON error. Agents should branch on `type` and surface `message`; `resolution` hints how to recover.",
        "required": ["type", "message"],
        "properties": {
          "type": { "type": "string", "description": "Stable machine-readable error code (e.g. invalid_request, unauthorized, insufficient_credits, not_found)." },
          "message": { "type": "string", "description": "Human-readable explanation." },
          "resolution": { "type": "string", "description": "How to fix or recover from the error." },
          "status": { "type": "integer", "description": "HTTP status code." }
        }
      }
    },
    "responses": {
      "Error": {
        "description": "Unexpected error",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "BadRequest": {
        "description": "Invalid request",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Unauthorized": {
        "description": "Missing or invalid Authorization header",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "InsufficientCredits": {
        "description": "Not enough credits to complete the operation",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded. See the RateLimit-* / X-RateLimit-* response headers for the policy and reset window.",
        "headers": {
          "RateLimit-Limit": { "schema": { "type": "integer" }, "description": "Requests allowed in the current window." },
          "RateLimit-Remaining": { "schema": { "type": "integer" }, "description": "Requests remaining in the current window." },
          "RateLimit-Reset": { "schema": { "type": "integer" }, "description": "Seconds until the window resets." }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    }
  },
  "security": [
    { "bearerAuth": [], "buyerEmail": [] }
  ]
}
