{
  "openapi": "3.1.0",
  "info": {
    "title": "AgentSearch Web Render",
    "version": "0.1.0",
    "description": "JavaScript page renderer and screenshot service for AI agents (headless Chromium), served on Pocket Network as agentsearch-web-render-v1. All inputs travel in the JSON body; every response is a JSON object. Target-site failures return HTTP 200 with an error object; bad input returns 4xx. Hard render deadline 4.2 s."
  },
  "servers": [
    {
      "url": "https://agent.pocket.network/v1/agentsearch-web-render-v1",
      "description": "Agentic Portal (pay per call)"
    }
  ],
  "paths": {
    "/v1/render": {
      "post": {
        "operationId": "render",
        "summary": "Render a URL in headless Chromium",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenderRequest"
              },
              "examples": {
                "text": {
                  "value": {
                    "url": "https://example.com/",
                    "formats": [
                      "text"
                    ],
                    "max_chars": 500
                  }
                },
                "screenshot": {
                  "value": {
                    "url": "https://react.dev/",
                    "formats": [
                      "markdown"
                    ],
                    "screenshot": true,
                    "screenshot_format": "jpeg"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rendered page, or a target-site failure with error set (content empty or partial).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RenderResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or URL not allowed (INVALID_REQUEST, URL_NOT_ALLOWED).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "Body over 8 KB (REQUEST_TOO_LARGE).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "CAPACITY_LIMIT, APPLICATION_RATE_LIMITED or HOST_RATE_LIMITED (retryable).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "INTERNAL_ERROR (backend fault only).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/version": {
      "get": {
        "operationId": "version",
        "responses": {
          "200": {
            "description": "Identity",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "service": {
                      "const": "agentsearch-web-render-v1"
                    },
                    "version": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/health": {
      "get": {
        "operationId": "health",
        "responses": {
          "200": {
            "description": "Ready",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "const": "ok"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Chromium pool or egress filter not ready",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "const": "degraded"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/capabilities": {
      "get": {
        "operationId": "capabilities",
        "responses": {
          "200": {
            "description": "Limits, formats and error codes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "RenderRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 4096,
            "description": "Public http(s) URL on port 80/443."
          },
          "formats": {
            "type": "array",
            "items": {
              "enum": [
                "markdown",
                "text",
                "html",
                "links"
              ]
            },
            "default": [
              "markdown"
            ]
          },
          "max_chars": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100000,
            "default": 20000
          },
          "screenshot": {
            "type": "boolean",
            "default": false
          },
          "screenshot_format": {
            "enum": [
              "png",
              "jpeg"
            ],
            "default": "png",
            "description": "PNG over 1 MB is re-encoded as JPEG q60; still over 1 MB -> omitted with warning SCREENSHOT_TOO_LARGE."
          },
          "full_page": {
            "type": "boolean",
            "default": false,
            "description": "Height clipped to 4000 px."
          },
          "viewport": {
            "type": "object",
            "properties": {
              "width": {
                "type": "integer",
                "minimum": 320,
                "maximum": 1920,
                "default": 1280
              },
              "height": {
                "type": "integer",
                "minimum": 240,
                "maximum": 1600,
                "default": 800
              }
            }
          },
          "wait_until": {
            "enum": [
              "domcontentloaded",
              "load",
              "networkidle"
            ],
            "default": "domcontentloaded"
          },
          "wait_for_selector": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 300,
            "description": "Waited for at most 1.5 s."
          },
          "wait_ms": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1500,
            "default": 0
          },
          "block": {
            "type": "array",
            "items": {
              "enum": [
                "image",
                "media",
                "font",
                "stylesheet"
              ]
            },
            "default": [
              "media",
              "font"
            ]
          }
        }
      },
      "RenderResponse": {
        "type": "object",
        "required": [
          "request_id",
          "url",
          "meta",
          "error"
        ],
        "properties": {
          "request_id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "requested_url": {
            "type": "string"
          },
          "status_code": {
            "type": [
              "integer",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "meta": {
            "type": "object",
            "properties": {
              "render_ms": {
                "type": "integer"
              },
              "fetched_at": {
                "type": "string",
                "format": "date-time"
              },
              "chars": {
                "type": "integer"
              },
              "truncated": {
                "type": "boolean"
              },
              "js": {
                "type": "boolean"
              },
              "robots": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "blocked_requests": {
                "type": "integer"
              },
              "content_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "lang": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "error": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "code",
                  "message",
                  "retryable"
                ],
                "properties": {
                  "code": {
                    "enum": [
                      "TARGET_HTTP_ERROR",
                      "TARGET_DEADLINE",
                      "TARGET_DNS_ERROR",
                      "TARGET_UNREACHABLE",
                      "TARGET_TLS_ERROR",
                      "TARGET_TOO_MANY_REDIRECTS",
                      "TARGET_REDIRECT_BLOCKED",
                      "ROBOTS_DISALLOWED",
                      "TARGET_BOT_WALL",
                      "UNSUPPORTED_CONTENT",
                      "RENDER_FAILED"
                    ]
                  },
                  "message": {
                    "type": "string"
                  },
                  "retryable": {
                    "type": "boolean"
                  },
                  "upstream_status": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "request_id": {
                    "type": "string"
                  }
                }
              }
            ]
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "links": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "string"
                },
                "href": {
                  "type": "string"
                }
              }
            }
          },
          "text": {
            "type": "string"
          },
          "markdown": {
            "type": "string"
          },
          "html": {
            "type": "string"
          },
          "screenshot": {
            "type": "object",
            "properties": {
              "format": {
                "enum": [
                  "png",
                  "jpeg"
                ]
              },
              "width": {
                "type": "integer"
              },
              "height": {
                "type": "integer"
              },
              "bytes": {
                "type": "integer",
                "maximum": 1000000
              },
              "base64": {
                "type": "string"
              }
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "retryable"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "upstream_status": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "request_id": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
