API reference

Errors, decoded

Every failure uses { error: { code, message }, requestId? }. 25 stable codes, each with its HTTP mapping, trigger and fix.

Updated 2026-11-08

One envelope, stable codes

Success is always 200 (201 on create) with { code, message, data } + X-Request-Id — see the example below. Every failure below uses { error: { code, message }, requestId? }.

  • Missing, revoked, or expired key — and insufficient scope (never distinguished); A2A/MCP answer JSON-RPC -32002

    401 AUTH_UNAUTHORIZED

    Send a valid Bearer key that includes the endpoint's scope.

  • Request body, query, or path fails schema validation

    400 VALIDATION_FAILED

    Fix the body, query or path to match the schema; details name the field.

  • Audit on an unverified owned site

    403 SITE_NOT_VERIFIED

    Verify ownership, then retry the audit.

  • Capability not covered by the current plan

    403 FEATURE_DISABLED

    Upgrade the plan or use an endpoint the current plan covers.

  • Resource does not exist or is not owned by the caller

    404 NOT_FOUND

    Check the id and that the resource belongs to your account.

  • Duplicate or conflicting state (e.g. a 6th key, duplicate site)

    409 CONFLICT

    Revoke an unused key or use a different domain or id.

  • Audit on an unassigned site or over site quota

    429 + Retry-After SITE_QUOTA_EXCEEDED

    Wait for Retry-After, or add site slots on the billing page.

  • Assigning paid audit slots without an active subscription (free, canceled, or past grace)

    403 SUBSCRIPTION_REQUIRED

    Start a paid subscription before assigning paid slots.

  • Assigning paid audit slots while the subscription period is still unreconciled — retry after the reconcile job backfills it

    403 BILLING_RECONCILING

    Retry after the reconcile job backfills the billing period.

  • Last payment failed — update the payment method before adding sites

    409 BILLING_PAST_DUE

    Update the payment method in the billing portal.

  • Subscription paused — resume it in the billing portal before adding sites

    409 BILLING_PAUSED

    Resume the subscription in the billing portal.

  • Subscription is no longer changeable (canceled) — resubscribe or contact support

    409 BILLING_SUBSCRIPTION_NOT_LIVE

    Resubscribe, or contact support if the state is unexpected.

  • Paddle declined the prorated charge for the extra sites

    409 BILLING_PAYMENT_DECLINED

    Use another payment method, then retry the site change.

  • Subscription has multiple billing items — site count cannot be changed automatically

    409 BILLING_UNSUPPORTED_ITEMS

    Contact support to change the site count for this subscription.

  • Subscription is already scheduled to cancel — changes are blocked

    409 BILLING_CANCEL_SCHEDULED

    Undo the scheduled cancellation in the Paddle portal, then change the subscription.

  • The admin action needs a permission the caller does not have

    403 FORBIDDEN

    Use an account with the required admin role, or ask an owner to perform the action.

  • A high-value refund or research-credit change needs a second admin approval

    403 APPROVAL_REQUIRED

    Submit an approval request and have an owner approve it before the action runs.

  • Over audited-URL quota for the site

    429 + Retry-After AUDIT_URLS_QUOTA_EXCEEDED

    Trim the URL list, or wait for the quota window to reset.

  • Over the share quota (10 interactive links / 50 snapshots)

    400 SHARE_LINK_QUOTA_EXCEEDED

    Revoke an old link before creating another.

  • Audits triggered too frequently

    429 + Retry-After AUDIT_FREQUENCY_QUOTA_EXCEEDED

    Wait for Retry-After before the next audit.

  • Over the key's monthly read quota (720h rolling, REST and A2A/MCP)

    429 + Retry-After API_QUOTA_EXCEEDED

    Wait for the 720h rolling window, or raise the key's quota.

  • Over 100 req/min per IP

    429 + Retry-After RATE_LIMITED

    Back off per Retry-After; the cap is 100 req/min per IP.

  • Request body too large

    413 REQUEST_TOO_LARGE

    Reduce the payload; split large URL lists.

  • Upstream fetch or gateway failed (5xx never counts toward usage)

    502 / 503 / 504 EXTERNAL_SERVICE_FAILED

    Retry; 5xx responses never count toward usage.

  • Unexpected server-side error — report with X-Request-Id

    500 INTERNAL_ERROR

    Report the X-Request-Id to support.

Keys are stored as SHA-256 hashes; the plaintext is shown exactly once at issuance.

JSON
201 · success — always this shape
{
  "code": "OK",
  "message": "Success",
  "data": {
    "site": { "id": "9f2k…", "domain": "example.com",
Show all · 5 more lines
      "verifyStatus": "unverified", "verifiedAt": null },
    "verification": { "method": "file",
      "fileUrl": "https://example.com/.well-known/seo-watch.txt" }
  }
}
JSON
403 · failure — always this shape
{
  "error": { "code": "SITE_NOT_VERIFIED",
    "message": "Verify ownership before triggering audits." },
  "requestId": "req_8f31abcd"
}