{
  "openapi": "3.1.0",
  "info": {
    "title": "Ozma API",
    "version": "1.0.0",
    "description": "Ozma control plane and gateway proxy API. Auth: Bearer `ozma_live_…` API key (register/CLI/MCP) for catalog + gateway calls, or a session token (login/signup) for billing + provider routes. Standard envelope on every response: `{ ok, data | error, meta: { request_id } }`."
  },
  "servers": [
    { "url": "https://api.ozma.app", "description": "Control plane" },
    { "url": "https://gateway.ozma.app", "description": "Data plane" }
  ],
  "paths": {
    "/v1/register": {
      "post": {
        "summary": "Agent auto-registration (no auth)",
        "description": "Mints an API key with 0 credits. Free catalog APIs work immediately; paid APIs need a payment method or human signup credits.",
        "responses": {
          "201": {
            "description": "Ephemeral org + API key, 0 starter credits",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "data": {
                      "type": "object",
                      "properties": {
                        "org_id": { "type": "string" },
                        "api_key": { "type": "string" },
                        "credit_cents": { "type": "integer" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup": {
      "post": {
        "summary": "Self-serve human signup (no auth)",
        "description": "Creates an account + API key + session token. Grants $1 trial credits (may require email verification before credits are usable).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email"],
                "properties": {
                  "email": { "type": "string", "format": "email" },
                  "name": { "type": "string" },
                  "turnstile_token": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "201": { "description": "Account + API key + session token + starter credits" }
        }
      }
    },
    "/v1/search": {
      "get": {
        "summary": "Search / browse the API catalog",
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string" }, "description": "Free-text or empty to browse" },
          { "name": "category", "in": "query", "schema": { "type": "string" } },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["ozma_score", "price", "relevance", "new", "calls", "gmv", "reliability", "value", "momentum"]
            }
          },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "maximum": 500, "default": 50 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "default": 0 } }
        ],
        "responses": {
          "200": { "description": "Ranked array of catalog listings (hybrid vector + keyword search)" }
        }
      }
    },
    "/v1/categories": {
      "get": {
        "summary": "List marketplace categories",
        "responses": {
          "200": {
            "description": "Categories with live API counts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": { "type": "string" },
                          "name": { "type": "string" },
                          "api_count": { "type": "integer" }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/providers": {
      "get": {
        "summary": "List public provider profiles",
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer" } },
          { "name": "offset", "in": "query", "schema": { "type": "integer" } }
        ],
        "responses": { "200": { "description": "Paginated provider directory" } }
      }
    },
    "/v1/providers/{slug}": {
      "get": {
        "summary": "Public provider profile by slug",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Profile, trust badges, stats, live APIs" } }
      }
    },
    "/v1/me/profile": {
      "get": {
        "summary": "Get your org profile",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Own profile including private fields" } }
      },
      "patch": {
        "summary": "Update your org profile",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Updated profile" } }
      }
    },
    "/v1/me/avatar": {
      "post": {
        "summary": "Upload avatar image (png/jpeg/webp ≤ 2MB)",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "avatar_url + profile" } }
      }
    },
    "/v1/apis/{slug}": {
      "get": {
        "summary": "Full listing detail for one API",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Listing detail (summary, tags, merit scores, pricing)" } }
      }
    },
    "/v1/apis/{slug}/schema": {
      "get": {
        "summary": "Endpoint input/output schemas for an API",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Endpoint schemas" } }
      }
    },
    "/v1/apis/{slug}/openapi": {
      "get": {
        "summary": "Live OpenAPI 3.0 document for an API listing",
        "description": "Returns the raw OpenAPI document (no Ozma envelope) on success.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "OpenAPI 3.0 JSON document" } }
      }
    },
    "/v1/keys": {
      "get": {
        "summary": "List your API keys",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Array of key summaries (id, keyPrefix, scopes, caps, spend)" } }
      },
      "post": {
        "summary": "Create a new scoped API key",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name"],
                "properties": {
                  "name": { "type": "string" },
                  "scopes": { "type": "array", "items": { "type": "string" } },
                  "budget_cents": { "type": "integer" }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "New key (id + plaintext key, shown once)" } }
      }
    },
    "/v1/keys/{id}": {
      "patch": {
        "summary": "Update budget caps / approval mode on a key",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "budget_cents": { "type": "integer" },
                  "per_call_max_cents": { "type": "integer" },
                  "daily_cap_cents": { "type": "integer" },
                  "approval_mode": { "type": "boolean" }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Updated" } }
      },
      "delete": {
        "summary": "Revoke an API key",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Revoked" } }
      }
    },
    "/v1/billing/balance": {
      "get": {
        "summary": "Prepaid credit balance and billing status",
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "credit_cents, billing_mode, auto_reload_enabled, has_payment_method, suspended",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "data": {
                      "type": "object",
                      "properties": {
                        "credit_cents": { "type": "integer" },
                        "billing_mode": { "type": "string" },
                        "auto_reload_enabled": { "type": "boolean" },
                        "has_payment_method": { "type": "boolean" },
                        "suspended": { "type": "boolean" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/checkout": {
      "post": {
        "summary": "Create a Stripe Checkout session to buy prepaid credits",
        "description": "Requires a session token with `billing:write` (sign in at https://ozma.app/dashboard or `ozma login --email`). A bare `ozma_register`/`ozma_live_…` API key cannot call this. Usage billing via a card on file (see /v1/billing/setup-intent or the dashboard) is recommended over one-off packs.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "pack": { "type": "string", "description": "See GET /v1/billing/packs" },
                  "amount_cents": { "type": "integer" },
                  "success_url": { "type": "string", "format": "uri" },
                  "cancel_url": { "type": "string", "format": "uri" }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Stripe Checkout session URL" } }
      }
    },
    "/v1/billing/portal": {
      "post": {
        "summary": "Get a Stripe Billing Portal link",
        "description": "Manage cards, invoices, and receipts. Requires session `billing:write`.",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Stripe Billing Portal URL" } }
      }
    },
    "/v1/leaderboards/{board}": {
      "get": {
        "summary": "Merit-based leaderboard",
        "parameters": [
          {
            "name": "board",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": ["top_grossing", "most_used", "most_reliable", "best_value", "trending", "new_rising"]
            }
          },
          { "name": "category", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Ranked array of listings for the board" } }
      }
    },
    "/v1/provider/apis": {
      "get": {
        "summary": "List your provider APIs",
        "description": "Requires a session token with `provider:write` (see docs/CLI.md `ozma provider`).",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Array of provider-owned API summaries" } }
      },
      "post": {
        "summary": "Create/import a provider API",
        "description": "Import from an OpenAPI spec (endpoints inline) or a source URL (`import_from`). Requires session `provider:write`.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name", "slug", "summary", "base_url"],
                "properties": {
                  "name": { "type": "string" },
                  "slug": { "type": "string" },
                  "summary": { "type": "string" },
                  "base_url": { "type": "string", "format": "uri" },
                  "endpoints": { "type": "array", "items": { "type": "object" } },
                  "import_from": {
                    "type": "object",
                    "properties": {
                      "type": { "type": "string", "enum": ["openapi_url", "rapidapi_url"] },
                      "url": { "type": "string", "format": "uri" }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "Draft provider API" } }
      }
    },
    "/v1/proxy/{apiSlug}/{path}": {
      "get": {
        "summary": "Gateway proxy call (data plane, gateway.ozma.app)",
        "description": "Proxies a metered call to the upstream API. Method/body pass through for non-GET; only GET is shown here for brevity — any method the upstream endpoint supports is allowed. Billed per-call unless the endpoint is free or the upstream call fails (failed calls are not billed).",
        "servers": [{ "url": "https://gateway.ozma.app" }],
        "parameters": [
          { "name": "apiSlug", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "path", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": { "description": "Upstream response, wrapped in Ozma envelope metadata via headers" },
          "402": { "description": "Insufficient credits — add a payment method at https://ozma.app/dashboard or top up" },
          "403": { "description": "Key lacks proxy:call scope, budget cap exceeded, or org suspended" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Ozma API key (`ozma_live_…`) for catalog/keys/gateway routes, or a session token (from /v1/signup or /v1/auth/login/verify) for billing/provider routes — session wins when both are sent."
      }
    }
  }
}
