Read API

The pull side of the integration: fetch your leads, deals and orders on demand. Webhooks push the same data the moment it changes; this API is for “give me the Hot leads in my Frisco farm” — a developer, a BI tool, or an AI assistant.

Authentication

Create a key under Account → Integrations (Pro or Elite). It is shown once and stored hashed. Send it on every request; keys are read-only, return only your own account’s data, allow 120 requests a minute, and stop working within a minute of being revoked.

curl -H "Authorization: Bearer spl_live_…" https://api.smartpropleads.com/v1/ping
# → {"ok":true,"user_id":"…","plan":"pro","scopes":["read"]}

Base URL https://api.smartpropleads.com. Every response is JSON; list responses carry total, limit and offset. Field names are the same snake_case names the webhook events use, so one parser serves both.

Sources

Leads are read through one of your sources — a saved list, a farm, or a saved search — never county-wide. These three calls list them so you have ids for /v1/leads.

GET /v1/lists     → {"lists":[{"id":"…","name":"Collin probate — Sept","status":"active","leads":212,"updated_at":"…"}]}
GET /v1/farms     → {"farms":[{"id":"…","name":"West Fort Worth","parcels":1840,"alerts_enabled":true,"updated_at":"…"}]}
GET /v1/searches  → {"searches":[{"id":"…","name":"Frisco absentee","label":"Frisco · Absentee · Hot","updated_at":"…"}]}

Leads

GET /v1/leads

ParameterMeaning
list_id | farm_id | search_idExactly one. The source to read through.
tierhot · warm · moderate · cold. Sets the score floor unless min_score is given.
min_score0–100. Default: the moderate floor (40).
lead_typeA lead-type id, e.g. probate, tax-delinquent, absentee-owner.
limit / offsetPage size 1–100 (default 25) and start. Rows are ordered by score, highest first.

The source is resolved to its parcels (up to 5,000 candidates; farms and searches replay live), scored, filtered, and paged. Each row is the lead shape from the events plus contacts — the phones and emails from a skip trace you purchased for that parcel, or null. Lead types above your plan are omitted.

curl -H "Authorization: Bearer spl_live_…" "https://api.smartpropleads.com/v1/leads?list_id=…&tier=hot&limit=50"

{
  "source": { "kind": "list", "id": "…", "name": "Collin probate — Sept", "candidates": 212, "candidate_cap": 5000 },
  "filters": { "tier": "hot", "min_score": null, "lead_type": null },
  "leads": [ {
      "parcel_id": "collin:R-1234-00",
      "county": "collin",
      "account_num": "R-1234-00",
      "address": "1108 Heather Ln, McKinney, TX 75069",
      "city": "McKinney",
      "zip": "75069",
      "score": 88,
      "tier": "hot",
      "lead_types": [
        "probate",
        "long-term-owner",
        "free-clear"
      ],
      "why": "Probate filed 9/11 (Collin Co.) · owned 23 yrs",
      "owner_name": "MARTINEZ ROSA ESTATE OF",
      "mailing_address": "PO Box 2210, Allen, TX 75013",
      "deal_url": "https://smartpropleads.com/leads/property/collin/R-1234-00",
      "crm_note": "SmartPropLeads score 88 · Hot · Lead types: Probate, Long-Term Owners (15+ yrs), Free & Clear · Why: Probate filed 9/11 (Collin Co.) · owned 23 yrs · Owner: MARTINEZ ROSA ESTATE OF · Mailing: PO Box 2210, Allen, TX 75013 · Open: https://smartpropleads.com/leads/property/collin/R-1234-00",
      "contacts": {
        "order_id": "ord_…",
        "phones": [
          "+12145550143",
          "+14695550198"
        ],
        "emails": [
          "rosa.martinez@example.com"
        ],
        "phone_primary": "+12145550143",
        "phone_secondary": "+14695550198",
        "email_primary": "rosa.martinez@example.com",
        "callable_phones": 1,
        "dnc_screened": true,
        "traced_at": "2026-09-23T14:07:05Z"
      }
    } ],
  "total": 37, "limit": 50, "offset": 0
}

