{
  "openapi": "3.1.0",
  "info": {
    "title": "Kliplot API",
    "version": "1.0.0",
    "description": "Batch-download public media from Instagram, TikTok, Pinterest and Twitter/X. Every link consumes one download from the API key owner's plan; failed links are refunded automatically. API access requires the Pro or Enterprise plan. AI agents can use the same capabilities through the MCP server at /api/mcp."
  },
  "servers": [{ "url": "/" }],
  "security": [{ "apiKey": [] }],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key created in Account → API & AI agents (format: dk_live_…)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable code",
                "enum": [
                  "invalid_api_key", "plan_without_api_access", "unauthenticated", "invalid_urls",
                  "limit_exceeded", "over_batch_limit", "too_many_active_batches", "rate_limited",
                  "not_found", "internal_error"
                ]
              },
              "message": { "type": "string" }
            }
          },
          "usage": { "$ref": "#/components/schemas/UsageSnapshot" },
          "invalid": { "type": "array", "items": { "type": "string" } }
        }
      },
      "UsageSnapshot": {
        "type": "object",
        "properties": {
          "filesInCurrentWindow": { "type": "integer" },
          "maxFilesPerBatch": { "type": "integer" },
          "lastBatchTime": { "type": ["integer", "null"], "description": "Window start (epoch ms)" },
          "cooldownMs": { "type": "integer" },
          "remainingCooldownMs": { "type": "integer" }
        }
      },
      "BatchFile": {
        "type": "object",
        "properties": {
          "type": { "type": "string", "enum": ["video", "image"] },
          "filename": { "type": "string" },
          "download_url": { "type": "string", "format": "uri", "description": "Expires ~1 hour after the response. Fetch the batch again for fresh links." }
        }
      },
      "BatchItem": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "position": { "type": "integer" },
          "url": { "type": "string" },
          "platform": { "type": "string", "enum": ["instagram", "tiktok", "pinterest", "twitter"] },
          "status": { "type": "string", "enum": ["queued", "processing", "done", "failed"] },
          "error": { "type": ["string", "null"] },
          "files": { "type": "array", "items": { "$ref": "#/components/schemas/BatchFile" } },
          "result": { "type": ["object", "null"], "description": "Raw extractor result (used by the web UI)." }
        }
      },
      "Batch": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "status": { "type": "string", "enum": ["queued", "running", "done", "partial", "failed"] },
          "source": { "type": "string", "enum": ["web", "api", "mcp", "cli"] },
          "total": { "type": "integer" },
          "done": { "type": "integer" },
          "failed": { "type": "integer" },
          "created_at": { "type": "string", "format": "date-time" },
          "completed_at": { "type": ["string", "null"], "format": "date-time" },
          "items": { "type": "array", "items": { "$ref": "#/components/schemas/BatchItem" } }
        }
      }
    }
  },
  "paths": {
    "/api/v1/batches": {
      "post": {
        "summary": "Create a batch",
        "description": "Reserves quota for every link (all or nothing) and starts server-side extraction. Poll GET /api/v1/batches/{id} every 1–2 s until status is done, partial or failed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["urls"],
                "properties": {
                  "urls": { "type": "array", "minItems": 1, "maxItems": 100, "items": { "type": "string", "format": "uri" } }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Batch accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "batch": { "$ref": "#/components/schemas/Batch" },
                    "usage": { "$ref": "#/components/schemas/UsageSnapshot" }
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid or unsupported links", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Invalid API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Plan without API access", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Quota, concurrency or rate limit", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "get": {
        "summary": "List recent batches",
        "parameters": [{ "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }],
        "responses": {
          "200": {
            "description": "Batches (without items)",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "batches": { "type": "array", "items": { "$ref": "#/components/schemas/Batch" } } } } } }
          }
        }
      }
    },
    "/api/v1/batches/{id}": {
      "get": {
        "summary": "Get a batch",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Batch with items and fresh download links", "content": { "application/json": { "schema": { "type": "object", "properties": { "batch": { "$ref": "#/components/schemas/Batch" } } } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/v1/usage": {
      "get": {
        "summary": "Plan, limits and current usage",
        "responses": {
          "200": {
            "description": "Usage",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "plan": { "type": "string" },
                    "limits": {
                      "type": "object",
                      "properties": {
                        "max_files_per_window": { "type": "integer" },
                        "cooldown_ms": { "type": "integer" },
                        "max_concurrent_batches": { "type": "integer" },
                        "api_access": { "type": "boolean" }
                      }
                    },
                    "usage": {
                      "type": "object",
                      "properties": {
                        "files_in_current_window": { "type": "integer" },
                        "files_available": { "type": "integer" },
                        "window_started_at": { "type": ["string", "null"], "format": "date-time" },
                        "remaining_cooldown_ms": { "type": "integer" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
