proxy-pool/docs/04-api-reference.md

406 lines
8.7 KiB
Markdown
Raw Permalink 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.

# API reference
## Authentication
All endpoints except `POST /auth/register` and `GET /health` require an API key in the `Authorization` header:
```
Authorization: Bearer pp_a1b2c3d4e5f6g7h8i9j0...
```
API keys use a `pp_` prefix (proxy pool) followed by 48 random characters. The prefix aids visual identification and log filtering.
Unauthenticated or invalid requests return `401 Unauthorized`. Requests with valid keys but insufficient credits return `402 Payment Required`.
## Common response patterns
### Pagination
List endpoints support cursor-based pagination:
```
GET /proxies?limit=50&cursor=eyJpZCI6Ii4uLiJ9
```
Response includes a `next_cursor` field when more results exist:
```json
{
"items": [...],
"next_cursor": "eyJpZCI6Ii4uLiJ9",
"total_count": 1234
}
```
### Error responses
All errors follow a consistent shape:
```json
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "You need at least 1 credit to acquire a proxy. Current balance: 0.",
"details": {}
}
}
```
## Proxy domain endpoints
### Sources
#### `GET /sources`
List all configured proxy sources.
**Query parameters**: `is_active` (bool, optional), `limit` (int, default 50), `cursor` (string, optional).
**Response** `200`:
```json
{
"items": [
{
"id": "uuid",
"url": "https://example.com/proxies.txt",
"parser_name": "plaintext",
"cron_schedule": "*/30 * * * *",
"default_protocol": "http",
"is_active": true,
"last_scraped_at": "2025-01-15T10:30:00Z",
"created_at": "2025-01-01T00:00:00Z"
}
],
"next_cursor": null,
"total_count": 5
}
```
#### `POST /sources`
Add a new proxy source.
**Request body**:
```json
{
"url": "https://example.com/proxies.txt",
"parser_name": "plaintext",
"cron_schedule": "*/30 * * * *",
"default_protocol": "http"
}
```
**Validation**: The `parser_name` must match a registered plugin. If omitted, the registry attempts auto-detection via `supports()`. Returns `422` if no matching parser is found.
**Response** `201`: The created source object.
#### `PATCH /sources/{source_id}`
Update a source. All fields are optional — only provided fields are changed.
#### `DELETE /sources/{source_id}`
Delete a source. Associated proxies are NOT deleted (they may have been discovered by multiple sources).
#### `POST /sources/{source_id}/scrape`
Trigger an immediate scrape of the source, bypassing the cron schedule. Returns the scrape result.
**Response** `200`:
```json
{
"source_id": "uuid",
"proxies_discovered": 142,
"proxies_new": 23,
"proxies_updated": 119,
"duration_ms": 1540
}
```
### Proxies
#### `GET /proxies`
Query the proxy pool with filtering and sorting.
**Query parameters**:
| Parameter | Type | Description |
|-----------|------|-------------|
| `status` | string | Filter by status: `active`, `dead`, `unchecked` |
| `protocol` | string | Filter by protocol: `http`, `https`, `socks4`, `socks5` |
| `anonymity` | string | Filter by anonymity: `transparent`, `anonymous`, `elite` |
| `country` | string | ISO 3166-1 alpha-2 country code |
| `min_score` | float | Minimum composite score (0.01.0) |
| `max_latency_ms` | float | Maximum average latency |
| `min_uptime_pct` | float | Minimum uptime percentage |
| `verified_within_minutes` | int | Only proxies checked within the last N minutes |
| `sort` | string | Sort field: `score`, `latency`, `uptime`, `last_checked` |
| `order` | string | Sort order: `asc`, `desc` (default: `desc` for score) |
| `limit` | int | Results per page (default: 50, max: 200) |
| `cursor` | string | Pagination cursor |
**Response** `200`:
```json
{
"items": [
{
"id": "uuid",
"ip": "203.0.113.42",
"port": 8080,
"protocol": "http",
"status": "active",
"anonymity": "elite",
"exit_ip": "203.0.113.42",
"country": "US",
"score": 0.87,
"avg_latency_ms": 245.3,
"uptime_pct": 94.2,
"last_checked_at": "2025-01-15T10:25:00Z",
"first_seen_at": "2025-01-10T08:00:00Z",
"tags": {"provider": "datacenter"}
}
],
"next_cursor": "...",
"total_count": 892
}
```
#### `GET /proxies/{proxy_id}`
Get detailed info for a single proxy, including recent check history.
**Response** `200`:
```json
{
"proxy": { ... },
"recent_checks": [
{
"checker_name": "tcp_connect",
"stage": 1,
"passed": true,
"latency_ms": 120.5,
"detail": "TCP connect OK",
"created_at": "2025-01-15T10:25:00Z"
}
]
}
```
#### `POST /proxies/acquire`
Acquire a proxy with an exclusive lease. Costs 1 credit.
**Request body**:
```json
{
"protocol": "http",
"country": "US",
"anonymity": "elite",
"min_score": 0.7,
"lease_duration_seconds": 300
}
```
All filter fields are optional. `lease_duration_seconds` defaults to 300 (5 minutes), max 3600 (1 hour).
**Response** `200`:
```json
{
"lease_id": "uuid",
"proxy": {
"ip": "203.0.113.42",
"port": 8080,
"protocol": "http",
"country": "US",
"anonymity": "elite"
},
"expires_at": "2025-01-15T10:30:00Z",
"credits_remaining": 42
}
```
**Error responses**: `402` if insufficient credits, `404` if no proxy matches the filters, `409` if all matching proxies are currently leased.
#### `POST /proxies/acquire/{lease_id}/release`
Release a lease early. The proxy becomes available immediately. The credit is NOT refunded (credits are consumed on acquisition).
#### `POST /proxies/test`
Test whether good proxies can reach a specific URL.
**Request body**:
```json
{
"url": "https://example.com",
"count": 5,
"timeout_seconds": 10,
"protocol": "http",
"country": "US"
}
```
**Response** `200`:
```json
{
"url": "https://example.com",
"results": [
{
"proxy_id": "uuid",
"ip": "203.0.113.42",
"port": 8080,
"reachable": true,
"status_code": 200,
"latency_ms": 340,
"error": null
},
{
"proxy_id": "uuid",
"ip": "198.51.100.10",
"port": 3128,
"reachable": false,
"status_code": null,
"latency_ms": null,
"error": "Connection refused by target"
}
],
"success_rate": 0.8
}
```
### Stats
#### `GET /stats/pool`
Pool health overview.
**Response** `200`:
```json
{
"total_proxies": 15420,
"by_status": {"active": 3200, "dead": 11800, "unchecked": 420},
"by_protocol": {"http": 8000, "https": 4000, "socks4": 1200, "socks5": 2220},
"by_anonymity": {"transparent": 1500, "anonymous": 1000, "elite": 700},
"avg_score": 0.62,
"avg_latency_ms": 380.5,
"sources_active": 12,
"sources_total": 15,
"last_scrape_at": "2025-01-15T10:30:00Z",
"last_validation_at": "2025-01-15T10:25:00Z"
}
```
#### `GET /stats/plugins`
Plugin registry status.
**Response** `200`:
```json
{
"parsers": [{"name": "plaintext", "type": "SourceParser"}],
"checkers": [
{"name": "tcp_connect", "stage": 1, "priority": 0},
{"name": "http_anonymity", "stage": 2, "priority": 0}
],
"notifiers": [
{"name": "smtp", "healthy": true, "subscribes_to": ["proxy.pool_low", "credits.*"]},
{"name": "webhook", "healthy": false, "subscribes_to": ["*"]}
]
}
```
## Accounts domain endpoints
### Auth
#### `POST /auth/register`
Create a new user account and initial API key. No authentication required.
**Request body**:
```json
{
"email": "user@example.com",
"display_name": "Alice"
}
```
**Response** `201`:
```json
{
"user": {"id": "uuid", "email": "user@example.com", "display_name": "Alice"},
"api_key": {
"id": "uuid",
"key": "pp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4",
"prefix": "pp_a1b2c",
"label": "default"
}
}
```
**Important**: The `key` field is the raw API key. It is returned ONLY in this response. Store it securely — it cannot be retrieved again.
#### `POST /auth/keys`
Create an additional API key for the authenticated user.
#### `GET /auth/keys`
List all API keys for the authenticated user (returns prefix and metadata, never the full key).
#### `DELETE /auth/keys/{key_id}`
Revoke an API key.
### Account
#### `GET /account`
Get the authenticated user's account info.
#### `GET /account/credits`
Get current credit balance and recent transaction history.
**Response** `200`:
```json
{
"balance": 42,
"recent_transactions": [
{
"amount": -1,
"tx_type": "acquire",
"description": "Proxy acquired: 203.0.113.42:8080",
"created_at": "2025-01-15T10:25:00Z"
},
{
"amount": 100,
"tx_type": "purchase",
"description": "Credit purchase",
"created_at": "2025-01-14T00:00:00Z"
}
]
}
```
#### `GET /account/leases`
List the authenticated user's active proxy leases.
## System endpoints
#### `GET /health`
Basic health check. No authentication required.
**Response** `200`:
```json
{
"status": "healthy",
"postgres": "connected",
"redis": "connected",
"version": "0.1.0"
}
```