Error Format
Errors return JSON with adetail field:
401 text says which of three things is wrong: no key was sent, the key does not start with vq_key_, or the key is unknown, revoked or expired.
Validation errors (422) keep detail as a short string and put the field-level details in errors:
detail for the message and errors[].loc to find the field.
Some validation errors carry extra keys on each entry, such as ctx for a failed rule.
A 422 from a rule that spans several fields (chapter without titleNumber, a malformed Boolean expression) is a plain detail string with no errors array, as is every other error status.
Status Codes
On
403, webhook delivery on a watch requires the Business plan: use channel: "email" or upgrade.
On 429, the watch cap is 3 outside Business and 100 on Business.
400 versus 422
A422 is schema validation: a field is missing, or its type or range is wrong.
The API rejects it before your request reaches any business logic, and the response carries the loc array shown above.
A 400 is a request that is well-formed but not allowed.
GET and POST /us/statutes/resolve return it for a corpusType or state scope they do not accept, and refund the charge.
POST /watches and PATCH /watches/{id} return it for:
- a
scopethe board cannot be narrowed by, or anactIdscope that does not exist on that board, - a source that is not scopable at all, meaning a board whose
scopableisfalsesuch as the Federal Register, - a missing
webhookUrloremailAddressfor thechannelyou asked for, or one set on a channel that does not use it, - a
webhookUrlthe API refuses as a delivery target, - a
webhookAuth.headerNamethat is not a legal header name, or outbound auth set on an email-only watch.
detail string names the specific problem, so read it rather than retrying.
409 on watches
POST /watches returns 409 when you already hold a watch on the same board, the same channel, and the same scope.
Watches are unique on that triple, so a 409 means the subscription already exists. Nothing has failed.
PATCH /watches/{id} returns it for the same reason, when narrowing a watch’s scope would collide with another watch you already hold.
List your watches with GET /watches and reuse the existing one.
Rate Limiting
Limits are enforced per API key and scale with your plan. Every response carriesX-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (a Unix timestamp) for the per-minute window, and X-RateLimit-Limit-Day and X-RateLimit-Remaining-Day for the daily one.
When you exceed one the API returns 429 with a Retry-After header telling you how many seconds to wait. Respect it, and add exponential backoff so retries spread out under sustained pressure.
Troubleshooting
401 but my key is correct
401 but my key is correct
Include the
Bearer prefix: Authorization: Bearer vq_key_.... The key alone is rejected.422 validation error
422 validation error
Set
Content-Type: application/json. Check the loc field in the response to find the problematic field.Related
Authentication
Create and manage your API key.
Best practices
Scope queries, cache coverage, and retry well.
SDKs
The official Python and TypeScript SDKs map these errors to typed exceptions and retry the safe ones for you.

