{
  "openapi": "3.1.0",
  "info": {
    "title": "Media API",
    "version": "0.7.0-local",
    "description": "Resolve public media links and choose direct, streamed or temporary stored delivery. The same local API also exposes independent public-data scraping operations, source discovery and optional asynchronous jobs."
  },
  "servers": [
    {
      "url": "http://127.0.0.1:8098"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "description": "Optional retry key. Reuses the operation for 24 hours; the in-memory replay result lasts at most one minute."
      }
    },
    "schemas": {
      "Request": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Public media post, current Instagram Stories account link, one active Story, or saved Instagram highlight collection. Optional story_media_id selects one collection item."
          },
          "media": {
            "type": "string",
            "enum": [
              "all",
              "video",
              "audio"
            ],
            "default": "all"
          },
          "quality": {
            "type": "string",
            "default": "best",
            "pattern": "^(best|[0-9]{3,4})$",
            "description": "Maximum shorter video edge, 144 through 4320, or best. No 1080p cap. Source renditions are preserved; unavailable lower qualities are not transcoded."
          },
          "proxy_mode": {
            "$ref": "#/components/schemas/ProxyMode"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "retryable",
              "request_id"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Safe public code. Optional routing errors include paid_attempt_limit, paid_byte_limit, paid_operation_limit, paid_route_cooldown, paid_capacity, paid_grant_closed, paid_route_unavailable, paid_route_expired, paid_media_disabled, provider_authentication_failed, provider_forbidden_host and provider_unavailable. Responses never include provider endpoints, credentials or private grant tokens."
              },
              "message": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "request_id": {
                "type": "string"
              },
              "requires": {
                "type": "string",
                "description": "Optional missing runtime, access or integration requirement for scraper errors."
              }
            }
          }
        }
      },
      "Result": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "resolved_at": {
            "type": "string",
            "format": "date-time"
          },
          "refresh_after": {
            "type": "string",
            "format": "date-time"
          },
          "client_access": {
            "const": "source_dependent"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "type": {
                  "enum": [
                    "video",
                    "audio",
                    "image"
                  ]
                },
                "formats": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Format"
                  }
                },
                "recommended_format_ids": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "author": {
            "type": "string"
          },
          "routing": {
            "$ref": "#/components/schemas/MediaRouting"
          }
        }
      },
      "Format": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "type": {
            "enum": [
              "video",
              "audio",
              "image"
            ]
          },
          "protocol": {
            "type": "string"
          },
          "width": {
            "type": "integer"
          },
          "height": {
            "type": "integer"
          },
          "has_audio": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "requires_merge": {
            "type": "boolean"
          },
          "direct_available": {
            "type": "boolean"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "validation": {
            "type": "string",
            "enum": [
              "metadata",
              "range"
            ]
          },
          "delivery_requires_proxy": {
            "type": "boolean",
            "description": "Extraction used a paid route; the source may bind this URL to its IP. Server streaming/storage requires explicit private allow_paid_media permission, a live owned route and remaining shared paid allowance. A client may try the source URL from its own connection."
          }
        }
      },
      "Direct": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string"
          },
          "operation_id": {
            "type": "string"
          },
          "result": {
            "$ref": "#/components/schemas/Result"
          },
          "usage": {
            "type": "object"
          },
          "cache_hit": {
            "type": "boolean"
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "client": {
            "type": "object"
          },
          "day": {
            "type": "string",
            "format": "date"
          },
          "timezone": {
            "const": "UTC"
          },
          "successful_requests": {
            "type": "integer"
          },
          "reserved_requests": {
            "type": "integer"
          },
          "history": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "string",
                  "format": "date"
                },
                "successful_requests": {
                  "type": "integer"
                },
                "tunnel_requests": {
                  "type": "integer",
                  "minimum": 0
                },
                "tunnel_bytes": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            }
          },
          "money_charged": {
            "const": false
          },
          "tunnel_requests": {
            "type": "integer",
            "minimum": 0
          },
          "tunnel_bytes": {
            "type": "integer",
            "minimum": 0
          },
          "tunnel_reserved_bytes": {
            "type": "integer",
            "minimum": 0
          },
          "tunnel_daily_byte_limit": {
            "type": "integer",
            "minimum": 0
          },
          "storage": {
            "type": "object",
            "properties": {
              "files": {
                "type": "integer"
              },
              "bytes": {
                "type": "integer"
              },
              "ttl_seconds": {
                "type": "integer"
              },
              "instance_capacity_bytes": {
                "type": "integer"
              },
              "reserved_bytes": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        }
      },
      "TunnelRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "operation_id",
          "format_id"
        ],
        "properties": {
          "operation_id": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "item_index": {
            "type": "integer",
            "minimum": 0,
            "default": 0
          },
          "format_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          }
        }
      },
      "Tunnel": {
        "type": "object",
        "required": [
          "url",
          "expires_at",
          "max_requests",
          "max_bytes",
          "usage"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri-reference",
            "description": "Relative capability URL on this API. GET requires no API key; keep the URL private."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "max_requests": {
            "type": "integer",
            "const": 3
          },
          "max_bytes": {
            "type": "integer"
          },
          "usage": {
            "type": "object",
            "properties": {
              "operation_units": {
                "const": 0
              },
              "money_charged": {
                "const": false
              }
            }
          },
          "mode": {
            "const": "tunnel"
          }
        }
      },
      "DeliveryRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "operation_id",
          "format_id"
        ],
        "properties": {
          "operation_id": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "item_index": {
            "type": "integer",
            "minimum": 0,
            "default": 0
          },
          "format_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          },
          "mode": {
            "type": "string",
            "enum": [
              "auto",
              "direct",
              "tunnel",
              "stored"
            ],
            "default": "auto"
          },
          "failed_modes": {
            "type": "array",
            "maxItems": 3,
            "items": {
              "enum": [
                "direct",
                "tunnel",
                "stored"
              ]
            },
            "description": "Modes the client actually attempted and could not download. The API cannot observe a direct CDN download."
          }
        }
      },
      "DeliveryDirect": {
        "type": "object",
        "required": [
          "mode",
          "url"
        ],
        "properties": {
          "mode": {
            "const": "direct"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "StoredFile": {
        "type": "object",
        "required": [
          "mode",
          "id",
          "status",
          "status_url",
          "expires_at"
        ],
        "properties": {
          "mode": {
            "const": "stored"
          },
          "id": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "status": {
            "enum": [
              "downloading",
              "ready",
              "failed"
            ]
          },
          "status_url": {
            "type": "string",
            "format": "uri-reference"
          },
          "url": {
            "type": "string",
            "format": "uri-reference",
            "description": "Private capability URL, present only after the complete original file is stored."
          },
          "size_bytes": {
            "type": "integer",
            "minimum": 1
          },
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "content_type": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "retryable"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "request_id": {
                "type": "string"
              }
            }
          }
        }
      },
      "ScrapeRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "source",
          "operation"
        ],
        "properties": {
          "source": {
            "type": "string",
            "minLength": 1,
            "description": "Source identifier from GET /v1/scrapers; the runtime catalog is authoritative."
          },
          "operation": {
            "type": "string",
            "minLength": 1,
            "description": "Operation identifier for the selected source."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Public HTTP(S) target accepted by the selected operation; private addresses and unsafe redirects are rejected."
          },
          "query": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "description": "Source localization; this alone does not select an IP location."
          },
          "language": {
            "type": "string"
          },
          "page": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000,
            "description": "Operation-specific page selector. Native cursors belong in options; supported ranges may be narrower."
          },
          "limit": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200,
            "description": "Maximum returned items, usually at most 100; apple.search supports 200. Zero selects the operation default."
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Explicit source headers. Transport-controlled headers are rejected; the local API key is never implicitly forwarded."
          },
          "options": {
            "type": "object",
            "additionalProperties": true,
            "description": "Operation-specific selectors, filters and runtime options.",
            "properties": {
              "proxy_mode": {
                "$ref": "#/components/schemas/ProxyMode"
              },
              "egress_country": {
                "type": "string",
                "pattern": "^[A-Za-z]{2}$",
                "description": "Required operator pool country; ordinary fallback must satisfy it too."
              },
              "premium": {
                "type": "boolean",
                "description": "Require an operator residential pool."
              },
              "session": {
                "type": "string",
                "description": "Client-scoped sticky routing selector; not a provider credential."
              }
            }
          }
        },
        "examples": [
          {
            "source": "apple",
            "operation": "search",
            "query": "notes",
            "limit": 5
          }
        ]
      },
      "ScraperDescriptor": {
        "type": "object",
        "required": [
          "source",
          "operation",
          "description"
        ],
        "properties": {
          "source": {
            "type": "string"
          },
          "operation": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "Scrapers": {
        "type": "object",
        "required": [
          "sources",
          "features"
        ],
        "properties": {
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScraperDescriptor"
            }
          },
          "features": {
            "type": "object",
            "additionalProperties": true,
            "description": "Current runtime feature availability; configured features do not guarantee access to every upstream source."
          }
        }
      },
      "ScrapeResult": {
        "type": "object",
        "required": [
          "source",
          "operation",
          "fetched_at",
          "data"
        ],
        "properties": {
          "source": {
            "type": "string"
          },
          "operation": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "fetched_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Independent source-operation response. Screenshot operations include the genuine image bytes in image_base64.",
            "properties": {
              "image_base64": {
                "type": "string",
                "contentEncoding": "base64"
              }
            }
          },
          "warnings": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "routing": {
            "$ref": "#/components/schemas/ScraperRouting"
          }
        }
      },
      "ScrapeResponse": {
        "type": "object",
        "required": [
          "request_id",
          "operation_id",
          "result",
          "cache_hit",
          "usage"
        ],
        "properties": {
          "request_id": {
            "type": "string"
          },
          "operation_id": {
            "type": "string"
          },
          "result": {
            "$ref": "#/components/schemas/ScrapeResult"
          },
          "cache_hit": {
            "type": "boolean"
          },
          "usage": {
            "type": "object",
            "required": [
              "operation_units",
              "money_charged"
            ],
            "properties": {
              "operation_units": {
                "type": "integer",
                "minimum": 0
              },
              "money_charged": {
                "const": false
              }
            }
          }
        }
      },
      "ScrapeFailure": {
        "type": "object",
        "required": [
          "code",
          "message",
          "retryable"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "retryable": {
            "type": "boolean"
          },
          "request_id": {
            "type": "string"
          },
          "requires": {
            "type": "string"
          },
          "details": {
            "type": "object",
            "additionalProperties": true,
            "description": "Bounded diagnostics such as individual search-engine failures or sanitized browser stage and network error codes."
          }
        }
      },
      "ScrapeJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "request"
        ],
        "properties": {
          "request": {
            "$ref": "#/components/schemas/ScrapeRequest"
          },
          "callback_url": {
            "type": "string",
            "format": "uri",
            "description": "Optional public HTTP(S) destination without a fragment. Private and loopback destinations are rejected."
          },
          "callback_secret": {
            "type": "string",
            "writeOnly": true,
            "description": "Optional separate HMAC-SHA256 secret held only in memory; never use the API key as this secret."
          }
        }
      },
      "ScrapeJob": {
        "type": "object",
        "required": [
          "id",
          "status",
          "status_url",
          "expires_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed",
              "cancelled"
            ]
          },
          "status_url": {
            "type": "string",
            "format": "uri-reference"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "result": {
            "$ref": "#/components/schemas/ScrapeResponse"
          },
          "error": {
            "$ref": "#/components/schemas/ScrapeFailure"
          }
        },
        "additionalProperties": true,
        "description": "Owned in-memory job status. Additional fields report callback delivery attempts and status. Jobs expire after 15 minutes and do not survive restart."
      },
      "ScrapeCallback": {
        "type": "object",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed",
              "cancelled"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/ScrapeResponse"
          },
          "error": {
            "$ref": "#/components/schemas/ScrapeFailure"
          }
        }
      },
      "ProxyMode": {
        "type": "string",
        "enum": [
          "auto",
          "direct",
          "proxy"
        ],
        "default": "auto",
        "description": "auto tries ordinary egress and permits one eligible paid fallback or a temporary learned preference. direct uses ordinary egress (Squid in Compose). proxy requires an enabled matching operator paid pool. Customers cannot supply provider credentials or endpoints."
      },
      "MediaRouting": {
        "type": "object",
        "required": [
          "mode",
          "attempts",
          "provider_bytes"
        ],
        "properties": {
          "attempts": {
            "type": "integer",
            "minimum": 0
          },
          "provider_bytes": {
            "type": "integer",
            "minimum": 0,
            "description": "Locally metered paid transport bytes, including protocol overhead; not a provider billing estimate."
          },
          "mode": {
            "type": "string",
            "enum": [
              "direct",
              "proxy"
            ],
            "description": "Ordinary local egress or an optional provider route."
          }
        },
        "additionalProperties": false
      },
      "ScraperRouting": {
        "type": "object",
        "required": [
          "mode",
          "attempts",
          "provider_bytes"
        ],
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "direct",
              "proxy"
            ],
            "description": "direct is ordinary egress, through Squid in Compose."
          },
          "attempts": {
            "type": "integer",
            "minimum": 0
          },
          "provider_bytes": {
            "type": "integer",
            "minimum": 0,
            "description": "Locally metered paid transport bytes, including protocol overhead; not a provider billing estimate."
          }
        },
        "additionalProperties": false
      }
    }
  },
  "paths": {
    "/healthz": {
      "get": {
        "operationId": "health",
        "security": [],
        "responses": {
          "200": {
            "description": "Ready"
          }
        }
      }
    },
    "/v1/resolve": {
      "post": {
        "operationId": "resolve",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Request"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resolved source URLs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Direct"
                }
              }
            }
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "usage",
        "responses": {
          "200": {
            "description": "Own UTC daily usage and delivered bytes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "401": {
            "description": "Invalid key"
          }
        }
      }
    },
    "/v1/tunnels": {
      "post": {
        "operationId": "createTunnel",
        "description": "Request a streaming fallback for an owned operation and format. No re-extraction or additional resolution unit. Operation metadata must still be available, at most five minutes after resolution. Progressive files only; no merging, transcoding or media storage.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TunnelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Temporary tunnel capability URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tunnel"
                }
              }
            }
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tunnels/{token}": {
      "get": {
        "operationId": "streamTunnel",
        "security": [],
        "description": "Stream an issued source representation. A single byte range is forwarded when supported by the source. Source headers and API keys are never accepted from the caller. Limits: 256 MiB per GET, ten minutes, three opens per ticket, 1 GiB and three times the resolution quota in transfer attempts per client/UTC day. Disconnect cancels upstream. Partial failures terminate the stream.",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{64}$"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Optional single byte range, such as bytes=0-1023."
          }
        ],
        "responses": {
          "200": {
            "description": "Original source bytes",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Source byte range",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/deliveries": {
      "post": {
        "summary": "Choose a delivery method",
        "description": "No failed modes selects direct; failed direct selects tunnel; failed direct and tunnel select on-demand temporary storage. This uses an owned resolved format and does not repeat extraction or consume a resolution unit. Missing source access cannot be repaired by changing transport. After a direct failure, an already ready stored copy is preferred over a new source transfer.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeliveryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Direct URL, tunnel ticket, or existing ready file",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DeliveryDirect"
                    },
                    {
                      "$ref": "#/components/schemas/Tunnel"
                    },
                    {
                      "$ref": "#/components/schemas/StoredFile"
                    }
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Storage started asynchronously",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoredFile"
                }
              }
            }
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/files": {
      "post": {
        "summary": "Store one owned source format on demand",
        "description": "Original bytes only. No merge or transcode. Returns immediately with an authenticated status URL. Repeated requests reuse the same active/ready file. Defaults: 256 MiB per file, 1 GiB total disk, 15-minute retention after completion, two simultaneous transfers, 64 entries. Source fetch and downloads share the client traffic budget.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TunnelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing file",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoredFile"
                }
              }
            }
          },
          "202": {
            "description": "Download started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoredFile"
                }
              }
            }
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/files/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          }
        }
      ],
      "get": {
        "summary": "Get own file preparation status",
        "responses": {
          "200": {
            "description": "Current state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoredFile"
                }
              }
            }
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete own file or cancel its download",
        "responses": {
          "200": {
            "description": "Deleted or cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/downloads/{token}": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "summary": "Download a complete temporary file",
        "security": [],
        "parameters": [
          {
            "name": "Range",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Original stored bytes; supports one Range. Capability expires after retention or ten downloads. Key revocation blocks new downloads. Restarts invalidate files and remove their bytes.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Original stored bytes; supports one Range. Capability expires after retention or ten downloads. Key revocation blocks new downloads. Restarts invalidate files and remove their bytes.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "head": {
        "summary": "Inspect a stored file without downloading bytes",
        "security": [],
        "responses": {
          "200": {
            "description": "Stored media headers"
          },
          "default": {
            "description": "Structured error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/scrapers": {
      "get": {
        "operationId": "scrapers",
        "summary": "Discover registered source operations and runtime features",
        "responses": {
          "200": {
            "description": "Current source catalog; registration is not proof of live upstream availability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Scrapers"
                }
              }
            }
          },
          "default": {
            "description": "Structured error; dependency failures may include error.requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/scrape": {
      "post": {
        "operationId": "scrape",
        "summary": "Run an independent public-data operation",
        "description": "Uses the same client rate, daily and concurrency budgets as media resolution. Matching owned idempotent results remain in bounded memory for up to 60 seconds. Only a request fingerprint is persisted; source headers and source parameters are not persisted. No payments are collected.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScrapeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured source result or page representation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeResponse"
                }
              }
            }
          },
          "default": {
            "description": "Structured error; dependency failures may include error.requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/scrape/jobs": {
      "post": {
        "operationId": "createScrapeJob",
        "summary": "Create an owned asynchronous scraping job",
        "description": "Bounded in-memory queue: 64 jobs and 16 MiB completed results, retained up to 15 minutes; capacity pressure can expire completed results earlier. Matching owned Idempotency-Key requests reuse a retained job; different request or callback settings conflict. Workers wait for capacity within the request deadline. Optional callback delivery makes up to three attempts and does not rerun the source. A configured callback_secret signs the exact JSON bytes with HMAC-SHA256 in X-Scraper-Signature: sha256=<hex>.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScrapeJobRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job accepted; poll its owned status URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeJob"
                }
              }
            }
          },
          "default": {
            "description": "Structured error; dependency failures may include error.requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "callbacks": {
          "completion": {
            "{$request.body#/callback_url}": {
              "post": {
                "security": [],
                "parameters": [
                  {
                    "in": "header",
                    "name": "X-Scraper-Signature",
                    "required": false,
                    "schema": {
                      "type": "string",
                      "pattern": "^sha256=[a-f0-9]{64}$"
                    },
                    "description": "Present only when a nonempty callback_secret is configured. Verify against the exact body bytes."
                  }
                ],
                "requestBody": {
                  "required": true,
                  "content": {
                    "application/json": {
                      "schema": {
                        "$ref": "#/components/schemas/ScrapeCallback"
                      }
                    }
                  }
                },
                "responses": {
                  "2XX": {
                    "description": "Callback accepted."
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "description": "Optional retry key scoped to this client and retained job. Replays the same request and callback settings for up to 15 minutes; completed results may expire earlier under memory pressure."
          }
        ]
      }
    },
    "/v1/scrape/jobs/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "scrapeJob",
        "summary": "Read an owned asynchronous scraping job",
        "responses": {
          "200": {
            "description": "Job status, result or error, and callback delivery information.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeJob"
                }
              }
            }
          },
          "default": {
            "description": "Structured error; dependency failures may include error.requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "cancelScrapeJob",
        "summary": "Cancel an owned scraping job",
        "responses": {
          "200": {
            "description": "Cancellation requested.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "cancelled"
                  ],
                  "properties": {
                    "cancelled": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured error; dependency failures may include error.requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  }
}
