API Reference
Base URL: https://averra.dev/api/v1/extract
All endpoints require Authorization: Bearer YOUR_API_KEY.
POST /extract
Convert a URL to clean Markdown.
1.1 seconds apart, or respect the Retry-After header when you receive a 429. See Rate Limits below for details.curl -X POST https://averra.dev/api/v1/extract \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"url": "https://example.com"}'Request body
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The webpage URL to extract. Must be a valid HTTP/HTTPS URL, max 2048 characters. Private, loopback, and link-local addresses are rejected. |
Response (200)
{
"markdown": "# Example Domain\n\nThis domain is for use in illustrative examples...",
"metadata": {
"title": "Example Domain",
"word_count": 20,
"links": ["https://iana.org/domains/example"],
"language": "en",
"timestamp": "2026-03-30T17:21:42.652Z"
}
}| Field | Type | Description |
|---|---|---|
| markdown | string | The extracted page content as Markdown |
| metadata.title | string | Page title (extracted from the page's metadata, heading, or URL) |
| metadata.word_count | number | Approximate word count of the content |
| metadata.links | string[] | All unique links found in the content |
| metadata.language | string | Detected language ("en" or "unknown") |
| metadata.timestamp | string | ISO 8601 timestamp of when the content was extracted |
| warning | string? | Present if content is under 200 words (thin content) |
Caching
Results are cached for 1 week. Repeated requests for the same URL return the cached version instantly. Cache is shared across all users.
Performance
| Scenario | Latency |
|---|---|
| Cached | < 500ms |
| Uncached | 3-15s (depends on target page) |
GET /extract/usage
Check your current monthly usage.
curl https://averra.dev/api/v1/extract/usage \
-H "Authorization: Bearer YOUR_API_KEY"Response (200)
{
"plan": "free",
"monthly_limit": 50,
"used": 42,
"remaining": 8
}| Field | Type | Description |
|---|---|---|
| plan | string | Your current plan: "free", "starter", "pro", or "scale" |
| monthly_limit | number | Total pages allowed this month |
| used | number | Pages used this month |
| remaining | number | Pages remaining this month |
POST /extract/keys
Create a new API key. The new key automatically inherits the plan and limits from your account's current subscription.
No request body required.
curl -X POST https://averra.dev/api/v1/extract/keys \
-H "Authorization: Bearer YOUR_EXISTING_KEY"Response (201)
{
"key": "sk_live_79519fab64062639cc3dd53e09d02b7f3aafb2541230100e",
"id": "678a6ec9-2afa-426d-a07a-12ba5103a8ca",
"prefix": "sk_live_7951",
"plan": "free",
"monthly_limit": 50,
"created_at": "2026-03-30T18:12:59.794Z",
"warning": "Store this key securely. It will not be shown again."
}The key field contains the full plaintext key. This is the only time it will be shown.
GET /extract/keys
List all API keys for your account.
curl https://averra.dev/api/v1/extract/keys \
-H "Authorization: Bearer YOUR_API_KEY"Response (200)
{
"keys": [
{
"id": "678a6ec9-2afa-426d-a07a-12ba5103a8ca",
"key_prefix": "sk_live_7951",
"plan": "free",
"monthly_limit": 50,
"is_active": true,
"created_at": "2026-03-30T18:12:59.794Z",
"revoked_at": null
}
]
}Returns all keys (active and revoked) sorted by creation date, newest first.
DELETE /extract/keys/:id
Revoke an API key.
Parameters
| Parameter | Type | Description |
|---|---|---|
| id | string (UUID) | The key ID to revoke |
curl -X DELETE https://averra.dev/api/v1/extract/keys/KEY_ID \
-H "Authorization: Bearer YOUR_API_KEY"Response (200)
{
"message": "API key revoked",
"id": "678a6ec9-2afa-426d-a07a-12ba5103a8ca",
"prefix": "sk_live_7951",
"revoked_at": "2026-03-30T18:13:10.674Z"
}Constraints
- You cannot revoke the key you are currently using to authenticate
- You can only revoke keys belonging to your account
- Already-revoked keys return a 404
Rate Limits
| Limit | Value | Scope |
|---|---|---|
| Per-minute throughput | 60 requests/minute | Per user (across all keys) |
| Monthly page limit | Depends on plan | Per user (across all keys) |
| Requests per second | 10 (Cloudflare rendering limit) | Global |
Per-minute throughput limit
To prevent runaway scripts from accidentally burning through your entire monthly quota, the API limits each user to 60 requests per minute. This is a safety net, not a restriction — normal usage rarely hits this limit.
If you're scraping in a loop, add a small delay between requests (e.g., 1 second) or respect the Retry-After header when you receive a 429 response:
{
"error": "Too many requests. Slow down to avoid exhausting your quota — max 60 requests per minute.",
"status": 429
}Monthly limit
When you exceed your monthly limit, the API returns 429 with your current usage:
{
"error": "Monthly usage limit exceeded",
"status": 429,
"limit": 50,
"usage": 50,
"plan": "free"
}