REST API
The REST API exposes the same features as the MCP server over plain HTTPS and JSON: list sites, read reports, run audits, check pages and draft llms.txt files.
By Surfaced team · Updated
How do I authenticate?#
Create a key in Settings → API and MCP and send it as a bearer token. Every request is scoped to the key's workspace.
header
Authorization: Bearer sfc_your_key
Responses are JSON: { "data": … } on success, { "error": { "code", "message" } } otherwise. Base URL: https://getsurfaced.in/api/v1
Endpoints#
| Method | Path | What it does | Credits |
|---|---|---|---|
| GET | /sites | Sites in the workspace with latest scores | 0 |
| GET | /sites/:site/report?section= | Latest report. :site is an id or domain. section: summary, issues, fixes, competitors, full | 0 |
| POST | /audits | Start a full audit for a url or existing site | 1 + 1 per 3 AI questions |
| GET | /audits/:id | Audit status, progress and scores | 0 |
| POST | /check | Single-page SEO and AEO check from a url or raw html | 0 (300/day) |
| POST | /llms-txt | Draft an llms.txt from a site's pages | 0 (30/day) |
| GET | /credits | Balance, pricing and each site's report cost | 0 |
Check a page
terminal
curl https://getsurfaced.in/api/v1/check \
-H "Authorization: Bearer $SURFACED_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'Pass html instead of url to check markup that isn't published yet, with an optional pageUrl for canonical checks.
Run an audit and wait for it
node
const headers = { Authorization: `Bearer ${process.env.SURFACED_KEY}`, "Content-Type": "application/json" };
const { data: run } = await fetch("https://getsurfaced.in/api/v1/audits", {
method: "POST",
headers,
body: JSON.stringify({ url: "https://example.com", competitors: ["https://competitor.com"] }),
}).then((r) => r.json());
let audit;
do {
await new Promise((r) => setTimeout(r, 5000));
({ data: audit } = await fetch(`https://getsurfaced.in/api/v1/audits/${run.auditId}`, { headers }).then((r) => r.json()));
} while (audit.status === "queued" || audit.status === "running");
const { data: fixes } = await fetch(`https://getsurfaced.in/api/v1/sites/${run.site.id}/report?section=fixes`, { headers }).then((r) => r.json());
console.log(fixes.fixes);Errors and limits#
| Status | Meaning |
|---|---|
| 400 | Invalid input (bad URL, missing field) |
| 401 | Missing, invalid or revoked API key |
| 402 | Not enough credits for an audit |
| 404 | Site, report or audit not found in this workspace |
| 429 | Rate limited: 60 requests a minute per endpoint, 10 audits a minute |