GET /v1/leads/:county/:account_num

One lead by parcel (the parcel_id is county:account_num). Same row shape, wrapped in lead.

GET /v1/leads/lookup?address=&city=&zip=

Find a lead by street address — exactly one parcel on that house number and street matches; a multi-unit building returns nothing rather than the wrong unit. Returns { leads: [] | [lead] } without contacts.

Deals

GET /v1/deals

ParameterMeaning
statusNEW · CONTACTED · OFFER_SENT · UNDER_CONTRACT · CLOSED · TERMINATED · DEAD
updated_sinceISO-8601; deals touched at or after this instant.
limit / offsetPage size 1–100 (default 25), newest activity first.
{
  "deals": [{
    "deal_id": "…", "parcel_id": "denton:R123456", "county": "denton", "account_num": "R123456",
    "address": "3305 Long Prairie Rd, Flower Mound, TX 75022", "city": "Flower Mound", "zip": "75022",
    "status": "UNDER_CONTRACT", "sub_state": "option_period", "exit_strategy": "assigned", "dead_reason": null,
    "note": null, "next_action": "Send assignment to title", "next_action_due": "2026-09-26",
    "offer_date": "2026-09-15", "effective_date": "2026-09-22", "option_end_date": "2026-09-29", "closing_date": "2026-10-17",
    "buyer_name": "Trinity Ridge Homes LLC", "buyer_phone": null, "buyer_email": null, "title_company": "Capital Title — Frisco",
    "created_via": "manual", "money": { "contract_price": 31500000, "earnest": 250000, "est_fee": 1500000 },
    "stage_entered_at": "…", "last_activity_at": "…", "created_at": "…", "updated_at": "…",
    "deal_url": "https://smartpropleads.com/pipeline?deal=…"
  }],
  "total": 1, "limit": 25, "offset": 0
}

money is in cents, by field. GET /v1/deals/:deal_id returns one deal as deal.

Orders

GET /v1/orders

ParameterMeaning
serviceSKIP_TRACE · POSTCARD
statusQUEUED · PAID · FULFILLED · CANCELLED
sinceISO-8601; orders placed at or after this instant.
limit / offsetPage size 1–100 (default 25), newest first.
{
  "orders": [{
    "order_id": "…", "batch_id": "…", "list_id": "…", "service": "SKIP_TRACE", "status": "FULFILLED", "price_cents": 50,
    "parcel_id": "collin:R-1234-00", "county": "collin", "account_num": "R-1234-00",
    "address": "1108 Heather Ln, McKinney, TX 75069", "owner_name": "MARTINEZ ROSA ESTATE OF",
    "created_at": "…", "fulfilled_at": "…",
    "contacts": { "phones": ["+12145550143", "+14695550198"], "emails": ["rosa.martinez@example.com"], "phone_primary": "+12145550143", "email_primary": "rosa.martinez@example.com", "callable_phones": 1, "dnc_screened": true, "traced_at": "…" },
    "postcard": null,
    "lead_url": "https://smartpropleads.com/leads/property/collin/R-1234-00"
  }],
  "total": 1, "limit": 25, "offset": 0
}

A postcard order carries postcard instead: { state: draft|production|mailed|delivered_est, lob_status, mailed_at }.

Errors & limits

ParameterMeaning
401 unauthorizedMissing, unknown or revoked key.
403 pro_requiredThe key’s account is on the Free plan.
403 upgrade_requiredThe source uses signals above the plan (required_plan says which).
404 not_foundNo such list / farm / search / deal / parcel on this account.
400 bad_requestA parameter is wrong; message says which.
422 unreplayableA saved search the API cannot replay.
429 rate_limited120 requests a minute per key; retry after Retry-After seconds.

Versioning is additive: fields are added, never renamed or removed. Contact data is for your own permitted use — see the compliance note.

Want the data pushed instead? Webhooks deliver the same shapes the moment something changes. Questions: support.