Skip to content

Test your website now

Free, no card. We read only public pages.

Run free audit →

Developers

API reference

7 endpoints today, covering scans, findings, pages and projects - not the whole dashboard. Available on Pro and above; keys are scoped per workspace, and what is not served yet is listed below. Every key expires: you choose 1 to 365 days (90 by default), and a workspace holds at most 3 active keys on Pro, 5 on Super and 10 on Agency.

We e-mail the workspace owners, and whoever created the key, 7 days before a key expires. A plan change never revokes a key. The active-key cap is checked when a key is created, so after a downgrade the keys you already have keep working until they expire or are revoked, and a new one can be added once you are under the new cap. On a plan without the API, existing keys answer 403 plan_required until the workspace is on a plan with the API again.

Authentication

Send a scoped key as a bearer token. Keys are shown once at creation. Every key can read; starting a scan additionally needs the write scope, so a key you only ever pull results with should be left read-only.

curl https://webauditos.com/api/v1/scans \
  -H "Authorization: Bearer waos_live_••••••••" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","mode":"full","depth":2,"page_budget":50}'

Endpoints

GET/v1/scans

List the workspace's scans, newest first.

POST/v1/scans

Start a scan from a URL. Returns a scan id immediately; the run is asynchronous. Needs a key with the write scope.

POST/v1/scans/batch

Start several scans in one request. Body: { scans: [ { url, mode?, depth?, page_budget? } ] }. Each item reports its own outcome, because a batch that runs out of allowance halfway really did start the first half. How many items you may send is bounded by your plan.

GET/v1/scans/{id}

Run status, progress, category scores and overall score.

GET/v1/scans/{id}/findings

Findings with severity, evidence, fix and affected URLs. Filter with ?severity= and ?category=.

GET/v1/scans/{id}/pages

Crawled URL inventory with status, depth, weight, vitals and per-page score.

GET/v1/projects

List projects with their domain, environment and monitoring state.

Not built yet

These are on the roadmap and are listed here so you do not build against them by mistake. Outbound webhooks are not implemented - poll GET /v1/scans/{id} for now; a completed scan reports status: "complete".

POST /v1/projectsPOST /v1/scans/{id}/reportsGET /v1/checklist

Paging

Every list endpoint is paged. Read next_cursor from the response and send it back as ?cursor= until has_more is false.

  • ?limit= sets the page size. The default is 50 and the maximum is 200; a larger value is served as 200 with has_more set, never truncated in silence.
  • has_more and next_cursor are on every list response, including the last page, where next_cursor is null. You never have to infer whether a list was complete.
  • The cursor is opaque and its format is not part of this API. It names the last row you were given, so rows arriving ahead of it do not shift your paging.
  • ?severity= and ?category= on the findings list filter before paging, so a filtered walk returns every match rather than the matches that happened to fall in one page.

Rate limits and errors

  • Pro 60, Super 90, Agency 120 requests per minute, unmetered on Enterprise. The rate belongs to the workspace and is shared by all of its keys - a second key adds none. Short bursts up to one and a half times the rate are absorbed, and starting a scan costs 10 requests where every read costs one. A batch costs that once per distinct address in it, capped at the bucket size, so a full bucket always accepts a batch your plan allows.
  • Keys per workspace: Pro 3, Super 5, Agency 10, uncapped on Enterprise. Revoked and expired keys do not count.
  • Every response to an accepted key carries x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset and x-ratelimit-scope; a 401, a plan refusal or a terms refusal carries none of these headers. Exceeding the workspace rate answers 429 with Retry-After and consumes no plan quota.
  • More than 30 failed authentications per minute from one address (an IPv6 /64 counts as one address) answer 429 with the code too_many_failed_auth and Retry-After, without checking the key, so a valid key from that address is refused too until the minute ends.
  • Each of those places is taken while a key is being checked and given back only once it proves valid, so more than 30 simultaneous requests from one address can be answered too_many_failed_auth even with a valid key; spread a burst out or retry after Retry-After.
  • A key whose workspace owner has not accepted the terms of service answers 403 with the code terms_not_accepted until the owner signs in to the app and accepts them. Like a plan refusal (403 plan_required), it does not count toward the failed-authentication limit above, unless the same workspace keeps sending refused requests faster than that per-minute limit; past it, those refusals count toward the address limit, so a workspace polling that fast with a refused key from a shared egress IP can cause too_many_failed_auth for other keys behind the same address.
  • Exceeding your plan's monthly scan or project allowance answers 402 with the code quota_exceeded - a status a CI pipeline can act on without parsing prose.
  • Errors return a stable machine code and a human message. Unknown, revoked and expired keys all answer 401 identically, on purpose. A request body larger than 64 KB answers 413 with the code payload_too_large, unread.