Home › API Documentation
▸ Preview Spec · Enterprise Tier · Early Access

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.

Heads up: The endpoints below describe the v1 API spec shipping to Enterprise customers. Endpoints, authentication, and quotas are finalized at contract signing. CSV import is available on every tier today — REST API access requires an Enterprise agreement. Submit an email request for early access.
Base URL: https://api.ownerleadsdirect.com/v1

Authentication

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
Security: Never expose API keys in client-side code or public repositories. Keys are scoped per environment (test vs. live) and per IP allowlist (Enterprise admin can restrict).

Endpoints

POST/v1/records/search

Search records matching filters.

// Request
{
  "industry": "construction",
  "state": "TX",
  "revenue_band_min": 1000000,
  "revenue_band_max": 5000000,
  "city": "Dallas",
  "limit": 100,
  "cursor": "eyJpZCI6ImFiYzEyMyJ9"
}
// Response
{
  "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
}
GET/v1/records/count

Get record count for a filter — does not consume records.

// Request
?industry=construction&state=TX&revenue_band_min=1000000
// Response
{
  "count": 14237,
  "filters_applied": {
    "industry": "construction",
    "state": "TX",
    "revenue_band_min": 1000000
  }
}
GET/v1/records/{id}

Retrieve a single record by ID. Counts against your monthly quota.

// Response
{
  "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"
}
GET/v1/records/recent

Retrieve records added or refreshed since a given timestamp.

// Request
?since=2026-04-01T00:00:00Z&industry=construction&limit=500
// Response
{ "records": [ ... ], "next_cursor": "...", "as_of": "2026-05-05T..." }
POST/v1/webhooks

Register a webhook to receive new records matching a saved filter.

// Request
{
  "url": "https://your-app.com/hooks/owner-leads",
  "filter": { "industry": "construction", "state": "TX" },
  "events": ["record.created", "record.refreshed"],
  "secret": "whsec_..."
}
// Response
{ "webhook_id": "wh_01HZK...", "status": "active" }
GET/v1/account/usage

Current billing-period usage and quota.

// Response
{
  "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/search with 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 →