{
  "openapi": "3.1.0",
  "info": {
    "title": "FrameFetch API",
    "version": "1.0.0",
    "description": "Agent-first API that turns any social-video URL (YouTube, YouTube Shorts, TikTok, Instagram Reels, Pinterest, Reddit) into metadata, insights, transcript, and parametrically-sampled frames. Pay per call with prepaid credits, Stripe, or x402 (USDC, no account). An MCP server is also available at POST /mcp.",
    "termsOfService": "https://framefetch.net/impressum",
    "contact": { "name": "FrameFetch", "url": "https://framefetch.net" }
  },
  "servers": [{ "url": "https://framefetch.net" }],
  "security": [{ "bearerAuth": [] }],
  "paths": {
    "/v1/keys": {
      "post": {
        "summary": "Create a self-serve API key (free credit)",
        "security": [],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email" } } } } } },
        "responses": { "200": { "description": "Key created (shown once)", "content": { "application/json": { "schema": { "type": "object", "properties": { "key": { "type": "string" }, "message": { "type": "string" } } } } } }, "400": { "$ref": "#/components/responses/Error" }, "429": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/v1/extract": {
      "post": {
        "summary": "Extract data from a video URL",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtractRequest" } } } },
        "responses": { "200": { "description": "Extraction result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtractResult" } } } }, "400": { "$ref": "#/components/responses/Error" }, "401": { "$ref": "#/components/responses/Error" }, "402": { "$ref": "#/components/responses/Error" }, "429": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/v1/metadata": { "post": { "summary": "Metadata + insights only", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UrlBody" } } } }, "responses": { "200": { "description": "Result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtractResult" } } } } } } },
    "/v1/transcript": { "post": { "summary": "Transcript only", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UrlBody" } } } }, "responses": { "200": { "description": "Result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtractResult" } } } } } } },
    "/v1/frames": { "post": { "summary": "Frames only (requires a frames spec)", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtractRequest" } } } }, "responses": { "200": { "description": "Result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtractResult" } } } } } } },
    "/v1/platforms": { "get": { "summary": "Per-platform capability matrix", "security": [], "responses": { "200": { "description": "Capabilities keyed by platform", "content": { "application/json": { "schema": { "type": "object" } } } } } } },
    "/v1/topup": { "post": { "summary": "Top up credit via x402 (USDC). Without payment returns 402 with x402 requirements; pay and retry with X-PAYMENT.", "responses": { "200": { "description": "Credited" }, "402": { "description": "x402 payment requirements" } } } },
    "/v1/checkout": { "post": { "summary": "Create a Stripe Checkout session (humans)", "responses": { "200": { "description": "Checkout URL", "content": { "application/json": { "schema": { "type": "object", "properties": { "url": { "type": "string" } } } } } } } } },
    "/healthz": { "get": { "summary": "Health check", "security": [], "responses": { "200": { "description": "OK" } } } }
  },
  "components": {
    "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "description": "API key from POST /v1/keys, sent as 'Authorization: Bearer <key>'." } },
    "responses": { "Error": { "description": "Error envelope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } },
    "schemas": {
      "UrlBody": { "type": "object", "required": ["url"], "properties": { "url": { "type": "string", "format": "uri", "description": "Supported hosts only: youtube.com, youtu.be, tiktok.com, instagram.com, pinterest.*, reddit.com, redd.it" } } },
      "ExtractRequest": {
        "type": "object", "required": ["url"],
        "properties": {
          "url": { "type": "string", "format": "uri" },
          "fields": { "type": "array", "items": { "type": "string", "enum": ["metadata", "insights", "transcript", "frames"] }, "default": ["metadata"] },
          "frames": { "$ref": "#/components/schemas/FrameSpec" },
          "verbosity": { "type": "string" }
        }
      },
      "FrameSpec": {
        "type": "object",
        "properties": {
          "mode": { "type": "string", "enum": ["all", "every_n", "fps", "range"] },
          "n": { "type": "integer", "minimum": 1 },
          "fps": { "type": "number", "maximum": 60 },
          "from": { "type": "number" }, "to": { "type": "number" },
          "format": { "type": "string", "enum": ["jpg", "png", "webp"] },
          "width": { "type": "integer", "minimum": 16, "maximum": 7680 }
        }
      },
      "ExtractResult": {
        "type": "object",
        "properties": {
          "platform": { "type": "string" },
          "url": { "type": "string" },
          "metadata": { "type": "object" },
          "insights": { "type": "object" },
          "transcript": { "type": "object", "properties": { "text": { "type": "string" }, "source": { "type": "string" } } },
          "frames": { "type": "array", "items": { "type": "object", "properties": { "index": { "type": "integer" }, "url": { "type": "string" }, "tSec": { "type": "number" } } } },
          "cost": { "type": "object", "properties": { "totalMicros": { "type": "integer" }, "breakdownMicros": { "type": "object" } } }
        }
      },
      "Error": { "type": "object", "properties": { "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" }, "hint": { "type": "string" } } } } }
    }
  }
}
