Forage API
Forage turns any web page or audio file into AI-ready data. Every endpoint is a single HTTPS request that returns markdown, structured JSON, an image, a PDF, or a transcript — whatever an agent or pipeline needs next.
https://forageapi.com — the examples below use that base URL. Swap in forageapi.com once it's announced.Quickstart
Two calls and you're done: mint a free key, then convert your first page.
1. Get a free key (300 credits, no card)
curl -X POST https://forageapi.com/v1/keys \
-H "content-type: application/json" \
-d '{"email":"you@example.com"}'The response includes your key. It's shown exactly once — store it now.
{
"key": "fk_live_9f8a1c...e2",
"key_id": "key_ab12cd34ef56",
"credits": 300,
"message": "Store this key now — it is shown exactly once.",
"docs": "https://forageapi.com/docs"
}2. Convert a page to markdown
curl -X POST https://forageapi.com/v1/markdown \
-H "Authorization: Bearer fk_live_9f8a1c...e2" \
-H "content-type: application/json" \
-d '{"url":"https://example.com"}'That's it. Every other endpoint follows the same shape: POST JSON, pass your bearer token, get JSON (or a binary file) back.
Authentication
Pass your key as a bearer token on every request except creating a key and the public GET /health check.
Authorization: Bearer fk_live_...
Keys start with fk_live_. Lose yours? There's no recovery — mint a new one (one per email means you'll want a fresh address, or email us to reset). Requests are rate-limited to 60 per minute per key.
Credits & billing
Every call spends credits. Your free key starts with 300; top up in one-time packs with no subscription (see pricing).
| Endpoint | Cost |
|---|---|
| /v1/markdown | 1 credit |
| /v1/screenshot | 1 credit |
| /v1/pdf | 2 credits |
| /v1/extract | 2 credits |
| /v1/reviews | 2 credits (not charged if no reviews found) |
| /v1/transcribe | 2 credits minimum, then 1 per started minute |
| /v1/keys, /v1/usage | Free |
Errors
Errors return a JSON body with an error code (and usually a message) alongside the HTTP status.
| Status | Code | Meaning |
|---|---|---|
| 400 | missing_url / missing_schema / invalid_email | The request body is missing a required field or is malformed. |
| 401 | missing_api_key / invalid_api_key | No bearer token, or the key is unknown or disabled. |
| 402 | insufficient_credits | Not enough credits. Response includes a buy link. |
| 409 | email_exists | A free key was already issued for that email. |
| 422 | audio_too_large | Audio exceeds the 24MB limit for transcription. |
| 429 | rate_limited | Over 60 requests/minute per key (or too many signups per IP). |
| 502 | fetch_failed / conversion_failed / capture_failed | An upstream fetch or conversion failed. Auto-refunded. |
{
"error": "insufficient_credits",
"buy": "https://forageapi.com/#pricing"
}Create a key
Mint a free API key seeded with 300 credits. One key per email address; the secret is returned once and never again.
Request body
email(string, required) — a valid email address.
curl -X POST https://forageapi.com/v1/keys \
-H "content-type: application/json" \
-d '{"email":"you@example.com"}'Response · 201
{
"key": "fk_live_9f8a1c...e2",
"key_id": "key_ab12cd34ef56",
"credits": 300,
"message": "Store this key now — it is shown exactly once.",
"docs": "https://forageapi.com/docs"
}Errors: 400 invalid_email, 409 email_exists, 429 rate_limited.
Markdown
Fetch a page and return clean, LLM-ready markdown with boilerplate removed.
Request body
url(string, required) — the page to convert.render(string, optional) —"auto"(default),"never", or"always". Controls headless-browser rendering.
curl -X POST https://forageapi.com/v1/markdown \
-H "Authorization: Bearer fk_live_..." \
-H "content-type: application/json" \
-d '{"url":"https://example.com","render":"auto"}'Response · 200
{
"url": "https://example.com",
"rendered": false,
"markdown": "# Example Domain\n\nThis domain is for use in...",
"tokens_estimate": 42
}rendered tells you whether a headless browser was used. tokens_estimate is a rough token count for budgeting.
Screenshot
Capture a PNG of a page rendered in a real headless browser. Returns the raw image with content-type: image/png.
Request body
url(string, required).full_page(boolean, default false) — capture the entire scrollable page.width(integer, default 1280) ·height(integer, default 800) — viewport, clamped 320–2560.wait_ms(integer, default 0) — extra wait after load, up to 5000ms.
curl -X POST https://forageapi.com/v1/screenshot \
-H "Authorization: Bearer fk_live_..." \
-H "content-type: application/json" \
-d '{"url":"https://example.com","full_page":true}' \
--output screenshot.pngResponse · 200
Binary PNG data (image/png). Pipe it to a file with --output as above.
Render a live page to a print-ready A4 PDF with backgrounds. Returns application/pdf.
Request body
url(string, required).width·height(integer, optional) — viewport for layout.wait_ms(integer, optional) — extra wait after load, up to 5000ms.
curl -X POST https://forageapi.com/v1/pdf \
-H "Authorization: Bearer fk_live_..." \
-H "content-type: application/json" \
-d '{"url":"https://example.com"}' \
--output page.pdfResponse · 200
Binary PDF data (application/pdf).
Extract
Pull structured JSON from a page (or raw HTML) that matches a JSON Schema you supply. Forage never invents data — fields not present in the content come back null.
Request body
url(string) orhtml(string) — one is required.schema(object, required) — a JSON Schema describing the output you want.instructions(string, optional) — extra guidance for the extractor.render(string, optional) —"auto"/"never"/"always".
curl -X POST https://forageapi.com/v1/extract \
-H "Authorization: Bearer fk_live_..." \
-H "content-type: application/json" \
-d '{
"url": "https://example.com/product/42",
"schema": {
"type": "object",
"properties": {
"title": { "type": "string" },
"price": { "type": "number" },
"in_stock": { "type": "boolean" }
}
}
}'Response · 200
{
"url": "https://example.com/product/42",
"rendered": false,
"data": {
"title": "Foraging Basket, Wax Canvas",
"price": 48.0,
"in_stock": true
}
}Errors: 400 missing_input (no url or html), 400 missing_schema.
Transcribe
Transcribe an audio file with Whisper, returning full text plus timestamped segments and a VTT track. Charged 2 credits minimum, then 1 credit per started minute of audio. Maximum file size is 24MB.
Request body
url(string, required) — a direct link to an audio file.
curl -X POST https://forageapi.com/v1/transcribe \
-H "Authorization: Bearer fk_live_..." \
-H "content-type: application/json" \
-d '{"url":"https://example.com/episode.mp3"}'Response · 200
{
"url": "https://example.com/episode.mp3",
"duration_seconds": 184.2,
"credits_charged": 4,
"text": "Welcome back to the show. Today we're...",
"segments": [
{ "start": 0.0, "end": 4.8, "text": "Welcome back to the show." },
{ "start": 4.8, "end": 9.1, "text": "Today we're talking about..." }
],
"vtt": "WEBVTT\n\n00:00.000 --> 00:04.800\nWelcome back..."
}Errors: 422 audio_too_large (over 24MB), 502 fetch_failed (audio URL unreachable — auto-refunded).
Reviews
Extract schema.org Review and AggregateRating data from any page carrying JSON-LD markup (many product, store, and Trustpilot-style pages). If the page has no review markup, you are not charged.
Request body
url(string, required).render(string, optional) —"auto"/"never"/"always".
curl -X POST https://forageapi.com/v1/reviews \
-H "Authorization: Bearer fk_live_..." \
-H "content-type: application/json" \
-d '{"url":"https://example.com/product/42"}'Response · 200 (reviews found)
{
"url": "https://example.com/product/42",
"rendered": false,
"subject": "Foraging Basket, Wax Canvas",
"aggregate": { "rating": 4.6, "count": 128 },
"count": 2,
"reviews": [
{
"author": "Dana R.",
"rating": 5,
"date": "2026-05-11",
"title": "Holds up in the rain",
"body": "Took it out mushroom hunting all season..."
},
{
"author": "Sam T.",
"rating": 4,
"date": "2026-04-02",
"title": "Roomy",
"body": "Wish the strap were a touch longer."
}
]
}Response · 200 (none found — not charged)
{
"url": "https://example.com/plain-page",
"rendered": false,
"reviews": [],
"aggregate": null,
"message": "No schema.org review markup found on this page. You were not charged."
}Usage
Check your current balance and the 50 most recent usage events for your key.
curl https://forageapi.com/v1/usage \
-H "Authorization: Bearer fk_live_..."Response · 200
{
"key_id": "key_ab12cd34ef56",
"balance": 294,
"recent": [
{ "endpoint": "markdown", "credits": 1, "created_at": "2026-07-02T18:20:11Z" },
{ "endpoint": "extract", "credits": 2, "created_at": "2026-07-02T18:19:47Z" }
]
}