Errors
The shape of a Scan API error response, and the error codes it carries, with the HTTP status of each and when it is returned.
The error shape
Every failure has the same shape: an error object with a stable code, a human message, and sometimes extra context. Branch on the code, never on the message.
{
"error": {
"code": "plan_required",
"message": "The Scan API and the AccessWiser MCP Server are included on the Basic, Pro and Business plans. Your plan still includes scanning in the dashboard. Upgrade under Billing to use them."
}
}Error codes
| Code | HTTP | When |
|---|---|---|
| unauthorized | 401 | No key, a malformed key, a revoked or expired key — or your public aw_ widget key, which is refused before any lookup. The reason is echoed in error.reason. |
| invalid_request | 400 | Missing or invalid url, an unrecognised scanClass, a non-deliverable webhookUrl, a malformed Idempotency-Key, or a body that is not valid JSON. |
| payload_too_large | 413 | The request body is over 4 KB. |
| site_not_added | 403 | The target host is not one of the sites added to this account. Add the site in the dashboard and install the widget, then scan it. |
| plan_required | 403 | Your plan does not include the Scan API. It is included on Basic, Pro and Business; on Free and Starter you scan from the dashboard. |
| no_allowance | 429 | This month's allowance for that scan class is used up and you hold no credits of that class. The body carries scansUsed, scanLimit, credits and resetsAt. |
| rate_limited | 429 | A per-IP, per-key or per-account rate limit was hit. Back off using the Retry-After header. |
| concurrency_limit | 429 / 503 | 429 when your account already has the maximum scans in flight; 503 when the scanner as a whole is at capacity. Both carry Retry-After. |
| idempotency_key_in_flight | 409 | Another request with the same Idempotency-Key is still being processed. Retry after a moment. |
| not_found | 404 | No scan with that id on your account. A scan belonging to another account returns 404, never 403. |
| method_not_allowed | 405 | Wrong verb, including any browser preflight — this is a server-to-server API and grants no cross-origin access. |
| internal_error | 500 | Something broke on our side. |