{
  "openapi": "3.1.0",
  "info": {
    "title": "Screenshot API — Development Preview",
    "version": "0.3.0-preview",
    "summary": "Feature-gated asynchronous screenshot jobs for developers and AI agents.",
    "description": "This is not an available production API. The local control-plane endpoints, durable job model, validation, idempotency, usage reservation, and cancellation are implemented. Browser rendering, worker network enforcement, object storage, accounts, billing products, and production activation remain unavailable."
  },
  "servers": [
    {
      "url": "https://api-screenshot.com/v1",
      "description": "Public preview origin. API routes currently return HTTP 503 until production activation."
    },
    {
      "url": "http://127.0.0.1:8081/v1",
      "description": "Local development only. The API feature flag remains off by default."
    }
  ],
  "externalDocs": {
    "description": "Human-readable Screenshot API documentation",
    "url": "https://api-screenshot.com/docs"
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Screenshots",
      "description": "Create, inspect, and cancel asynchronous screenshot jobs."
    },
    {
      "name": "Usage",
      "description": "Inspect reserved and consumed screenshot credits."
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Inspect control-plane schema readiness",
        "security": [],
        "responses": {
          "200": {
            "description": "The control-plane schema is ready."
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/screenshots": {
      "post": {
        "operationId": "createScreenshot",
        "summary": "Create an asynchronous screenshot job",
        "tags": ["Screenshots"],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateScreenshotRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "An earlier equivalent request with the same Idempotency-Key is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScreenshotResponse"
                }
              }
            }
          },
          "202": {
            "description": "The bounded screenshot job was accepted and its credit reserved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScreenshotResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/screenshots/{screenshot_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ScreenshotId"
        }
      ],
      "get": {
        "operationId": "getScreenshot",
        "summary": "Retrieve screenshot job state and result metadata",
        "tags": ["Screenshots"],
        "responses": {
          "200": {
            "description": "Current job state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScreenshotResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "operationId": "deleteScreenshot",
        "summary": "Cancel an active job or request deletion of a terminal job",
        "tags": ["Screenshots"],
        "responses": {
          "202": {
            "description": "Cancellation or deletion was accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScreenshotResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Retrieve current credit and concurrency usage",
        "tags": ["Usage"],
        "responses": {
          "200": {
            "description": "Metered usage for the authenticated account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Screenshot API key"
      }
    },
    "parameters": {
      "ScreenshotId": {
        "name": "screenshot_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^shot_[A-Za-z0-9]+$"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "A visible ASCII value, 8 to 128 characters. Reusing it with different request data returns HTTP 409.",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      }
    },
    "schemas": {
      "Viewport": {
        "type": "object",
        "additionalProperties": false,
        "required": ["width", "height"],
        "properties": {
          "width": {
            "type": "integer",
            "minimum": 320,
            "maximum": 3840
          },
          "height": {
            "type": "integer",
            "minimum": 240,
            "maximum": 2160
          },
          "device_scale_factor": {
            "type": "number",
            "minimum": 0.5,
            "maximum": 3,
            "default": 1
          }
        }
      },
      "CreateScreenshotRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["url"],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Public HTTP or HTTPS URL without embedded credentials. Private and special-use destinations are rejected."
          },
          "preset": {
            "type": "string",
            "enum": ["desktop", "mobile"],
            "default": "desktop",
            "description": "Mutually exclusive with viewport."
          },
          "viewport": {
            "$ref": "#/components/schemas/Viewport"
          },
          "full_page": {
            "type": "boolean",
            "default": false
          },
          "format": {
            "type": "string",
            "enum": ["png", "jpeg", "webp"],
            "default": "png"
          },
          "quality": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "Available only for JPEG and WebP."
          },
          "wait_until": {
            "type": "string",
            "enum": ["load", "domcontentloaded", "networkidle"],
            "default": "load"
          },
          "delay_ms": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "default": 0
          },
          "block_ads": {
            "type": "boolean",
            "default": false
          },
          "block_cookie_banners": {
            "type": "boolean",
            "default": false
          },
          "block_chat_widgets": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "Artifact": {
        "type": "object",
        "required": ["id", "mime_type", "byte_count", "sha256", "width", "height", "expires_at"],
        "properties": {
          "id": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "byte_count": {
            "type": "integer",
            "minimum": 1
          },
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "width": {
            "type": "integer",
            "minimum": 1
          },
          "height": {
            "type": "integer",
            "minimum": 1
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "download_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "A short-lived, account-authorized S3-compatible GET URL. Null after artifact expiry."
          },
          "download_expires_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "Expiry of the current download URL, never later than the artifact expiry."
          }
        }
      },
      "ScreenshotJob": {
        "type": "object",
        "required": ["id", "status", "url", "options", "attempt_count", "format", "created_at"],
        "properties": {
          "id": {
            "type": "string",
            "examples": ["shot_01KEXAMPLE"]
          },
          "status": {
            "type": "string",
            "enum": ["queued", "claimed", "rendering", "uploading", "succeeded", "failed", "cancel_requested", "canceled", "deleting", "deleted"]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "options": {
            "type": "object",
            "additionalProperties": true
          },
          "attempt_count": {
            "type": "integer",
            "minimum": 0
          },
          "final_url": {
            "type": ["string", "null"],
            "format": "uri"
          },
          "width": {
            "type": ["integer", "null"],
            "minimum": 1
          },
          "height": {
            "type": ["integer", "null"],
            "minimum": 1
          },
          "format": {
            "type": "string",
            "enum": ["png", "jpeg", "webp"]
          },
          "duration_ms": {
            "type": ["integer", "null"],
            "minimum": 0
          },
          "artifact": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Artifact"
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Error"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "started_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "completed_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "deleted_at": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        }
      },
      "ScreenshotResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ScreenshotJob"
          }
        }
      },
      "UsageResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "type": "object",
            "required": ["credits_reserved", "credits_consumed", "credits_released", "credits_limit", "credits_remaining", "active_jobs", "concurrency_limit", "period_started_at", "period_ends_at"],
            "properties": {
              "credits_reserved": {
                "type": "integer",
                "minimum": 0
              },
              "credits_consumed": {
                "type": "integer",
                "minimum": 0
              },
              "credits_released": {
                "type": "integer",
                "minimum": 0
              },
              "credits_limit": {
                "type": "integer",
                "minimum": 0
              },
              "credits_remaining": {
                "type": "integer",
                "minimum": 0
              },
              "active_jobs": {
                "type": "integer",
                "minimum": 0
              },
              "concurrency_limit": {
                "type": "integer",
                "minimum": 0
              },
              "period_started_at": {
                "type": "string",
                "format": "date-time"
              },
              "period_ends_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "details": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "Request JSON, render options, Idempotency-Key, or target URL is invalid.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "A valid bearer API key is required.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Conflict": {
        "description": "The Idempotency-Key was already used with different request data, or the job changed concurrently.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "The screenshot job does not exist for this account.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "The account exceeded an applicable request, concurrency, or credit limit.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unavailable": {
        "description": "The control plane or one of its required dependencies is unavailable.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  }
}
