Errors, rate limits & versioning¶
How the API signals failure, enforces quotas, and evolves over time.
Error model¶
Errors return a standard HTTP status and a JSON body:
Include the request_id when contacting support — it lets
us trace the exact call.
Status codes¶
| Status | Meaning | Typical cause | What to do |
|---|---|---|---|
400 |
Bad request | Malformed body, invalid target | Fix the payload |
401 |
Unauthenticated | Missing/expired/revoked token | Re-authenticate |
403 |
Forbidden | Plan gate, missing role, or unverified domain | Upgrade plan, use admin, or complete domain verification |
404 |
Not found | Wrong ID or another org's resource | Check the ID / org scope |
409 |
Conflict | Duplicate or concurrent modification | Retry after reconciling |
422 |
Validation error | Field-level schema failure | Read detail for the field |
429 |
Too many requests | Rate limit or daily scan quota exceeded | Back off; see headers below |
5xx |
Server error | Unexpected failure | Retry with backoff; report request_id |
Tenant isolation
A resource that belongs to another organization returns 404, not 403 —
Vex Raptor does not confirm the existence of resources outside your org.
Rate limits¶
- Login is rate-limited per IP/user to slow credential stuffing.
- Scans are bounded by a per-org daily quota (by plan), enforced
atomically. Exceeding it returns
429. - Per-target scan traffic is separately rate-capped to keep tests non-disruptive (configurable).
When throttled you receive 429 with headers:
Honor Retry-After; use exponential backoff for 5xx.
Idempotency¶
GET is safe and idempotent. For scan-creating calls, pass a client-generated
Idempotency-Key header to make retries safe — a repeated key returns the
original result instead of starting a second scan.
curl -sS -X POST https://<host>/api/v1/webhook/scan \
-H "X-Vex-Key: <org-api-key>" \
-H "Idempotency-Key: 3f2a...-deploy-4711" \
-H "Content-Type: application/json" \
-d '{"target":"https://staging.example.com","fail_on":"high"}'
Versioning & deprecation¶
- The API is versioned in the path:
/api/v1. - Additive changes (new fields, new endpoints) ship within
v1and are backward-compatible — parse defensively and ignore unknown fields. - Breaking changes ship under a new version (
/api/v2); the previous version is supported for a documented deprecation window announced in the release notes. - The OpenAPI spec at
/api/openapi.jsonis the source of truth for the current contract.