Developer reference
REST API
Pull scores and issues into your own dashboards and ticketing, and trigger scans from CI. Five endpoints, JSON in and out, one base URL:
https://rampsight.com/api/v1Authentication
Every request carries an API key as a Bearer token. An administrator creates keys under Settings → API keys in the dashboard; the key is shown once, at creation, and never again — we store only a hash of it. Keys are scoped to your agency (they can read every client, site and scan, and start scans) and can be revoked at any time. An agency can hold up to 20 active keys.
Authorization: Bearer rs_live_h3Kq9… # keys start with rs_live_Keep keys in your CI secret store, not in source control. If one leaks, revoke it in the dashboard and create a new one — the old one stops working immediately.
Rate limits
Up to 120 requests per minute per key on the Agency plan, 300 on Scale. Past that, requests answer 429 with a Retry-After header (seconds); wait and retry. Counters are kept per server instance, so the allowance you actually get is never lower than this. All responses are sent with Cache-Control: no-store.
Errors
Every error is JSON with a single human-readable error field. Do not match on the message — it may be reworded; match on the status.
{ "error": "Invalid or revoked API key." }| Status | Meaning |
|---|---|
| 400 | The request could not be understood. |
| 401 | Missing, malformed, unknown or revoked API key. The response carries a WWW-Authenticate: Bearer header. |
| 402 | Your plan does not include the API, or the account is read-only (trial ended, subscription paused). The body carries a "code" of "plan_required" or "read_only". The API is included from the Agency plan up. |
| 404 | No such site or scan in your agency. Ids of other agencies answer the same way. |
| 409 | A scan of that site is already queued or running. |
| 429 | Rate limit exceeded. Wait the number of seconds in the Retry-After header, then retry. |
| 500 | Something failed on our side. Retry later. |
Endpoints
Timestamps are ISO-8601 in UTC. score is an integer from 0 to 100 (100 means no detectable issues) and grade is A–F, exactly as the dashboard shows them. status is one of queued, running, done, error. reportUrl is the public white-label report — anyone with the link can open it, so share it as you would share the report itself.
GET/me
The agency the key belongs to, its access state and its plan limits. A cheap probe for “is my key configured right?”. access.mode is "full" or "read_only" (trial over, subscription paused or ended) — in read-only mode POST /sites/{id}/scans answers 402.
Request
curl -H "Authorization: Bearer $RAMPSIGHT_API_KEY" \
https://rampsight.com/api/v1/meResponse · 200 OK
{
"agency": {
"id": "cmfg1a7rk0000v7k4x9b2n4qe",
"name": "Acme Digital",
"plan": "agency",
"locale": "en"
},
"access": { "mode": "full", "reason": "active", "trialEndsAt": null },
"limits": {
"maxSites": 40,
"sitesInUse": 12,
"maxPagesPerScan": 300,
"maxSeats": 20,
"requestsPerMinute": 120
},
"features": {
"reportDomain": true,
"api": true,
"jira": true,
"prioritySupport": false
},
"apiKey": { "id": "cmfg1c2mn0002v7k4r5t7w8yu" }
}GET/sites
Every monitored site of your agency, oldest first, with its client and the most recent finished scan (latestScan is null until a scan has completed).
Request
curl -H "Authorization: Bearer $RAMPSIGHT_API_KEY" \
https://rampsight.com/api/v1/sitesResponse · 200 OK
{
"sites": [
{
"id": "cmfg2p1x60001v7k4d3e9q2ra",
"url": "https://example.com",
"scanFrequency": "weekly",
"createdAt": "2026-08-20T09:14:51.208Z",
"client": { "id": "cmfg2n0kd0000v7k4z6y1u3po", "name": "Example GmbH" },
"latestScan": {
"id": "cmfg3q9zt0003v7k4h2m8p1sc",
"siteId": "cmfg2p1x60001v7k4d3e9q2ra",
"status": "done",
"score": 82,
"grade": "B",
"pagesScanned": 37,
"kind": "full",
"pagesDone": 37,
"pagesDiscovered": 37,
"stopReason": null,
"queuedAt": "2026-09-01T06:00:02.114Z",
"startedAt": "2026-09-01T06:00:04.590Z",
"finishedAt": "2026-09-01T06:01:12.033Z",
"error": null,
"reportUrl": "https://rampsight.com/report/cmfg3q9zt0003v7k4h2m8p1sc?token=3f1c…"
}
}
]
}GET/sites/{id}
One site with its last 12 scans of any status, newest first.
Request
curl -H "Authorization: Bearer $RAMPSIGHT_API_KEY" \
https://rampsight.com/api/v1/sites/cmfg2p1x60001v7k4d3e9q2raResponse · 200 OK
{
"site": {
"id": "cmfg2p1x60001v7k4d3e9q2ra",
"url": "https://example.com",
"scanFrequency": "weekly",
"createdAt": "2026-08-20T09:14:51.208Z",
"client": { "id": "cmfg2n0kd0000v7k4z6y1u3po", "name": "Example GmbH" }
},
"scans": [
{
"id": "cmfg3q9zt0003v7k4h2m8p1sc",
"siteId": "cmfg2p1x60001v7k4d3e9q2ra",
"status": "done",
"score": 82,
"grade": "B",
"pagesScanned": 37,
"kind": "full",
"pagesDone": 37,
"pagesDiscovered": 37,
"stopReason": null,
"queuedAt": "2026-09-01T06:00:02.114Z",
"startedAt": "2026-09-01T06:00:04.590Z",
"finishedAt": "2026-09-01T06:01:12.033Z",
"error": null,
"reportUrl": "https://rampsight.com/report/cmfg3q9zt0003v7k4h2m8p1sc?token=3f1c…"
},
{
"id": "cmfg3p2ab0002v7k4c1d5e7fg",
"siteId": "cmfg2p1x60001v7k4d3e9q2ra",
"status": "error",
"score": null,
"grade": null,
"pagesScanned": null,
"kind": "full",
"pagesDone": 41,
"pagesDiscovered": 210,
"stopReason": null,
"queuedAt": "2026-08-25T06:00:01.870Z",
"startedAt": "2026-08-25T06:00:03.120Z",
"finishedAt": "2026-08-25T06:10:03.120Z",
"error": "Scan timed out or the worker was interrupted; run it again.",
"reportUrl": null
}
]
}- 404 when the site does not exist or belongs to another agency — the two cases are not distinguished.
GET/scans/{id}
One scan with every issue it found: the rule, the pages it failed on, the affected element count, and located samples with the engine’s fix advice. Most severe first.
Request
curl -H "Authorization: Bearer $RAMPSIGHT_API_KEY" \
https://rampsight.com/api/v1/scans/cmfg3q9zt0003v7k4h2m8p1scResponse · 200 OK
{
"scan": {
"id": "cmfg3q9zt0003v7k4h2m8p1sc",
"siteId": "cmfg2p1x60001v7k4d3e9q2ra",
"status": "done",
"score": 82,
"grade": "B",
"pagesScanned": 37,
"kind": "full",
"pagesDone": 37,
"pagesDiscovered": 37,
"stopReason": null,
"queuedAt": "2026-09-01T06:00:02.114Z",
"startedAt": "2026-09-01T06:00:04.590Z",
"finishedAt": "2026-09-01T06:01:12.033Z",
"error": null,
"reportUrl": "https://rampsight.com/report/cmfg3q9zt0003v7k4h2m8p1sc?token=3f1c…"
},
"issues": [
{
"id": "cmfg3r1ce0004v7k4j3k6l9mn",
"ruleId": "image-alt",
"impact": "critical",
"wcagTags": ["wcag2a", "wcag111"],
"description": "Ensure <img> elements have alternative text or a role of none or presentation",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/image-alt",
"pages": 9,
"nodes": 23,
"pageUrls": ["https://example.com/", "https://example.com/products"],
"samples": [
{
"pageUrl": "https://example.com/",
"selector": "main > .hero > img",
"snippet": "<img src=\"/hero.jpg\">",
"fixSummary": "Fix any of the following:\n Element does not have an alt attribute"
}
]
}
]
}- issues is empty until status is "done". impact is one of critical, serious, moderate, minor; wcagTags are axe-core tags (wcag2a, wcag21aa, …).
- pages and nodes are exact counts. pageUrls is capped at 50 entries and samples at 10 per rule — they are evidence to locate the pattern, not a full inventory.
- selector, snippet and fixSummary were captured from the scanned page: treat them as untrusted text and never render them as HTML.
POST/sites/{id}/scans
Queues a new scan of the site. The scan runs asynchronously; poll GET /scans/{id} until status is done or error.
Request
curl -X POST -H "Authorization: Bearer $RAMPSIGHT_API_KEY" \
https://rampsight.com/api/v1/sites/cmfg2p1x60001v7k4d3e9q2ra/scansResponse · 202 Accepted
{
"scan": {
"id": "cmfg4a0de0005v7k4n2o4p6qr",
"siteId": "cmfg2p1x60001v7k4d3e9q2ra",
"status": "queued",
"score": null,
"grade": null,
"pagesScanned": null,
"kind": "full",
"pagesDone": 0,
"pagesDiscovered": 0,
"stopReason": null,
"queuedAt": "2026-09-03T10:12:40.501Z",
"startedAt": null,
"finishedAt": null,
"error": null,
"reportUrl": null
}
}- 409 while a scan of the same site is already queued or running — the body carries the id of the one in flight: { "error": "…", "scan": { "id": "…", "status": "running" } }.
- A scan covers up to your plan’s page budget — 100 pages on Starter, 300 on Agency, 1000 on Scale — crawled from the site’s home page within the same origin. GET /me returns the number as limits.maxPagesPerScan.
- The first scan of a site is preceded by a quick first pass of 50 pages (kind "quick"), so a score exists within minutes; the full scan (kind "full", the one this call returns) follows right after. While running, pagesDone counts the pages crawled so far and pagesDiscovered the pages found so far.
- A scan also stops after 60 minutes (10 for the quick pass). stopReason tells you whether the result covers every reachable page (null) or is a sample ("page_limit" or "time_limit").
Trigger a scan after a deploy
The pattern most agencies want: queue a scan when a client site ships, then poll until it finishes and read the score.
# 1. Queue (409 means one is already running — reuse its id from the body)
SCAN_ID=$(curl -fsS -X POST \
-H "Authorization: Bearer $RAMPSIGHT_API_KEY" \
https://rampsight.com/api/v1/sites/$SITE_ID/scans | jq -r '.scan.id')
# 2. Poll every 30 s until done or error
until curl -fsS -H "Authorization: Bearer $RAMPSIGHT_API_KEY" \
https://rampsight.com/api/v1/scans/$SCAN_ID \
| jq -e '.scan.status | IN("done","error")' > /dev/null; do
sleep 30
doneAutomated testing finds many real WCAG failures fast, but it cannot detect every barrier — treat the score as a monitoring signal, not a certification.