Errors and rate limits

The SEOFix API error envelope, every error code with its HTTP status, the rate limits per key and endpoint, insufficient credits, and when to retry.

Updated 8 October 2026View as Markdown

Every SEOFix API error has the same shape: {"error": {"code": "...", "message": "..."}} with a matching HTTP status. Branch on code, not on message. Each API key may make 60 requests per minute; some endpoints have an extra, lower limit. Retry only 429, 503 and report_not_ready, and honour Retry-After.

The error envelope

{
  "error": {
    "code": "site_not_verified",
    "message": "Rechecks need a verified site. Verify ownership first: see GET /v1/sites/{id}/verification."
  }
}
  • code is stable and machine-readable. message is for people and can change.
  • Validation errors add fields, the failing parameters with their messages:
{
  "error": {
    "code": "validation_failed",
    "message": "The max rps field must not be greater than 10.",
    "fields": {"max_rps": ["The max rps field must not be greater than 10."]}
  }
}
  • budget_exhausted adds resets_at (ISO 8601).
  • Unexpected server errors answer 500 internal_error and never include internal details.

Over MCP, a failed tool returns the same code as text: code: message, with isError: true.

Error codes

Any endpoint

Status Code Meaning What to do
401 unauthenticated No key, a wrong key, or a revoked or rotated key Send Authorization: Bearer sk_... with a current key
403 team_access_revoked The key holder is no longer a member of the key's team Issue a new key for a team you belong to
404 not_found Unknown id, unknown path, or a resource of another team Check the id and the key's team
422 validation_failed A parameter is missing or out of range; see fields Fix the request
429 rate_limited A rate limit was hit Wait for Retry-After seconds
500 internal_error Unexpected server error Retry later with backoff; email [email protected] if it persists

Credits and plans

Status Code Meaning
402 insufficient_credits The balance is below what the request reserves (the page cap of an audit, or 1 per URL of a recheck)
403 plan_limit_max_pages max_pages is above the plan's per-audit page limit (a quarter of the monthly page tier: at least 10,000 on Starter and 250,000 on Growth, at most 500,000). The message states your limit.
403 plan_limit_sites The plan's site limit is reached
403 plan_limit_monitoring The plan does not include scheduled monitoring

Audits

Status Code Meaning
422 invalid_url The URL is not a public http(s) address
422 max_rps_requires_verified_site max_rps above 3 without a verified site for that origin
422 site_url_mismatch With site_id, the url is not on the site's origin
409 site_not_verified More than 500 pages, rechecks, monitoring, Google data or IndexNow need a verified site
404 report_not_ready The report, diff, templates or fix prompt does not exist yet
410 crawl_archived Issue and page detail of this audit were archived; report, diff and fix prompt remain
409 conflict Cancel on an audit that already ended
503 dispatch_failed The audit could not be queued; its reserved credits are refunded automatically

Sites

Status Code Meaning
409 site_exists The team already has a site for that host
422 verification_failed No ownership proof matched; the message lists what to publish

Fix tasks and rechecks

Status Code Meaning
404 not_found No fix task with this key in the site's latest audit
422 cannot_verify The task's check cannot be judged by a recheck (site-wide, link-graph, sitemap or Google-indexing checks); nothing was started. Run a full audit instead.
422 invalid_urls A URL is not on the site's host, or there are not 1-200 URLs
429 recheck_rate_limited More than 30 rechecks this hour for the team; see Retry-After

Google Search Console

Status Code Meaning
409 gsc_not_connected No active Search Console connection for the site
409 gsc_forbidden The connected Google account lost access to the property
422 url_not_in_site A URL is not part of the site's Search Console property
422 gsc_request_rejected Search Console rejected the request
429 budget_exhausted Today's URL Inspection budget for the property is used up; see resets_at
503 google_unavailable Search Console is temporarily unavailable

IndexNow

Status Code Meaning
409 indexnow_key_unverified The key file has not been verified yet; serve it, then check it
422 url_not_in_site None of the URLs is on the site's host
422 invalid_indexnow_key The key is not 8-128 characters of A-Z a-z 0-9 -
422 invalid_indexnow_key_location key_location is not an https .txt URL on the site's host
429 indexnow_cap The site's 10,000 IndexNow URLs for today (UTC) are used up
502 indexnow_rejected IndexNow accepted none of the URLs, or could not be reached

