478 lines
11 KiB
Markdown
478 lines
11 KiB
Markdown
# Web API Documentation
|
|
|
|
## Base URL
|
|
|
|
```
|
|
{BASE_URL}
|
|
```
|
|
|
|
- **Local development:** `http://localhost:51100`
|
|
- **Docker (internal):** `http://web-api:51100`
|
|
- **Production:** Use your configured hostname
|
|
|
|
## Authentication
|
|
|
|
Authentication is optional. If `WEB_API_TOKENS` is set, Bearer token authentication is required.
|
|
|
|
```
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
If authentication is disabled (default), no Authorization header is needed.
|
|
|
|
## Endpoints
|
|
|
|
### Gather (Main Endpoint)
|
|
|
|
Execute the full evidence-gathering pipeline: search → fetch → evidence.
|
|
|
|
```
|
|
POST /v1/gather
|
|
```
|
|
|
|
#### Request Body
|
|
|
|
```json
|
|
{
|
|
"claim": "The claim to verify",
|
|
"search_queries": ["optional custom queries"],
|
|
"max_search_results": 20,
|
|
"site_allowlist": ["reuters.com"],
|
|
"site_blocklist": ["spam-site.com"],
|
|
"fetch_method": "auto",
|
|
"auto_fallback": true,
|
|
"extract_snippets": true,
|
|
"max_evidence_items": 15,
|
|
"dedupe": true,
|
|
"timeout_seconds": 60.0
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `claim` | string | Yes | - | Claim to gather evidence for (10-1000 chars) |
|
|
| `search_queries` | array[string] | No | null | Custom search queries (auto-generated if not provided) |
|
|
| `max_search_results` | integer | No | 20 | Max search results (5-50) |
|
|
| `site_allowlist` | array[string] | No | null | Only search these domains |
|
|
| `site_blocklist` | array[string] | No | null | Exclude these domains |
|
|
| `fetch_method` | string | No | "auto" | "auto", "http", "browse", "vision" |
|
|
| `auto_fallback` | boolean | No | true | Escalate on fetch failure |
|
|
| `extract_snippets` | boolean | No | true | Use LLM for snippet extraction |
|
|
| `max_evidence_items` | integer | No | 15 | Max items in final pack (1-50) |
|
|
| `dedupe` | boolean | No | true | Deduplicate evidence |
|
|
| `parallel_fetches` | integer | No | 5 | Concurrent fetch operations (1-10) |
|
|
| `timeout_seconds` | number | No | 60.0 | Total pipeline timeout (10-300) |
|
|
|
|
#### Response
|
|
|
|
```json
|
|
{
|
|
"request_id": "uuid",
|
|
"claim": "The claim",
|
|
"evidence": [
|
|
{
|
|
"url": "https://example.com/article",
|
|
"title": "Article Title",
|
|
"publisher": "example.com",
|
|
"snippet": "Relevant excerpt...",
|
|
"relevance_score": 0.8,
|
|
"credibility_score": null,
|
|
"published_at": "2024-01-15",
|
|
"retrieved_at": "2025-01-20T10:00:00Z",
|
|
"full_text_hash": "sha256...",
|
|
"provenance": {
|
|
"extraction_method": "http",
|
|
"fallback_chain": []
|
|
}
|
|
}
|
|
],
|
|
"evidence_stats": {
|
|
"input_items": 10,
|
|
"after_dedup": 8,
|
|
"output_items": 8,
|
|
"duplicates_removed": 2,
|
|
"tokens_used": 1500
|
|
},
|
|
"stages": [
|
|
{"stage": "search", "success": true, "items_processed": 10, "items_failed": 0, "duration_ms": 500.0},
|
|
{"stage": "fetch", "success": true, "items_processed": 8, "items_failed": 2, "duration_ms": 5000.0},
|
|
{"stage": "evidence", "success": true, "items_processed": 8, "items_failed": 0, "duration_ms": 3000.0}
|
|
],
|
|
"total_urls_found": 10,
|
|
"total_pages_fetched": 8,
|
|
"total_evidence_items": 8,
|
|
"execution_time_ms": 8500.0
|
|
}
|
|
```
|
|
|
|
#### Example
|
|
|
|
```bash
|
|
curl -X POST http://localhost:51100/v1/gather \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"claim": "Romania had the highest economic growth in the EU in 2024",
|
|
"max_search_results": 5,
|
|
"extract_snippets": true,
|
|
"max_evidence_items": 5
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
### Search
|
|
|
|
Execute web search queries.
|
|
|
|
```
|
|
POST /v1/search
|
|
```
|
|
|
|
#### Request Body
|
|
|
|
```json
|
|
{
|
|
"queries": ["string"],
|
|
"max_results": 10,
|
|
"site_allowlist": ["string"],
|
|
"site_blocklist": ["string"],
|
|
"language": "en",
|
|
"country": "US",
|
|
"freshness": "month",
|
|
"safe_search": "moderate"
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `queries` | array[string] | Yes | - | Search queries (1-10) |
|
|
| `max_results` | integer | No | 10 | Results per query (1-100) |
|
|
| `site_allowlist` | array[string] | No | null | Only include these domains |
|
|
| `site_blocklist` | array[string] | No | null | Exclude these domains |
|
|
| `language` | string | No | "en" | Search language (ISO 639-1) |
|
|
| `country` | string | No | "US" | Search country (ISO 3166-1) |
|
|
| `freshness` | string | No | null | Filter by age: day, week, month, year |
|
|
| `safe_search` | string | No | "moderate" | off, moderate, strict |
|
|
|
|
#### Response
|
|
|
|
```json
|
|
{
|
|
"request_id": "uuid",
|
|
"results": [
|
|
{
|
|
"query": "string",
|
|
"url": "string",
|
|
"title": "string",
|
|
"snippet": "string",
|
|
"rank": 1,
|
|
"site": "string",
|
|
"published_at": "string|null"
|
|
}
|
|
],
|
|
"total_results": 10,
|
|
"execution_time_ms": 150.5,
|
|
"queries_processed": 1
|
|
}
|
|
```
|
|
|
|
#### Example
|
|
|
|
```bash
|
|
curl -X POST http://localhost:51100/v1/search \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"queries": ["climate change effects", "renewable energy"],
|
|
"max_results": 5,
|
|
"site_allowlist": ["reuters.com", "bbc.com"],
|
|
"freshness": "month"
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
### Image Search
|
|
|
|
Search for images using SearXNG image search.
|
|
|
|
```
|
|
POST /v1/image-search
|
|
```
|
|
|
|
#### Request Body
|
|
|
|
```json
|
|
{
|
|
"queries": ["solar eclipse"],
|
|
"max_results": 50,
|
|
"language": "en",
|
|
"country": "US",
|
|
"safe_search": "strict",
|
|
"spellcheck": true
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `queries` | array[string] | Yes | - | Search queries (1-10) |
|
|
| `max_results` | integer | No | 50 | Results per query (1-200) |
|
|
| `language` | string | No | "en" | Search language (ISO 639-1) |
|
|
| `country` | string | No | "US" | Search country (ISO 3166-1) |
|
|
| `safe_search` | string | No | "strict" | off or strict |
|
|
| `spellcheck` | boolean | No | true | Enable spellcheck |
|
|
|
|
#### Response
|
|
|
|
```json
|
|
{
|
|
"request_id": "uuid",
|
|
"results": [
|
|
{
|
|
"query": "solar eclipse",
|
|
"image_url": "https://example.com/eclipse.jpg",
|
|
"thumbnail_url": "https://example.com/eclipse_thumb.jpg",
|
|
"source_url": "https://example.com/article",
|
|
"title": "Solar Eclipse Photo",
|
|
"description": "A total solar eclipse captured in 2024",
|
|
"width": 1920,
|
|
"height": 1080,
|
|
"publisher": "example.com",
|
|
"rank": 1
|
|
}
|
|
],
|
|
"total_results": 50,
|
|
"execution_time_ms": 200.5,
|
|
"queries_processed": 1
|
|
}
|
|
```
|
|
|
|
#### Example
|
|
|
|
```bash
|
|
curl -X POST http://localhost:51100/v1/image-search \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"queries": ["solar eclipse", "northern lights"],
|
|
"max_results": 5,
|
|
"safe_search": "strict"
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
### Fetch
|
|
|
|
Fetch and extract content from URLs with automatic fallback (HTTP → Playwright → Vision LLM).
|
|
|
|
```
|
|
POST /v1/fetch
|
|
```
|
|
|
|
#### Request Body
|
|
|
|
```json
|
|
{
|
|
"urls": ["https://example.com/article"],
|
|
"extract_text": true,
|
|
"include_html": false,
|
|
"extract_metadata": true,
|
|
"auto_fallback": true,
|
|
"method": "auto",
|
|
"timeout_seconds": 30.0,
|
|
"min_text_length": 200,
|
|
"parallel_fetches": 5
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `urls` | array[string] | Yes | - | URLs to fetch (1-50) |
|
|
| `extract_text` | boolean | No | true | Extract main text content |
|
|
| `include_html` | boolean | No | false | Include raw HTML |
|
|
| `extract_metadata` | boolean | No | true | Extract metadata |
|
|
| `auto_fallback` | boolean | No | true | Auto-escalate on failure |
|
|
| `method` | string | No | "auto" | "auto", "http", "browse", "vision" |
|
|
| `timeout_seconds` | number | No | 30.0 | Timeout per URL (1-120) |
|
|
| `min_text_length` | integer | No | 200 | Min text before fallback |
|
|
| `parallel_fetches` | integer | No | 5 | Concurrent fetches (1-20) |
|
|
|
|
#### Response
|
|
|
|
```json
|
|
{
|
|
"request_id": "uuid",
|
|
"pages": [
|
|
{
|
|
"url": "https://example.com/article",
|
|
"title": "Article Title",
|
|
"text": "Extracted text content...",
|
|
"text_hash": "sha256...",
|
|
"extraction_method": "http",
|
|
"fallback_chain": [],
|
|
"retrieved_at": "2025-01-20T10:00:00Z",
|
|
"extraction_time_ms": 500.0,
|
|
"status_code": 200,
|
|
"content_type": "text/html"
|
|
}
|
|
],
|
|
"total_fetched": 1,
|
|
"total_failed": 0,
|
|
"execution_time_ms": 600.0,
|
|
"failed_urls": []
|
|
}
|
|
```
|
|
|
|
#### Example
|
|
|
|
```bash
|
|
curl -X POST http://localhost:51100/v1/fetch \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"urls": ["https://en.wikipedia.org/wiki/Climate_change"],
|
|
"method": "auto",
|
|
"auto_fallback": true
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
### Info
|
|
|
|
Get component information for service catalog.
|
|
|
|
```
|
|
GET /v1/info
|
|
```
|
|
|
|
#### Response
|
|
|
|
Returns complete metadata about this service including resource information, available functions, and their schemas. Used by the catalog-api for service discovery.
|
|
|
|
#### Example
|
|
|
|
```bash
|
|
curl http://localhost:51100/v1/info
|
|
```
|
|
|
|
---
|
|
|
|
### Health Check
|
|
|
|
Check service health and provider status.
|
|
|
|
```
|
|
GET /health
|
|
```
|
|
|
|
#### Response
|
|
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"providers": [
|
|
{
|
|
"name": "searxng",
|
|
"healthy": true,
|
|
"message": null
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
| Status | Description |
|
|
|--------|-------------|
|
|
| `healthy` | All providers operational |
|
|
| `degraded` | Some providers unavailable |
|
|
| `unhealthy` | All providers down |
|
|
|
|
---
|
|
|
|
### Readiness Probe
|
|
|
|
Check if service is ready to accept requests.
|
|
|
|
```
|
|
GET /ready
|
|
```
|
|
|
|
#### Response
|
|
|
|
```json
|
|
{
|
|
"ready": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Error Responses
|
|
|
|
### Error Format
|
|
|
|
```json
|
|
{
|
|
"detail": {
|
|
"error": "error_code",
|
|
"message": "Human readable message",
|
|
"provider": "searxng"
|
|
}
|
|
}
|
|
```
|
|
|
|
### HTTP Status Codes
|
|
|
|
| Code | Error | Description |
|
|
|------|-------|-------------|
|
|
| 400 | `validation_error` | Invalid request body |
|
|
| 401 | `authentication_required` | Missing or invalid auth token |
|
|
| 422 | `validation_error` | Request validation failed |
|
|
| 429 | `rate_limit_exceeded` | Too many requests |
|
|
| 502 | `provider_error` | Search provider error |
|
|
| 503 | `service_unavailable` | Concurrency limit reached |
|
|
| 504 | `timeout` | Request timeout |
|
|
|
|
---
|
|
|
|
## Request Headers
|
|
|
|
| Header | Required | Description |
|
|
|--------|----------|-------------|
|
|
| `Content-Type` | Yes | Must be `application/json` |
|
|
| `Authorization` | Conditional | Bearer token (if auth enabled) |
|
|
| `X-Request-ID` | No | Custom request ID for tracing |
|
|
|
|
---
|
|
|
|
## Rate Limiting
|
|
|
|
The API implements token bucket rate limiting:
|
|
|
|
- **Default:** 10 requests/second with burst of 20
|
|
- **429 Response:** Includes `Retry-After` header
|
|
|
|
**Note:** Rate limiting is per-process. In multi-replica deployments, use external rate limiting.
|
|
|
|
---
|
|
|
|
## SDK Example (Python)
|
|
|
|
```python
|
|
import httpx
|
|
|
|
async def search(query: str, base_url: str = "http://localhost:51100"):
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.post(
|
|
f"{base_url}/v1/search",
|
|
json={
|
|
"queries": [query],
|
|
"max_results": 10,
|
|
},
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
|
|
# Usage
|
|
results = await search("climate change")
|
|
for r in results["results"]:
|
|
print(f"{r['title']}: {r['url']}")
|
|
```
|