api
REST API quickstart
MetricSpot's REST API in one page: Bearer auth at app.metricspot.com, six endpoints, rate limits, error codes, JSON over HTTPS.
What MetricSpot’s REST API does
MetricSpot’s REST API is a JSON-over-HTTPS interface at app.metricspot.com that wraps the same audit pipeline powering the dashboard. It exposes six endpoints: run an audit, fetch one by id, list recent audits, generate a branded PDF, and pull organic traffic from linked Google Analytics 4 and Search Console properties.
Capabilities:
- Run a one-shot anonymous audit on any public URL (no auth, 1 per IP per 24 hours).
- Queue a full audit asynchronously and poll until complete.
- Fetch an audit envelope by id with score, module breakdown, and findings.
- List recent audits, deduplicated by URL.
- Trigger PDF generation and stream the file once ready.
- Read a 28-day organic-traffic snapshot for any audit, cached 24 hours.
The API is the same surface MetricSpot’s own dashboard talks to. Anything you can see in the UI, an API client can reproduce.
Why it matters
A REST API turns audits into a building block. A CI bot can audit a preview deploy and fail the build on red findings. A Zapier flow can run a weekly audit and post the score to Slack. A reporting agency can pull PDFs for 200 clients on a schedule. None of these require browser automation: just HTTPS + a Bearer token.
Concrete workflows:
- An audit-on-PR bot calls
POST /api/auditswhen a preview URL deploys, pollsGET /api/audits/:iduntilstatus === "completed", and posts the score delta back to the PR. - A weekly Zapier zap calls
GET /api/auditsto list every URL audited this month, then triggers a Slack message if any score dropped more than 5 points. - A white-label agency cron fetches
POST /api/audits/:id/pdfovernight for every client domain and emails the rendered PDF the next morning.
How to use it
All endpoints except POST /api/public/audit require a Bearer API key minted from your MetricSpot account. The anonymous audit is cap-limited by IP and intentionally skips PageSpeed Insights to keep the cost predictable.
Auth header:
Authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Mint a key at app.metricspot.com/settings/api-keys. Up to 10 active keys per account. Keys start with ms_live_ and are shown once on creation.
Endpoints
| Method | Path | Auth | Rate limit |
|---|---|---|---|
POST | /api/public/audit | none | 1 per IP per 24 hours |
POST | /api/audits | Bearer | Free 10/mo, Starter 50/mo, Pro unlimited (plus per-domain cooldown) |
GET | /api/audits | Bearer | none beyond plan |
GET | /api/audits/:id | Bearer | none beyond plan |
POST | /api/audits/:id/pdf then GET /api/pdfs/:id | Bearer | none beyond plan |
GET | /api/audits/:id/google | Bearer + Pro (GA4 / GSC linked) | none beyond plan, cached 24h |
The full machine-readable catalog lives at /.well-known/api-catalog per RFC 9727.
Quickstart: anonymous audit (no key)
curl -X POST https://app.metricspot.com/api/public/audit \
-H "content-type: application/json" \
-d '{"url": "https://example.com"}'
Quickstart: authenticated audit + poll
# 1. Queue
curl -X POST https://app.metricspot.com/api/audits \
-H "authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "content-type: application/json" \
-d '{"url": "https://example.com"}'
# 2. Poll (replace 12345 with the returned audit_id)
curl https://app.metricspot.com/api/audits/12345 \
-H "authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Quickstart: Node fetch
const res = await fetch("https://app.metricspot.com/api/audits", {
method: "POST",
headers: {
"content-type": "application/json",
authorization: "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx",
},
body: JSON.stringify({ url: "https://example.com" }),
});
const { audit } = await res.json();
console.log(audit.id, audit.status);
Quickstart: Python httpx
import httpx
r = httpx.post(
"https://app.metricspot.com/api/audits",
headers={"authorization": "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx"},
json={"url": "https://example.com"},
timeout=30.0,
)
print(r.json()["audit"])
Response envelope
Every successful response is JSON. Mutating endpoints return 201 Created with the newly created resource; read endpoints return 200 OK with the resource and any related data (findings, plan, cooldown) the dashboard uses to render the same view.
Errors are JSON with at minimum error and an HTTP status code; some endpoints add message for human-readable detail.
Common errors
| Code | When | Action |
|---|---|---|
UNAUTHORIZED (401) | Missing or invalid Bearer token | Mint a key at app.metricspot.com/settings/api-keys |
FORBIDDEN (403) | Token valid but not allowed for this resource (e.g. another user’s audit) | Use a key for the owning account |
RATE_LIMITED (429) | Anonymous IP cap or per-domain cooldown | Wait the indicated window |
QUOTA_EXCEEDED (402) | Monthly plan allowance used up | Upgrade at app.metricspot.com/billing |
INVALID_URL (400) | URL not parseable, not absolute, or longer than 2000 chars | Pass an absolute https:// URL |
AUDIT_NOT_FOUND (404) | audit_id doesn’t exist or isn’t yours | List audits to find a valid id |
UPSTREAM_FAILED (5xx) | PageSpeed Insights, GA4, or GSC blip | Retry with backoff |
Frequently asked questions
Is the REST API free?
The anonymous endpoint (POST /api/public/audit) is free, capped at 1 audit per IP per 24 hours, and skips Core Web Vitals to keep cost predictable. The five authenticated endpoints count against your plan: Free 10 audits per month, Starter 50, Pro unlimited. List, get, PDF, and organic-traffic endpoints have no per-call cost beyond the audit they reference.
Where is the OpenAPI spec?
The machine-readable catalog is at https://metricspot.com/.well-known/api-catalog following RFC 9727. It links to the JSON spec for every endpoint and is what discovery agents read first.
How long does an audit take?
10 to 30 seconds for typical sites. JS-heavy targets or sites with large amounts of structured data can take up to 90 seconds. PageSpeed Insights is fetched in parallel with the crawler, so the bottleneck is usually Google’s PSI response time.
Can I use the API from the browser?
The anonymous endpoint accepts CORS from metricspot.com. Authenticated endpoints do not set permissive CORS by design: tokens belong on the server, never in client JavaScript. Use a serverless function or backend route as the proxy.
Sources
Last updated 2026-05-14