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.

Rate limit: 60 requests / minute per user. If you're ingesting URLs in a loop (e.g. building a RAG corpus), space requests at least 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

FieldTypeRequiredDescription
urlstringYesThe webpage URL to extract. Must be a valid HTTP/HTTPS URL, max 2048 characters. Private, loopback, and link-local addresses are rejected.

Response (200)

json
{
  "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"
  }
}
FieldTypeDescription
markdownstringThe extracted page content as Markdown
metadata.titlestringPage title (extracted from the page's metadata, heading, or URL)
metadata.word_countnumberApproximate word count of the content
metadata.linksstring[]All unique links found in the content
metadata.languagestringDetected language ("en" or "unknown")
metadata.timestampstringISO 8601 timestamp of when the content was extracted
warningstring?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

ScenarioLatency
Cached< 500ms
Uncached3-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)

json
{
  "plan": "free",
  "monthly_limit": 50,
  "used": 42,
  "remaining": 8
}
FieldTypeDescription
planstringYour current plan: "free", "starter", "pro", or "scale"
monthly_limitnumberTotal pages allowed this month
usednumberPages used this month
remainingnumberPages 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)

json
{
  "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)

json
{
  "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

ParameterTypeDescription
idstring (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)

json
{
  "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

LimitValueScope
Per-minute throughput60 requests/minutePer user (across all keys)
Monthly page limitDepends on planPer user (across all keys)
Requests per second10 (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:

json
{
  "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:

json
{
  "error": "Monthly usage limit exceeded",
  "status": 429,
  "limit": 50,
  "usage": 50,
  "plan": "free"
}