api
GET /api/audits
List recent audits for your account, deduplicated by URL. Supports limit + offset pagination, ordered by display position then created_at.
What this endpoint does
GET /api/audits returns the most recent audits for the authenticated account, deduplicated by URL. If you’ve audited the same URL ten times, you get one row back: the latest one. The list is ordered by the user’s saved display position (set in the dashboard) and then by created_at descending.
- Deduplicated by URL: one row per unique URL.
- Ordered by
display_position ASC NULLS LAST, created_at DESC. - Returns up to 100 rows by default. No
limitoroffsetparameters in v1; the dashboard fetches the same shape. - Cheap and idempotent: no plan cost, no PSI, no crawler call.
Why it matters
This is the endpoint a dashboard, weekly digest, or CI dashboard hits first. It gives every URL the account cares about with its latest score, ready to be linked to GET /api/audits/:id for the full envelope or to POST /api/audits to queue a fresh re-run.
Concrete workflows:
- A weekly Zapier zap calls
GET /api/audits, diffs scores against last week’s snapshot in Airtable, and posts a Slack message for every URL that dropped more than 5 points. - An internal CI dashboard polls the endpoint every minute and renders a status grid keyed by
display_positionso the most important pages show up first.
How to use it
Bearer auth required. No query parameters.
Request
GET /api/audits HTTP/1.1
Host: app.metricspot.com
Authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx
curl
curl https://app.metricspot.com/api/audits \
-H "authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Node fetch
const res = await fetch("https://app.metricspot.com/api/audits", {
headers: { authorization: "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx" },
});
const { audits } = await res.json();
for (const a of audits) {
console.log(a.score, a.url);
}
Python httpx
import httpx
r = httpx.get(
"https://app.metricspot.com/api/audits",
headers={"authorization": "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx"},
timeout=30.0,
)
for a in r.json()["audits"]:
print(f"{a['score'] or '..'} {a['url']} ({a['status']})")
Response
200 OK:
{
"audits": [
{
"id": 12345,
"domain": "example.com",
"url": "https://example.com",
"status": "completed",
"score": 78,
"created_at": "2026-05-14T10:18:04.000Z",
"completed_at": "2026-05-14T10:18:24.000Z",
"display_position": 0
},
{
"id": 12321,
"domain": "example.com",
"url": "https://example.com/pricing",
"status": "completed",
"score": 71,
"created_at": "2026-05-13T09:02:11.000Z",
"completed_at": "2026-05-13T09:02:34.000Z",
"display_position": 1
}
]
}
Fields per row:
id: integer audit id, used in follow-up calls.domain: hostname.url: full URL audited.status: one ofqueued,running,completed,failed.score: integer 0 to 100, ornullwhile queued or running.created_at: ISO 8601 timestamp.completed_at: ISO 8601 timestamp, ornullif not yet complete.display_position: integer rank set in the dashboard via drag-and-drop, ornullif the user hasn’t reordered. The endpoint orders by this first.
The endpoint always returns {"audits": [...]}. There is no pagination envelope; the cap is 100 rows. Use POST /api/audits followed by GET /api/audits/:id for full per-audit detail.
Error envelope
{ "error": "Unauthorized" }
Common errors
| Code | When | Action |
|---|---|---|
UNAUTHORIZED (401) | Missing or invalid Bearer token | Mint a key at app.metricspot.com/settings/api-keys |
UPSTREAM_FAILED (5xx) | Database hiccup | Retry once with backoff |
The endpoint never returns 404 or 429: it’s a list of your own resources with no rate limit beyond your plan.
Frequently asked questions
Why is the list deduplicated by URL?
The dashboard shows one card per URL: re-auditing the same URL replaces the previous card’s score. The API mirrors that view exactly so a third-party UI can render the same list without re-implementing the dedupe.
How do I get every audit (including older runs of the same URL)?
Use the per-URL history endpoint exposed in the audit’s detail. The list endpoint is intentionally the “latest per URL” view because that’s what dashboards and digests need. A future revision may expose a flat unpaginated history.
Is display_position editable via the API?
Yes, indirectly: the dashboard’s drag-and-drop maps to a separate reorder endpoint that takes an array of URLs in the new order. The list endpoint reads the saved positions; it doesn’t write them.
Does this count against plan allowance?
No. The list endpoint is unmetered. Only POST /api/audits (and only on success) decrements the monthly counter.
Sources
Last updated 2026-05-14