{
  "openapi": "3.0.3",
  "info": {
    "title": "SPA Render & Extract",
    "description": "Renders JavaScript-heavy SPA pages in real headless Chromium via Cloudflare Browser Rendering, waits for network-idle / selector-ready, strips nav/footer/script chrome, and serializes the fully-rendered DOM into clean, LLM-ready Markdown.",
    "version": "0.1.0"
  },
  "servers": [
    {
      "url": "https://spa-dom-to-md.jannioura.workers.dev",
      "description": "Deployed Cloudflare Worker"
    }
  ],
  "paths": {
    "/": {
      "post": {
        "summary": "Render a URL in headless Chromium and extract Markdown",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Public https URL of the page to render."
                  },
                  "wait_for_selector": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Optional CSS selector to wait for before extraction."
                  },
                  "wait_ms": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 15000,
                    "default": 2000,
                    "description": "Extra settle time after load, in milliseconds."
                  },
                  "markdown": {
                    "type": "boolean",
                    "default": true,
                    "description": "Return Markdown (true) or raw rendered HTML (false)."
                  },
                  "strip_selectors": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "description": "Extra CSS selectors to remove from the rendered DOM before extraction."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rendered extraction result (payment settled).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "url",
                    "final_url",
                    "http_status",
                    "title",
                    "content_bytes",
                    "render_ms"
                  ],
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "final_url": {
                      "type": "string",
                      "description": "URL after redirects."
                    },
                    "http_status": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "markdown": {
                      "type": "string",
                      "description": "Rendered page as Markdown (present when request markdown is true, the default)."
                    },
                    "html": {
                      "type": "string",
                      "description": "Rendered HTML (present when request markdown is false)."
                    },
                    "content_bytes": {
                      "type": "integer"
                    },
                    "render_ms": {
                      "type": "integer"
                    },
                    "cached": {
                      "type": "boolean",
                      "description": "True if served from the KV render cache."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402 v2 challenge)."
          },
          "502": {
            "description": "Target URL returned an HTTP error status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "x-402": {
    "version": 2,
    "scheme": "exact",
    "network": "eip155:84532",
    "networkName": "Base Sepolia (testnet)",
    "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    "amount": "10000",
    "amountDecimal": "0.01",
    "payTo": "REPLACE",
    "facilitator": "https://x402.org/facilitator",
    "eip712Domain": {
      "name": "USDC",
      "version": "2"
    }
  }
}