Error Codes.
When an API request fails, the response includes an HTTP status code, an
error code string, and a human-readable
error message. Here is the full reference.
Error response format
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"code": "INVALID_URL",
"error": "The URL is malformed or uses an unsupported protocol."
} All error codes
| HTTP Status | Code | Description | How to fix |
|---|---|---|---|
400 | INVALID_URL | The URL is malformed, uses an unsupported protocol, or is missing the hostname. | Ensure the URL starts with https:// or http:// and has a valid domain (e.g., https://example.com). |
400 | INVALID_TYPE | The scan type is not recognized. | Use one of: security, performance, accessibility, seo. |
400 | URL_NOT_REACHABLE | The target URL did not respond or DNS resolution failed. | Verify the URL is accessible from the public internet. Check for DNS issues, firewalls, or downtime. |
400 | INVALID_PARAMS | One or more query parameters are invalid. | Check parameter types and ranges (e.g., limit must be 1-100, status must be a valid value). |
401 | UNAUTHORIZED | The request is missing an API key or the key is invalid. | Include a valid API key in the Authorization header: Authorization: Bearer avk_live_... |
401 | KEY_REVOKED | The API key has been revoked. | Create a new API key in the dashboard and update your configuration. |
403 | DOMAIN_BLOCKED | The target domain is on the blocklist (localhost, internal IPs, reserved domains). | AppVet only scans publicly accessible websites. Use a public URL instead. |
404 | SCAN_NOT_FOUND | No scan exists with this ID, or it belongs to a different organization. | Verify the scan ID. You can only access scans created with your API key or within your organization. |
409 | SCAN_NOT_COMPLETE | The report was requested but the scan is still running. | Poll GET /v1/scan/:id until status is 'completed' or 'partial' before requesting the report. |
429 | RATE_LIMITED | Too many API requests in the current time window. | Wait until the X-RateLimit-Reset timestamp and retry. Consider reducing request frequency. |
429 | QUOTA_EXCEEDED | Monthly scan quota has been exhausted. | Upgrade your plan for more scans, or wait for the next billing period. Check usage with GET /v1/usage. |
429 | CONCURRENT_LIMIT | Maximum number of concurrent scans reached for your tier. | Wait for an active scan to complete before starting a new one, or upgrade your plan. |
500 | INTERNAL_ERROR | An unexpected server error occurred. | Retry after a short delay. If the error persists, contact support@appvet.dev. |
503 | SERVICE_UNAVAILABLE | The service is temporarily unavailable due to maintenance or high load. | Retry after a few minutes. Check https://status.appvet.dev for service status. |
Handling errors in code
Always check the HTTP status code first, then parse the JSON body for
the code and error fields:
const resp = await fetch("https://appvet.dev/v1/scan", {
method: "POST",
headers: {
Authorization: "Bearer avk_live_your_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({ url: "https://example.com", type: "security" }),
});
if (!resp.ok) {
const err = await resp.json();
console.error(`Error ${resp.status}: [${err.code}] ${err.error}`);
if (resp.status === 429) {
const resetAt = resp.headers.get("X-RateLimit-Reset");
console.log(`Retry after: ${new Date(Number(resetAt) * 1000)}`);
}
return;
}
const scan = await resp.json(); Rate limit errors
When you receive a 429 response, the response headers
indicate when you can retry:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1711800060
Use exponential backoff for retries. The
X-RateLimit-Reset value is a Unix timestamp indicating when
the rate limit window resets.