Billing

Status Code Meaning
403 not_team_owner Only the team owner can buy credits or plans
409 subscription_exists The account already has a subscription; change it in Settings → Plan & billing
409 no_billing_account Nothing bought yet, so there is no billing portal to open
422 price_not_configured That plan, volume and interval is not offered
503 billing_not_configured Billing is not available on this server

Device login (npx seofix connect)

Status Code Meaning
428 authorization_pending Not approved yet; keep polling
429 slow_down Polled faster than every 5 seconds
403 access_denied The request was denied
400 expired_token The code expired (after 10 minutes)
400 invalid_grant Unknown or already used device code

MCP-only codes

The MCP server adds three codes of its own:

Code Meaning
unauthenticated (No API key provided.) The MCP request had no Authorization header; nothing was sent to the API
network_error The MCP server could not reach the API
http_<status> The API answered an error without the usual envelope

Rate limits

Scope Limit Keyed by
Every authenticated /v1 endpoint, combined 60 requests per minute API key
POST /v1/sites/{id}/verify 10 per minute API key
POST /v1/sites/{id}/google/inspect 10 per minute API key
POST /v1/sites/{id}/indexnow 10 per minute API key
POST /v1/sites/{id}/indexnow/check-key 10 per minute API key
PUT /v1/sites/{id}/indexnow/key 10 per minute API key
POST /v1/sites/{id}/recheck 30 rechecks per hour team
IndexNow submissions 10,000 URLs per day (UTC) site
Google URL Inspection the property's daily budget, shared with the daily sync Search Console property
POST /v1/device/start 10 per hour IP address
POST /v1/device/token 60 per minute, and one poll per 5 seconds per device code IP address
GET /v1/health none

The per-endpoint limits apply in addition to the 60 per minute. All keys of one user count separately; the recheck limit is shared by everyone in the team.

Responses carry X-RateLimit-Limit and X-RateLimit-Remaining. A 429 rate_limited answer also carries Retry-After (seconds). recheck_rate_limited and budget_exhausted carry Retry-After too.

Insufficient credits

Audits and rechecks reserve credits before they start:

  • An audit reserves its full page cap (max_pages). The unused part is refunded when it ends.
  • A recheck reserves 1 credit per URL.

If the balance that pays for it is lower, the API answers 402 insufficient_credits and creates nothing: no audit, no reservation. A recheck refused this way does not count against the hourly recheck limit.

Which balance pays: a plain-URL audit (POST /v1/crawls with url) uses the key holder's own balance; audits of a registered site, scheduled audits and rechecks use the team owner's balance. GET /v1/account shows both (balance and team_credits).

To proceed: lower max_pages to fit the balance, or add credits (Settings → Plan & billing in the app, or a checkout link from POST /v1/billing/checkout for the team owner). Do not retry the same request unchanged.

Retry guidance

Answer Retry?
429 rate_limited, recheck_rate_limited Yes, after Retry-After seconds
429 budget_exhausted Yes, after resets_at
429 indexnow_cap Yes, after midnight UTC
404 report_not_ready Yes, every 5-10 seconds while the audit is finalizing or just done
500 internal_error, 502 indexnow_rejected, 503 codes Yes, with exponential backoff (for example 5 s, 15 s, 60 s), a few times
503 dispatch_failed Yes, once after a minute; the failed audit's credits are refunded
428 authorization_pending Yes, every 5 seconds until approved or expired
400, 401, 402, 403, other 404, 409, 410, 422 No: fix the request, the key, the plan or the site first

Never retry POST /v1/crawls or POST /v1/sites/{id}/recheck after a timeout without checking first: the audit or recheck may have started. List audits with GET /v1/crawls?site_id= before starting another. Over MCP, verify_fix never starts a second recheck on its own; continue with get_recheck.

More in REST API

Still stuck? Email [email protected] with your site and what you expected to see.