Files
openserp/docs/openapi.yaml

1537 lines
49 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.0.3
info:
title: OpenSERP API
version: 1.0.0
description: >
OpenSERP provides dedicated and multi-engine search endpoints for Google, Yandex,
Baidu, Bing, and DuckDuckGo. All responses are wrapped in a v1 envelope with
query echo, metadata, normalized results, and pagination. Invalid client input
returns 400 with a machine-readable `reason` code.
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: http://127.0.0.1:7000
description: Local default server
security: []
tags:
- name: Search
description: Dedicated per-engine search endpoints
- name: Mega
description: Cross-engine aggregated search endpoints
- name: Health
description: Health and readiness endpoints
- name: Stats
description: Runtime statistics endpoints
- name: Docs
description: OpenAPI and Swagger UI endpoints
paths:
/{engine}/search:
get:
tags: [Search]
operationId: searchWeb
summary: Search web results from a specific engine
description: >
Engine path values are `google`, `yandex`, `baidu`, `bing`, and `duck`
(`duck` maps to DuckDuckGo internally). Use `?format=markdown|text|ndjson`
for alternative output formats.
parameters:
- $ref: "#/components/parameters/EnginePath"
- $ref: "#/components/parameters/TextQuery"
- $ref: "#/components/parameters/LangQuery"
- $ref: "#/components/parameters/DateQuery"
- $ref: "#/components/parameters/FileQuery"
- $ref: "#/components/parameters/SiteQuery"
- $ref: "#/components/parameters/LimitQuery"
- $ref: "#/components/parameters/StartQuery"
- $ref: "#/components/parameters/FilterQuery"
- $ref: "#/components/parameters/AnswersQuery"
- $ref: "#/components/parameters/FormatQuery"
- $ref: "#/components/parameters/UseProxyHeader"
- $ref: "#/components/parameters/ProxyURLHeader"
- $ref: "#/components/parameters/ProxyCountryHeader"
- $ref: "#/components/parameters/ProxyClassHeader"
- $ref: "#/components/parameters/ProxyProviderHeader"
- $ref: "#/components/parameters/ProxySessionIDHeader"
- $ref: "#/components/parameters/TenantHeader"
responses:
"200":
description: Search results envelope
headers:
X-Request-ID:
$ref: "#/components/headers/XRequestID"
X-Cache:
$ref: "#/components/headers/XCache"
X-Fallback-Engine:
$ref: "#/components/headers/XFallbackEngine"
X-Proxy-Mode:
$ref: "#/components/headers/XProxyMode"
X-Proxy-Tag:
$ref: "#/components/headers/XProxyTag"
X-Proxy-Used:
$ref: "#/components/headers/XProxyUsed"
X-Network-Bytes:
$ref: "#/components/headers/XNetworkBytes"
content:
application/json:
schema:
$ref: "#/components/schemas/SearchEnvelope"
examples:
default:
value:
query:
text: golang
lang: EN
engines_requested: [google]
meta:
request_id: 01HXYZ...
requested_at: "2026-04-24T12:00:00Z"
took_ms: 842
engines_failed: []
version: "1.0"
results:
- id: s_a1b2c3d4e5f6a1b2
rank: 1
type: organic
title: The Go Programming Language
url: https://go.dev/
display_url: go.dev
snippet: Go is an open source programming language...
domain: go.dev
favicon: https://go.dev/favicon.ico
is_ad: false
position:
absolute: 1
page: 1
on_page: 1
engine: google
domain_info:
tld: dev
sld: go
is_gov: false
is_edu: false
is_mil: false
is_news: false
is_forum: false
is_marketplace: false
is_social: false
classification:
content_type: webpage
source_hint: ""
pagination:
page: 1
has_more: true
next_start: 25
text/markdown:
schema:
type: string
text/plain:
schema:
type: string
application/x-ndjson:
schema:
type: string
"400":
$ref: "#/components/responses/BadRequestError"
"403":
$ref: "#/components/responses/ForbiddenError"
"429":
$ref: "#/components/responses/TooManyRequestsError"
"502":
$ref: "#/components/responses/BadGatewayError"
"503":
$ref: "#/components/responses/ServiceUnavailableError"
"504":
$ref: "#/components/responses/GatewayTimeoutError"
"404":
$ref: "#/components/responses/NotFoundError"
"500":
$ref: "#/components/responses/InternalServerError"
/{engine}/image:
get:
tags: [Search]
operationId: searchImages
summary: Search image results from a specific engine
parameters:
- $ref: "#/components/parameters/EnginePath"
- $ref: "#/components/parameters/TextQuery"
- $ref: "#/components/parameters/LangQuery"
- $ref: "#/components/parameters/DateQuery"
- $ref: "#/components/parameters/FileQuery"
- $ref: "#/components/parameters/SiteQuery"
- $ref: "#/components/parameters/LimitQuery"
- $ref: "#/components/parameters/StartQuery"
- $ref: "#/components/parameters/FilterQuery"
- $ref: "#/components/parameters/AnswersQuery"
- $ref: "#/components/parameters/FormatQuery"
- $ref: "#/components/parameters/UseProxyHeader"
- $ref: "#/components/parameters/ProxyURLHeader"
- $ref: "#/components/parameters/ProxyCountryHeader"
- $ref: "#/components/parameters/ProxyClassHeader"
- $ref: "#/components/parameters/ProxyProviderHeader"
- $ref: "#/components/parameters/ProxySessionIDHeader"
- $ref: "#/components/parameters/TenantHeader"
responses:
"200":
description: Image search results envelope
headers:
X-Request-ID:
$ref: "#/components/headers/XRequestID"
X-Cache:
$ref: "#/components/headers/XCache"
X-Fallback-Engine:
$ref: "#/components/headers/XFallbackEngine"
X-Proxy-Mode:
$ref: "#/components/headers/XProxyMode"
X-Proxy-Tag:
$ref: "#/components/headers/XProxyTag"
X-Proxy-Used:
$ref: "#/components/headers/XProxyUsed"
X-Network-Bytes:
$ref: "#/components/headers/XNetworkBytes"
content:
application/json:
schema:
$ref: "#/components/schemas/ImageEnvelope"
"400":
$ref: "#/components/responses/BadRequestError"
"403":
$ref: "#/components/responses/ForbiddenError"
"429":
$ref: "#/components/responses/TooManyRequestsError"
"502":
$ref: "#/components/responses/BadGatewayError"
"503":
$ref: "#/components/responses/ServiceUnavailableError"
"504":
$ref: "#/components/responses/GatewayTimeoutError"
"404":
$ref: "#/components/responses/NotFoundError"
"500":
$ref: "#/components/responses/InternalServerError"
/mega/search:
get:
tags: [Mega]
operationId: megaSearch
summary: Search across multiple engines in parallel
description: >
Results are deduplicated by normalized URL. The `clusters` field groups
results that appeared in multiple engines, scored by cross-engine agreement.
Partial failures are surfaced in `meta.engines_failed` and
`meta.engine_errors`. If all selected engines fail, the endpoint returns
a 502 with per-engine error details. Use `?format=markdown|text|ndjson`
for alternative output formats.
parameters:
- $ref: "#/components/parameters/TextQuery"
- $ref: "#/components/parameters/LangQuery"
- $ref: "#/components/parameters/DateQuery"
- $ref: "#/components/parameters/FileQuery"
- $ref: "#/components/parameters/SiteQuery"
- $ref: "#/components/parameters/LimitQuery"
- $ref: "#/components/parameters/StartQuery"
- $ref: "#/components/parameters/FilterQuery"
- $ref: "#/components/parameters/AnswersQuery"
- $ref: "#/components/parameters/EnginesQuery"
- $ref: "#/components/parameters/FormatQuery"
- $ref: "#/components/parameters/UseProxyHeader"
- $ref: "#/components/parameters/ProxyURLHeader"
- $ref: "#/components/parameters/ProxyCountryHeader"
- $ref: "#/components/parameters/ProxyClassHeader"
- $ref: "#/components/parameters/ProxyProviderHeader"
- $ref: "#/components/parameters/ProxySessionIDHeader"
- $ref: "#/components/parameters/TenantHeader"
responses:
"200":
description: Aggregated envelope with clusters
headers:
X-Request-ID:
$ref: "#/components/headers/XRequestID"
X-Cache:
$ref: "#/components/headers/XCache"
X-Proxy-Mode:
$ref: "#/components/headers/XProxyMode"
X-Proxy-Tag:
$ref: "#/components/headers/XProxyTag"
X-Proxy-Used:
$ref: "#/components/headers/XProxyUsed"
X-Network-Bytes:
$ref: "#/components/headers/XNetworkBytes"
content:
application/json:
schema:
$ref: "#/components/schemas/MegaSearchEnvelope"
text/markdown:
schema:
type: string
text/plain:
schema:
type: string
application/x-ndjson:
schema:
type: string
"400":
$ref: "#/components/responses/BadRequestError"
"403":
$ref: "#/components/responses/ForbiddenError"
"429":
$ref: "#/components/responses/TooManyRequestsError"
"502":
$ref: "#/components/responses/BadGatewayError"
"503":
$ref: "#/components/responses/ServiceUnavailableError"
"504":
$ref: "#/components/responses/GatewayTimeoutError"
"500":
$ref: "#/components/responses/InternalServerError"
/mega/image:
get:
tags: [Mega]
operationId: megaImageSearch
summary: Image search across multiple engines in parallel
parameters:
- $ref: "#/components/parameters/TextQuery"
- $ref: "#/components/parameters/LangQuery"
- $ref: "#/components/parameters/DateQuery"
- $ref: "#/components/parameters/FileQuery"
- $ref: "#/components/parameters/SiteQuery"
- $ref: "#/components/parameters/LimitQuery"
- $ref: "#/components/parameters/StartQuery"
- $ref: "#/components/parameters/FilterQuery"
- $ref: "#/components/parameters/AnswersQuery"
- $ref: "#/components/parameters/EnginesQuery"
- $ref: "#/components/parameters/FormatQuery"
- $ref: "#/components/parameters/UseProxyHeader"
- $ref: "#/components/parameters/ProxyURLHeader"
- $ref: "#/components/parameters/ProxyCountryHeader"
- $ref: "#/components/parameters/ProxyClassHeader"
- $ref: "#/components/parameters/ProxyProviderHeader"
- $ref: "#/components/parameters/ProxySessionIDHeader"
- $ref: "#/components/parameters/TenantHeader"
responses:
"200":
description: Aggregated image results envelope
headers:
X-Request-ID:
$ref: "#/components/headers/XRequestID"
X-Cache:
$ref: "#/components/headers/XCache"
X-Proxy-Mode:
$ref: "#/components/headers/XProxyMode"
X-Proxy-Tag:
$ref: "#/components/headers/XProxyTag"
X-Proxy-Used:
$ref: "#/components/headers/XProxyUsed"
X-Network-Bytes:
$ref: "#/components/headers/XNetworkBytes"
content:
application/json:
schema:
$ref: "#/components/schemas/ImageEnvelope"
"400":
$ref: "#/components/responses/BadRequestError"
"403":
$ref: "#/components/responses/ForbiddenError"
"429":
$ref: "#/components/responses/TooManyRequestsError"
"502":
$ref: "#/components/responses/BadGatewayError"
"503":
$ref: "#/components/responses/ServiceUnavailableError"
"504":
$ref: "#/components/responses/GatewayTimeoutError"
"500":
$ref: "#/components/responses/InternalServerError"
/mega/engines:
get:
tags: [Mega]
operationId: listMegaEngines
summary: List available engines and runtime state
responses:
"200":
description: Engine list
content:
application/json:
schema:
$ref: "#/components/schemas/MegaEnginesResponse"
/health:
get:
tags: [Health]
operationId: healthCheck
summary: Service health status
responses:
"200":
description: Healthy or degraded service
content:
application/json:
schema:
$ref: "#/components/schemas/HealthStatus"
"503":
description: Unhealthy service
content:
application/json:
schema:
$ref: "#/components/schemas/HealthStatus"
/ready:
get:
tags: [Health]
operationId: readinessCheck
summary: Service readiness status
responses:
"200":
description: Instance is ready
content:
application/json:
schema:
$ref: "#/components/schemas/ReadinessStatus"
"503":
description: Instance is draining
content:
application/json:
schema:
$ref: "#/components/schemas/ReadinessStatus"
/stats:
get:
tags: [Stats]
operationId: getStats
summary: Combined cache, proxy, and circuit-breaker stats
responses:
"200":
description: Runtime statistics
content:
application/json:
schema:
$ref: "#/components/schemas/StatsResponse"
/stats/cache:
get:
tags: [Stats]
operationId: getCacheStats
summary: Cache statistics only
responses:
"200":
description: Cache status
content:
application/json:
schema:
$ref: "#/components/schemas/CacheStats"
/stats/proxy:
get:
tags: [Stats]
operationId: getProxyStats
summary: Proxy pool and per-engine proxy policy statistics
responses:
"200":
description: Proxy stats
content:
application/json:
schema:
$ref: "#/components/schemas/ProxyStats"
/stats/cb:
get:
tags: [Stats]
operationId: getCircuitBreakerStats
summary: Circuit breaker state per engine
responses:
"200":
description: Circuit breaker stats
content:
application/json:
schema:
$ref: "#/components/schemas/CircuitBreakerStatsResponse"
/openapi.yaml:
get:
tags: [Docs]
operationId: getOpenAPISpec
summary: Get raw OpenAPI YAML
responses:
"200":
description: OpenAPI YAML
content:
application/yaml:
schema:
type: string
/docs:
get:
tags: [Docs]
operationId: getSwaggerUI
summary: Swagger UI for interactive API docs
responses:
"200":
description: HTML page loading Swagger UI from CDN
content:
text/html:
schema:
type: string
components:
parameters:
EnginePath:
name: engine
in: path
required: true
description: Search engine endpoint alias (`duck` is DuckDuckGo).
schema:
type: string
enum: [google, yandex, baidu, bing, duck]
TextQuery:
name: text
in: query
required: false
description: >
Search query text. At least one of `text`, `site`, or `file` must be non-empty.
schema:
type: string
example: golang
LangQuery:
name: lang
in: query
required: false
description: Language code (engine-specific behavior).
schema:
type: string
example: EN
DateQuery:
name: date
in: query
required: false
description: Date interval in `YYYYMMDD..YYYYMMDD` format.
schema:
type: string
pattern: "^[0-9]{8}\\.\\.[0-9]{8}$"
example: 20250101..20250131
FileQuery:
name: file
in: query
required: false
description: File extension filter (for engines that support it).
schema:
type: string
example: PDF
SiteQuery:
name: site
in: query
required: false
description: Site/domain filter.
schema:
type: string
example: github.com
LimitQuery:
name: limit
in: query
required: false
description: Maximum results to return (1100).
schema:
type: integer
minimum: 1
maximum: 100
default: 25
example: 10
StartQuery:
name: start
in: query
required: false
description: Pagination offset (must be >= 0).
schema:
type: integer
minimum: 0
default: 0
example: 20
FilterQuery:
name: filter
in: query
required: false
description: Duplicate filtering flag (primarily used by Google parser behavior).
schema:
type: boolean
default: true
AnswersQuery:
name: answers
in: query
required: false
description: Include answer box style results when supported.
schema:
type: boolean
default: false
EnginesQuery:
name: engines
in: query
required: false
description: >
Comma-separated engine list for mega endpoints. If omitted, all available engines are used.
schema:
type: string
example: google,bing,duckduckgo
FormatQuery:
name: format
in: query
required: false
description: >
Output format. `json` (default) returns the full envelope. `markdown` returns a
Markdown document suitable for Slack/email. `text` returns a minimal plain-text
block optimised for LLM context windows. `ndjson` returns one result object per
line with no envelope. The `Accept` header is also checked
(`text/markdown`, `text/plain`, `application/x-ndjson`).
schema:
type: string
enum: [json, markdown, text, ndjson]
default: json
UseProxyHeader:
name: X-Use-Proxy
in: header
required: false
description: >
Request-scoped proxy override. Use `direct` to disable proxy or a tag name to
force a specific proxy pool.
schema:
type: string
examples:
direct:
value: direct
tag:
value: us
ProxyURLHeader:
name: X-Proxy-URL
in: header
required: false
description: >
Per-request proxy URL supplied by an upstream balancer. Honored only when
`proxies.allow_request_proxy_url: true` is set on the worker; otherwise the
request is rejected with `400 bad_request` and `reason=REQUEST_PROXY_URL_DISABLED`.
Authenticated SOCKS proxies are rejected in browser mode
(`reason=UNSUPPORTED_PROXY_SCHEME`). Credentials are never logged or returned.
Precedence: `X-Use-Proxy: direct` > `X-Proxy-URL` > `X-Use-Proxy: <tag>` >
per-engine configured tag > `proxies.global` > direct.
schema:
type: string
example: http://user:pass@proxy.example:8080
ProxyCountryHeader:
name: X-Proxy-Country
in: header
required: false
description: >
Two-letter market country code for the supplied proxy. Used as part of the
cache key so different markets do not share results.
schema:
type: string
example: us
ProxyClassHeader:
name: X-Proxy-Class
in: header
required: false
description: Proxy class identifier (e.g. `datacenter`, `residential`, `mobile`). Part of the cache key.
schema:
type: string
example: residential
ProxyProviderHeader:
name: X-Proxy-Provider
in: header
required: false
description: Upstream proxy provider identifier (e.g. `webshare`, `brightdata`). Part of the cache key.
schema:
type: string
example: webshare
ProxySessionIDHeader:
name: X-Proxy-Session-ID
in: header
required: false
description: >
Sticky session identifier minted by the balancer. Reusing the same value lets
OpenSERP reuse cookies and browser profile for that lane. Lanes are LRU-bounded
by `proxies.lanes.max_lanes`. Rotating the session ID gives a clean lane.
schema:
type: string
example: sid-123
TenantHeader:
name: X-Tenant
in: header
required: false
description: >
Optional tenant scope used to namespace sticky lane state across multi-tenant
deployments. When present, lanes are keyed by `tenant + engine + session_id`.
schema:
type: string
headers:
XRequestID:
description: >
UUID v7 request identifier. Matches `meta.request_id` in the response body and
appears in server logs for correlation.
schema:
type: string
XCache:
description: Cache status when cache is enabled (`HIT`, `MISS`, `BYPASS`).
schema:
type: string
enum: [HIT, MISS, BYPASS]
XFallbackEngine:
description: Engine name used when dedicated endpoint fallback served the response.
schema:
type: string
XProxyMode:
description: >
Effective proxy mode for the request. `request_url` indicates a per-request
`X-Proxy-URL` was honored.
schema:
type: string
enum: [off, tag_pool, request_url]
XProxyTag:
description: >
Effective proxy tag when `X-Proxy-Mode=tag_pool`. Header is omitted when no
tag is in effect (i.e. `X-Proxy-Mode` is `request_url` or `off`).
schema:
type: string
XProxyUsed:
description: >
Effective proxy target used. Values: `direct`, masked `scheme://host:port` URL,
`pooled`, `multiple`, or `mixed`. Credentials are never included.
schema:
type: string
XNetworkBytes:
description: >
Aggregate inbound network bytes consumed while executing the search request.
Single-engine endpoints report that engine's request bytes; mega endpoints
report the sum across selected engines. Cache hits return `0`.
schema:
type: integer
format: int64
minimum: 0
responses:
BadRequestError:
description: Invalid request parameters
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
examples:
invalidLimit:
value:
error: bad_request
code: 400
message: "INVALID_LIMIT: limit must be between 1 and 100"
reason: INVALID_LIMIT
emptyQuery:
value:
error: bad_request
code: 400
message: "EMPTY_QUERY: query cannot be empty"
reason: EMPTY_QUERY
requestProxyURLDisabled:
value:
error: bad_request
code: 400
message: "REQUEST_PROXY_URL_DISABLED: X-Proxy-URL is disabled by server configuration"
reason: REQUEST_PROXY_URL_DISABLED
unsupportedProxyScheme:
value:
error: bad_request
code: 400
message: "UNSUPPORTED_PROXY_SCHEME: authenticated SOCKS proxies are not supported in browser mode"
reason: UNSUPPORTED_PROXY_SCHEME
ForbiddenError:
description: The search engine blocked the request
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
examples:
blocked:
value:
error: blocked
code: 403
message: "search engine blocked the request"
meta:
engine: google
proxy_used: http://proxy.example:8080
proxy_country: us
proxy_class: residential
proxy_provider: webshare
proxy_session_id: sid-123
TooManyRequestsError:
description: Captcha challenge or rate-limit response from the search engine
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
examples:
captcha:
value:
error: captcha_detected
code: 429
message: "captcha detected"
meta:
engine: google
proxy_used: http://proxy.example:8080
proxy_session_id: sid-123
rateLimited:
value:
error: rate_limited
code: 429
message: "search engine rate limited the request"
meta:
engine: google
proxy_used: http://proxy.example:8080
BadGatewayError:
description: Engine internal failure, parser drift, or all-engine failure when fallback is enabled.
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
examples:
parserFailure:
value:
error: parser_failure
code: 502
message: "parser failure"
meta:
engine: google
engineInternal:
value:
error: engine_internal
code: 502
message: "engine internal error"
meta:
engine: google
allEnginesFailed:
value:
error: engine_internal
code: 502
message: "all search engines failed"
meta:
engine: google
GatewayTimeoutError:
description: Search timed out waiting for required SERP elements
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
examples:
searchTimeout:
value:
error: search_timeout
code: 504
message: "timeout. Cannot find element on page"
meta:
engine: google
ServiceUnavailableError:
description: Proxy-layer failure (no healthy proxy or transport error). The search itself was not produced.
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
examples:
proxyConnect:
value:
error: proxy_connect
code: 503
message: "proxy connection failed"
meta:
engine: google
proxy_used: http://proxy.example:8080
proxy_country: us
proxyAuth:
value:
error: proxy_auth
code: 503
message: "proxy authentication failed"
meta:
engine: google
proxy_used: http://proxy.example:8080
proxyTimeout:
value:
error: proxy_timeout
code: 503
message: "proxy request timed out"
meta:
engine: google
proxy_used: http://proxy.example:8080
proxyUnavailable:
value:
error: proxy_unavailable
code: 503
message: "proxy unavailable"
meta:
engine: google
NotFoundError:
description: Endpoint not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
InternalServerError:
description: Internal error while handling request
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
schemas:
# ── v1 envelope ──────────────────────────────────────────────────
QueryEcho:
type: object
required: [text, engines_requested]
properties:
text:
type: string
example: golang
lang:
type: string
example: EN
engines_requested:
type: array
items:
type: string
example: [google]
ResponseMeta:
type: object
required: [request_id, requested_at, took_ms, engines_failed, version]
properties:
request_id:
type: string
example: 01HXYZ...
requested_at:
type: string
format: date-time
example: "2026-04-24T12:00:00Z"
took_ms:
type: integer
example: 842
engines_failed:
type: array
items:
type: string
example: []
engine_errors:
type: array
description: Sanitized per-engine failures for mega endpoints.
items:
$ref: "#/components/schemas/EngineErrorDetail"
version:
type: string
example: "1.0"
EngineErrorDetail:
type: object
required: [engine, error]
properties:
engine:
type: string
example: bing
error:
type: string
example: blocked
message:
type: string
description: Sanitized detail; proxy credentials are never included.
example: "blocked: 403"
Pagination:
type: object
required: [page, has_more, next_start]
properties:
page:
type: integer
minimum: 1
example: 1
has_more:
type: boolean
example: true
next_start:
type: integer
example: 25
# ── Result ───────────────────────────────────────────────────────
Position:
type: object
required: [absolute, page, on_page]
properties:
absolute:
type: integer
description: 1-based rank counting from the first result of the first page.
example: 1
page:
type: integer
example: 1
on_page:
type: integer
example: 1
DomainInfo:
type: object
required: [tld, sld, is_gov, is_edu, is_mil, is_news, is_forum, is_marketplace, is_social]
properties:
tld:
type: string
example: org
sld:
type: string
example: wikipedia
is_gov:
type: boolean
is_edu:
type: boolean
is_mil:
type: boolean
is_news:
type: boolean
is_forum:
type: boolean
is_marketplace:
type: boolean
is_social:
type: boolean
Classification:
type: object
required: [content_type, source_hint]
properties:
content_type:
type: string
enum: [article, document, video, forum_thread, webpage]
example: article
source_hint:
type: string
example: encyclopedia
ResultType:
type: string
description: >
SERP block type. New values require a minor version bump (`meta.version: "1.1"`).
In v1.0, engines emit `organic`, `ad`, or `answer_box`; other enum values are
reserved for future parser upgrades.
enum:
- organic
- ad
- featured_snippet
- knowledge_panel
- people_also_ask
- video
- image
- news
- shopping
- local
- answer_box
Result:
type: object
required:
- id
- rank
- type
- title
- url
- display_url
- snippet
- domain
- favicon
- is_ad
- position
- engine
properties:
id:
type: string
description: >
Stable identifier: `s_` + hex(first 8 bytes of MD5(engine|normalized_url)).
Normalized URL: lowercase scheme+host, trailing slash stripped, utm_*/fbclid/gclid
tracking params removed. Same URL → same ID across requests.
example: s_a1b2c3d4e5f6a1b2
rank:
type: integer
example: 1
type:
$ref: "#/components/schemas/ResultType"
title:
type: string
example: The Go Programming Language
url:
type: string
example: https://go.dev/
display_url:
type: string
description: Breadcrumb form of the URL (e.g. `go.dev doc install`).
example: go.dev
snippet:
type: string
example: Go is an open source programming language...
domain:
type: string
description: Registrable domain with leading `www.` stripped.
example: go.dev
favicon:
type: string
description: Constructed as `https://{domain}/favicon.ico`. Not probed.
example: https://go.dev/favicon.ico
is_ad:
type: boolean
example: false
position:
$ref: "#/components/schemas/Position"
engine:
type: string
example: google
domain_info:
$ref: "#/components/schemas/DomainInfo"
classification:
$ref: "#/components/schemas/Classification"
# ── Image result ─────────────────────────────────────────────────
ImageData:
type: object
required: [url]
properties:
url:
type: string
example: https://example.com/gopher.png
thumbnail:
type: string
example: https://example.com/gopher-thumb.png
width:
type: integer
example: 1200
height:
type: integer
example: 800
ImageSource:
type: object
required: [page_url, domain]
properties:
page_url:
type: string
example: https://example.com/article-about-gophers
domain:
type: string
example: example.com
ImageResult:
type: object
required: [id, rank, type, title, image, source, engine]
properties:
id:
type: string
description: Stable identifier prefixed with `i_`.
example: i_a1b2c3d4e5f6a1b2
rank:
type: integer
example: 1
type:
type: string
enum: [image]
title:
type: string
image:
$ref: "#/components/schemas/ImageData"
source:
$ref: "#/components/schemas/ImageSource"
engine:
type: string
# ── Clusters (mega only) ──────────────────────────────────────────
ClusterOccurrence:
type: object
required: [engine, rank, result_id]
properties:
engine:
type: string
example: google
rank:
type: integer
example: 1
result_id:
type: string
example: s_a1b2c3d4e5f6a1b2
Cluster:
type: object
required: [id, canonical_url, domain, title, occurrences, engines_count, best_rank, score]
properties:
id:
type: string
description: >
Stable identifier: `c_` + hex(first 8 bytes of MD5(normalized_url)).
example: c_a1b2c3d4e5f6a1b2
canonical_url:
type: string
example: https://go.dev/
domain:
type: string
example: go.dev
title:
type: string
example: The Go Programming Language
occurrences:
type: array
items:
$ref: "#/components/schemas/ClusterOccurrence"
engines_count:
type: integer
description: Number of engines this URL appeared in.
example: 3
best_rank:
type: integer
description: Lowest (best) rank seen across all engines.
example: 1
score:
type: number
format: float
description: >
Cross-engine agreement score: sum(1/rank for each occurrence) / engines_queried,
capped at 1.0. Higher is better.
example: 0.92
# ── Envelopes ─────────────────────────────────────────────────────
SearchEnvelope:
type: object
required: [query, meta, results, pagination]
properties:
query:
$ref: "#/components/schemas/QueryEcho"
meta:
$ref: "#/components/schemas/ResponseMeta"
results:
type: array
items:
$ref: "#/components/schemas/Result"
pagination:
$ref: "#/components/schemas/Pagination"
MegaSearchEnvelope:
allOf:
- $ref: "#/components/schemas/SearchEnvelope"
- type: object
properties:
clusters:
type: array
nullable: true
items:
$ref: "#/components/schemas/Cluster"
description: >
Cross-engine clusters, sorted by score descending. Only present on
/mega/search responses. Absent (not null) on single-engine endpoints.
ImageEnvelope:
type: object
required: [query, meta, results, pagination]
properties:
query:
$ref: "#/components/schemas/QueryEcho"
meta:
$ref: "#/components/schemas/ResponseMeta"
results:
type: array
items:
$ref: "#/components/schemas/ImageResult"
pagination:
$ref: "#/components/schemas/Pagination"
# ── Error ─────────────────────────────────────────────────────────
ErrorResponse:
type: object
required: [error, code]
properties:
error:
type: string
description: >
Stable machine-readable error class. Search-pipeline failures use the
following codes: `captcha_detected`, `blocked`, `rate_limited`,
`search_timeout`, `proxy_connect`, `proxy_auth`, `proxy_timeout`,
`proxy_unavailable`, `parser_failure`, `engine_internal`,
`all_engines_failed`, `circuit_open`, `request_timeout`,
`request_canceled`. Validation errors use `bad_request`. Other
generic codes (`not_found`, `service_unavailable`, `server_error`,
`client_error`, `error`) may appear for non-search routes.
enum:
- bad_request
- not_found
- rate_limited
- service_unavailable
- server_error
- client_error
- error
- captcha_detected
- blocked
- search_timeout
- proxy_connect
- proxy_auth
- proxy_timeout
- proxy_unavailable
- parser_failure
- engine_internal
- all_engines_failed
- circuit_open
- request_timeout
- request_canceled
example: bad_request
code:
type: integer
example: 400
request_id:
type: string
description: Matches the `X-Request-ID` response header.
example: 01HXYZ...
message:
type: string
example: "INVALID_LIMIT: limit must be between 1 and 100"
reason:
type: string
description: >
Stable client-actionable reason code. Present on 400 errors.
Known values: INVALID_LIMIT, INVALID_START, INVALID_PARAM, EMPTY_QUERY,
NO_ENGINES, UNKNOWN_FORMAT, REQUEST_PROXY_URL_DISABLED,
UNSUPPORTED_PROXY_SCHEME.
example: INVALID_LIMIT
meta:
type: object
description: >
Sanitized context for search-pipeline errors. Credentials are never
included.
additionalProperties: true
properties:
engine:
type: string
example: google
proxy_used:
type: string
description: Masked `scheme://host:port`; never includes credentials.
example: http://proxy.example:8080
proxy_country:
type: string
example: us
proxy_class:
type: string
example: residential
proxy_provider:
type: string
example: webshare
proxy_session_id:
type: string
example: sid-123
error_detail:
type: string
description: Sanitized underlying error detail when available.
example: "proxy_connect: dial tcp proxy.example:8080: connection refused"
engine_errors:
type: array
items:
$ref: "#/components/schemas/EngineErrorDetail"
# ── Health / Stats ────────────────────────────────────────────────
EngineHealth:
type: object
required: [name, initialized, status]
properties:
name:
type: string
example: google
initialized:
type: boolean
example: true
status:
type: string
enum: [ready, not_initialized, circuit_open]
HealthStatus:
type: object
required: [status, uptime, engines, system]
properties:
status:
type: string
enum: [healthy, degraded, unhealthy]
uptime:
type: string
example: 1h12m3s
engines:
type: array
items:
$ref: "#/components/schemas/EngineHealth"
system:
type: object
additionalProperties: true
ReadinessStatus:
type: object
required: [status]
properties:
status:
type: string
enum: [ready, draining]
CacheStatsEnabled:
type: object
required: [status, entries, hits, misses, bypasses, evictions, ttl_seconds, max_size]
properties:
status:
type: boolean
enum: [true]
entries:
type: integer
hits:
type: integer
misses:
type: integer
bypasses:
type: integer
evictions:
type: integer
ttl_seconds:
type: integer
max_size:
type: integer
CacheStatsDisabled:
type: object
required: [status]
properties:
status:
type: boolean
enum: [false]
CacheStats:
oneOf:
- $ref: "#/components/schemas/CacheStatsEnabled"
- $ref: "#/components/schemas/CacheStatsDisabled"
ProxyTagSummary:
type: object
required: [configured, healthy]
properties:
configured:
type: integer
healthy:
type: integer
ProxyStatsEntry:
type: object
required: [proxy, tags, healthy, failures, disabled]
properties:
proxy:
type: string
tags:
type: array
items:
type: string
healthy:
type: boolean
failures:
type: integer
disabled:
type: boolean
ProxyEngineStats:
type: object
required: [selected_proxy]
properties:
tag:
type: string
selected_proxy:
type: string
LaneStats:
type: object
required: [active, evicted_lru, cookies_dropped]
description: Sticky proxy lane state observed by this worker.
properties:
active:
type: integer
description: Number of lanes currently held by the worker.
example: 12
evicted_lru:
type: integer
description: Lanes evicted by the LRU bound since worker start.
example: 7
cookies_dropped:
type: integer
description: Lane cookie drops triggered by captcha/challenge responses.
example: 20
BrowserPoolStats:
type: object
required: [active, max, evicted_lru, evicted_idle]
description: >
Live state of the per-process Chrome pool. Each authenticated upstream
proxy identity (scheme+host+port+username) gets a dedicated Chrome so
Chrome can answer 407 challenges natively. Direct and unauthenticated
proxies share one Chrome with per-BrowserContext proxy override.
properties:
active:
type: integer
description: Number of Chrome processes currently held by the pool.
example: 3
max:
type: integer
description: Configured `app.max_processes` LRU cap.
example: 4
evicted_lru:
type: integer
description: Chrome processes closed because the LRU cap was exceeded.
example: 12
evicted_idle:
type: integer
description: Chrome processes closed by the idle sweeper after `app.idle_ttl`.
example: 5
ProxyStats:
type: object
required:
[
configured_count,
healthy_count,
unhealthy_count,
request_proxy_url_enabled,
lanes,
browser_processes,
tags,
entries,
]
properties:
configured_count:
type: integer
healthy_count:
type: integer
unhealthy_count:
type: integer
request_proxy_url_enabled:
type: boolean
description: Whether `proxies.allow_request_proxy_url` is enabled on this worker.
lanes:
$ref: "#/components/schemas/LaneStats"
browser_processes:
$ref: "#/components/schemas/BrowserPoolStats"
tags:
type: object
additionalProperties:
$ref: "#/components/schemas/ProxyTagSummary"
entries:
type: array
items:
$ref: "#/components/schemas/ProxyStatsEntry"
engines:
type: object
additionalProperties:
$ref: "#/components/schemas/ProxyEngineStats"
CircuitBreakerStat:
type: object
required: [engine, state, failure_count, last_changed]
properties:
engine:
type: string
state:
type: string
enum: [closed, open, half-open]
failure_count:
type: integer
last_changed:
type: string
format: date-time
retry_in:
type: integer
description: Seconds until next half-open attempt (present when state is open).
CircuitBreakerStatsResponse:
type: object
required: [circuit_breakers]
properties:
circuit_breakers:
type: array
items:
$ref: "#/components/schemas/CircuitBreakerStat"
StatsResponse:
type: object
required: [cache, proxy, circuit_breakers]
properties:
cache:
$ref: "#/components/schemas/CacheStats"
proxy:
$ref: "#/components/schemas/ProxyStats"
circuit_breakers:
type: array
items:
$ref: "#/components/schemas/CircuitBreakerStat"
MegaEngineInfo:
type: object
required: [name, initialized]
properties:
name:
type: string
initialized:
type: boolean
circuit_state:
type: string
enum: [closed, open, half-open]
MegaEnginesResponse:
type: object
required: [engines, total]
properties:
engines:
type: array
items:
$ref: "#/components/schemas/MegaEngineInfo"
total:
type: integer