Build with the API
The API itself is built in MVP 1, Phase 3 (see the roadmap). This page defines the contract it follows, so integrations can be designed now. Full endpoint definitions, request and response schemas, and interactive examples will be published in the Vora Swagger documentation.
Quickstart
- Step 1Get an API key
Create one in the Vora dashboard. Production keys start with vora_live_.
- Step 2Make a request
Call any endpoint with your key in the Authorization header.
- Step 3Read the JSON
Records come back in a data array, with pagination details alongside.
Your first request
Search enforcement actions for a company:
- curl
- JavaScript
- Python
curl "https://api.withvora.com/v1/enforcement?query=acme+bank&limit=5" \
-H "Authorization: Bearer $VORA_API_KEY"
const response = await fetch('https://api.withvora.com/v1/enforcement?query=acme+bank&limit=5', {
headers: { Authorization: `Bearer ${process.env.VORA_API_KEY}` },
});
const { data, pagination } = await response.json();
import os
import requests
response = requests.get(
"https://api.withvora.com/v1/enforcement",
params={"query": "acme bank", "limit": 5},
headers={"Authorization": f"Bearer {os.environ['VORA_API_KEY']}"},
)
body = response.json()
What you get back
Every list endpoint returns the same envelope:
{
"data": [],
"pagination": {
"total": 843,
"limit": 20,
"offset": 40,
"has_more": true
}
}
All responses use Content-Type: application/json. Request bodies, where applicable, should be sent as JSON with the same header.
Authentication
Vora uses API key authentication. Every request must include a valid key as a Bearer token in the Authorization header:
GET /v1/enforcement
Authorization: Bearer vora_live_xxxxxxxxxxxxxxxxxxxx
Key format
| Prefix | Meaning |
|---|---|
vora_live_ | Production key |
vora_test_ | Sandbox key, once a sandbox environment is introduced |
Managing keys
API keys are created and managed in the Vora dashboard. You can create, rotate, and revoke keys at any time. Rotating a key immediately invalidates the previous one.
- Never expose your API key in client-side code or public repositories.
- Rotate your key immediately if you believe it has been compromised.
- Each key is tied to your account, and all usage is logged against it.
Authentication errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | API key is missing or invalid |
| 403 | forbidden | API key is valid but does not have access to this resource |
Pagination
All list endpoints return paginated results, using offset-based pagination.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit | integer | No | 20 | Number of records to return. Maximum 100. |
offset | integer | No | 0 | Number of records to skip before returning results |
GET /v1/enforcement?limit=20&offset=40
Authorization: Bearer vora_live_xxxxxxxxxxxx
| Field | Type | Description |
|---|---|---|
data | array | The records on this page |
total | integer | Total number of matching records |
limit | integer | The limit applied to this request |
offset | integer | The offset applied to this request |
has_more | boolean | Whether more records exist beyond this page |
Filtering and sorting
These parameters apply across the API. Each endpoint's Swagger definition lists which filters it supports.
| Parameter | Type | Description | Example |
|---|---|---|---|
date_from | ISO 8601 date | Records on or after this date | date_from=2024-01-01 |
date_to | ISO 8601 date | Records on or before this date | date_to=2024-12-31 |
query | string | Search by entity name. Partial matches supported. | query=acme+bank |
| enum filters | string | A single value or a comma-separated list | source=cfpb,occ |
sort_by | string | Field to sort by. Default: action_date | sort_by=action_date |
sort_order | enum | asc or desc. Default: desc | sort_order=asc |
All filters can be combined in one request:
GET /v1/enforcement?query=acme+bank&source=cfpb,occ&date_from=2024-01-01&sort_order=asc
Errors
Every error has the same shape, whatever the endpoint or error type:
{
"error": {
"code": "rate_limit_exceeded",
"message": "You have exceeded your rate limit. Please retry after 1714480800.",
"details": {}
}
}
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code |
message | string | Human-readable description of the error |
details | object | Extra context where applicable, otherwise empty |
| Status | Code | What it means |
|---|---|---|
| 400 | bad_request | Missing or invalid query parameters |
| 401 | unauthorized | API key is missing or invalid |
| 403 | forbidden | API key does not have access to this resource |
| 404 | not_found | The requested record does not exist |
| 429 | rate_limit_exceeded | Rate limit reached for the current window |
| 500 | internal_server_error | Something went wrong on Vora's end |
Rate limiting
Rate limits are enforced per API key, to protect infrastructure stability and keep performance consistent across all integrations.
A single global rate limit applies to all customers until the pricing tiers are finalized after customer validation. See pricing.
| Tier | Per minute | Per day |
|---|---|---|
| Global (today) | TBD | TBD |
| Starter | TBD | TBD |
| Pro | TBD | TBD |
| Enterprise | Custom | Custom |
Every response includes these headers, so your integration can track its usage:
| Header | Description |
|---|---|
X-RateLimit-Limit | Total requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the current window resets |
Going over the limit returns 429 Too Many Requests. Pause until the time in X-RateLimit-Reset, then retry.
Versioning
The API version is part of the base URL, so breaking changes never reach existing integrations without notice.
| Version | Status | Released | Base URL |
|---|---|---|---|
| V1 | Active | 2026 | https://api.withvora.com/v1 |
V1 includes:
- Enforcement action search and lookup:
/v1/enforcement,/v1/enforcement/:id - License record search and lookup:
/v1/licenses,/v1/licenses/:id - Data source listing:
/v1/sources - Health check:
/v1/health - API key authentication
What counts as a breaking change?
Non-breaking changes can be added to any version at any time, without notice:
- New optional query parameters
- New fields in existing response schemas
- New endpoints
- New enum values
Breaking changes always ship as a new version, with a deprecation notice and a migration guide before the previous version is retired:
- Removed or renamed fields
- Changed response shapes
- Modified authentication behavior
- Removed endpoints