API Documentation
Programmatic access to the Owner Leads Direct database. Search by industry, state, revenue band, or city. Retrieve full records. Push new matches into your stack via webhooks.
https://api.ownerleadsdirect.com/v1Authentication
All requests require a Bearer token in the Authorization header. API keys are issued from the Enterprise tier dashboard and may be rotated at any time.
curl -H "Authorization: Bearer sk_live_abc123..." \ https://api.ownerleadsdirect.com/v1/records/search
Endpoints
/v1/records/searchSearch records matching filters.
{
"industry": "construction",
"state": "TX",
"revenue_band_min": 1000000,
"revenue_band_max": 5000000,
"city": "Dallas",
"limit": 100,
"cursor": "eyJpZCI6ImFiYzEyMyJ9"
}{
"records": [
{
"id": "rec_01HZK...",
"owner_first_name": "John",
"owner_last_name": "[redacted in docs]",
"owner_mobile": "+1555...",
"owner_email": "[redacted]",
"business_name": "[redacted]",
"business_city": "Dallas",
"business_state": "TX",
"industry": "construction",
"revenue_band": "1M-5M",
"years_in_business": 8
}
],
"next_cursor": "eyJpZCI6ImRlZjQ1NiJ9",
"total_matched": 14237
}/v1/records/countGet record count for a filter — does not consume records.
?industry=construction&state=TX&revenue_band_min=1000000
{
"count": 14237,
"filters_applied": {
"industry": "construction",
"state": "TX",
"revenue_band_min": 1000000
}
}/v1/records/{id}Retrieve a single record by ID. Counts against your monthly quota.
{
"id": "rec_01HZK...",
"owner_first_name": "John",
"owner_last_name": "Doe",
"owner_mobile": "+15555551234",
"owner_email": "john@example.com",
"business_name": "Doe Construction LLC",
"business_street": "123 Main St",
"business_city": "Dallas",
"business_state": "TX",
"business_zip": "75201",
"industry": "construction",
"revenue_band": "1M-5M",
"years_in_business": 8,
"funding_history": "Prior MCA 2024-Q3",
"lead_source": "Owner Leads Direct",
"first_seen": "2025-08-12T00:00:00Z",
"last_verified": "2026-04-22T00:00:00Z"
}/v1/records/recentRetrieve records added or refreshed since a given timestamp.
?since=2026-04-01T00:00:00Z&industry=construction&limit=500
{ "records": [ ... ], "next_cursor": "...", "as_of": "2026-05-05T..." }/v1/webhooksRegister a webhook to receive new records matching a saved filter.
{
"url": "https://your-app.com/hooks/owner-leads",
"filter": { "industry": "construction", "state": "TX" },
"events": ["record.created", "record.refreshed"],
"secret": "whsec_..."
}{ "webhook_id": "wh_01HZK...", "status": "active" }/v1/account/usageCurrent billing-period usage and quota.
{
"plan": "enterprise",
"period_start": "2026-05-01",
"period_end": "2026-05-31",
"records_used": 4128,
"records_quota": "unlimited",
"api_calls_today": 982
}Webhooks — Payload Format
When a new record matches your registered filter, we POST to your endpoint:
POST https://your-app.com/hooks/owner-leads
Content-Type: application/json
X-OLD-Signature: sha256=abc123...
X-OLD-Event: record.created
{
"event": "record.created",
"delivered_at": "2026-05-05T18:32:11Z",
"data": { /* full record object */ }
}Verify the X-OLD-Signature header by computing HMAC-SHA256 of the request body using your webhook secret. Reject any request whose signature does not match.
Webhook deliveries retry with exponential backoff (1m, 5m, 30m, 2h, 12h, 24h) on non-2xx responses for up to 24 hours.
Code Samples
Node.js / TypeScript
const res = await fetch("https://api.ownerleadsdirect.com/v1/records/search", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.OLD_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
industry: "construction",
state: "TX",
revenue_band_min: 1_000_000,
limit: 100,
}),
});
const data = await res.json();
console.log(`Found ${data.total_matched} matches`);Python
import os, requests
res = requests.post(
"https://api.ownerleadsdirect.com/v1/records/search",
headers={"Authorization": f"Bearer {os.environ['OLD_API_KEY']}"},
json={"industry": "construction", "state": "TX", "limit": 100},
)
data = res.json()
print(f"Found {data['total_matched']} matches")Rate Limits
- Default: 60 requests / minute, 5,000 requests / hour per API key.
- Bulk endpoints (
/records/recent,/records/searchwith limit > 100): 10 requests / minute. - Burst capacity: Up to 2× default for short bursts; higher rates available on request.
Rate limit responses return HTTP 429 with Retry-After header indicating wait time in seconds. Current limits are exposed via X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers on every response.
Status Codes
- 200 OK — Request succeeded.
- 400 Bad Request — Invalid filter or body.
- 401 Unauthorized — Missing or invalid API key.
- 403 Forbidden — API key lacks permission for this endpoint or your tier doesn't include API access.
- 404 Not Found — Record ID does not exist.
- 422 Unprocessable — Filter combination produced no possible matches (invalid state code, etc.).
- 429 Too Many Requests — Rate limit exceeded.
- 5xx Server Error — Retry with exponential backoff.
Quota & Billing
API record retrievals (/records/{id} and full records returned by /records/search or /records/recent) count against your monthly quota. Search count queries (/records/count) are free. Usage resets at the start of each billing cycle.
Enterprise tier offers unlimited or volume-based pricing — request a quote by email.
Versioning & Changelog
The current API version is v1. Breaking changes will be released under a new version (v2) with a minimum 12-month deprecation window for the prior version. Non-breaking additions (new optional fields, new endpoints) are added to v1 without notice.
Need API access?
API access is available on the Enterprise tier. Submit an email request for an API key, custom rate limits, and integration support.
Request API Access →