Read-only JSON access to Texas Appraisal Review Board (ARB) hearing results, county coverage, and premium no-show / failed-to-reduce leads. Multi-year, multi-county.
https://api.txtaxfight.com
All data endpoints are versioned under /v1. Responses are application/json.
Every /v1 endpoint except /v1/health requires an API key. Send it as a Bearer token or an x-api-key header:
Authorization: Bearer YOUR_API_KEY
# or
x-api-key: YOUR_API_KEY
Keys have a scope:
/leads endpoint.Keys are stored server-side as a SHA-256 hash — the plaintext is never persisted. Contact the operator to be issued a key.
Liveness probe. No auth. Returns service status, version, and time.
Coverage list: every TX county with fips, name, tier (T1/T2/T3), status (LIVE / OPEN / PIA), coverageClass, whether a live hearings feed exists, and registry freshness.
County detail + stats. When a hearings feed exists, includes stats (total / reduced / no-change / raised / pending / leads) and feed freshness.
Paginated ARB hearing results: date, disposition, board determination, noticed value, and the cut (dollars off the noticed value).
| Query | Default | Notes |
|---|---|---|
limit | 50 | max 500 |
offset | 0 | row offset |
The premium prospect list, classified objectively (no guesswork): owners who failed to reduce — the board determination came in at or above the noticed value (zero dollars off) — or who were a no-show (explicit NS disposition). Each lead carries a reason. Same pagination as hearings. agentOfRecord is returned as null until ARB-filing data is wired — it is never fabricated. A feed-scoped key hitting this endpoint gets 403.
Upload a book of properties — a JSON array of {ref?, address?, city?, state?, zip?, lat?, lng?} and/or a CSV (raw text/csv or a multipart/form-data file field). Each row is geocoded with the free US Census Bureau geocoder (returns lat/lng + county FIPS), matched to txtaxfight coverage, and classified matched (with county FIPS/name, coordinates, coverage status & tier) or failed (with a human reason). Un-geocodable rows are never assigned a guessed county. Matched rows are grouped by county (sorted by count) as a “what to license” suggestion. This endpoint calls an external geocoder, so it carries its own tighter per-key throttle on top of the normal rate limit. Response: { summary, counties[], properties[], failures[] }.
/v1/portfolio/process adds a tighter per-key window (geocoding is heavy).Exceeding either returns 429 Too Many Requests with a Retry-After header (seconds).
| Status | error | Meaning |
|---|---|---|
| 200 | — | OK |
| 401 | missing_api_key / invalid_api_key | No key, or key not found / inactive |
| 403 | insufficient_scope | feed key on a premium endpoint |
| 404 | county_not_found / not_found | Unknown fips or route |
| 413 | too_many_properties / payload_too_large | Portfolio upload over the row/byte cap |
| 415 | unsupported_media_type | Portfolio body not JSON, CSV, or multipart |
| 429 | rate_limited | Per-key or per-IP limit hit (see Retry-After) |
| 500 | internal_error | Server error |
# health (open)
curl https://api.txtaxfight.com/v1/health
# coverage list
curl -H "Authorization: Bearer $KEY" \
https://api.txtaxfight.com/v1/counties
# county detail + stats (Bell County)
curl -H "Authorization: Bearer $KEY" \
https://api.txtaxfight.com/v1/counties/48027
# hearings, paginated
curl -H "Authorization: Bearer $KEY" \
"https://api.txtaxfight.com/v1/counties/48245/hearings?limit=25&offset=0"
# premium leads (requires a premium key)
curl -H "x-api-key: $KEY" \
"https://api.txtaxfight.com/v1/counties/48245/leads?limit=25"
# portfolio: geocode + county-match a book of properties (premium)
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"properties":[{"ref":"a","address":"101 E Central Ave","city":"Belton","state":"TX","zip":"76513"}]}' \
https://api.txtaxfight.com/v1/portfolio/process
# ...or upload a CSV file:
curl -X POST -H "Authorization: Bearer $KEY" -F "file=@book.csv" \
https://api.txtaxfight.com/v1/portfolio/process
| Endpoint | Backed by |
|---|---|
| /v1/counties, /v1/counties/:fips | txarb Postgres county registry (254 TX counties) |
| /hearings, /leads | Live published county feeds (Bell 48027, Jefferson 48245) |
| /portfolio/process | US Census Bureau geocoder (free, public) + txarb county registry |
Coverage expands as counties are onboarded. Counties without a live feed return an empty hearings/leads set with total: 0.