KeysIQ Public API

v1 — REST + GraphQL

Programmatic access to the same scoring engine that powers keysiq.xyz. Built for insurance carriers, mortgage underwriters, and anyone running portfolios across the Florida Keys.

Get an API key

Sign up at app.keysiq.xyz, open the Embed → API Keys tab, and create a key with the public-api scope. Free tier is 1,000 requests/month — no credit card.

Pricing

TierPriceMonthly requestsRate limit
Free dev$01,00060 / min
Starter$99/mo10,000300 / min
Growth$499/mo100,000600 / min
Enterprisecontactcustomcustom

Rate-limit headers (`X-RateLimit-Limit`, `X-Quota-Limit`, `X-Quota-Remaining`) appear on every response. A 429 means either the per-minute bucket is empty (retry in 60s) or the monthly quota is exhausted (resets at the timestamp in `X-RateLimit-Reset`).

Authentication

curl -H "Authorization: Bearer kpa_..." \
  https://api.keysiq.xyz/api/v1/parcels/00046800-000000

REST endpoints

GET/api/v1/parcels/:parcelId

Full property report — all six scores plus raw inputs and source attribution.

GET/api/v1/parcels?address=<addr>

Geocode + lookup. Returns the same shape as a parcel-id lookup.

GET/api/v1/parcels/:parcelId/scores

Just the six scores — lighter payload for portfolio-wide ETLs.

GET/api/v1/parcels/:parcelId/comparables?radius_mi=1&limit=5

Nearby parcels, ranked by composite score.

POST/api/v1/batch/lookup

Body: { "parcelIds": ["a","b",...] }. Up to 100 ids per call. Per-row ok/error envelope.

GET/api/v1/layers/flood-zones?bbox=...

GeoJSON layers — flood zones, ROGO tiers, SLR scenarios, recent permits.

Response envelope

{
  "data": { ... },
  "meta": {
    "request_id": "01HFG...",
    "version": "1.0",
    "rate_limit": { "capacity": 600, "remaining": 600, "reset_at": "2026-05-01T00:00:00Z" },
    "quota":      { "monthly_limit": 10000, "used": 274, "remaining": 9726 }
  }
}

GraphQL

Same data via POST /api/v1/graphql. Schema includes parcel(id), parcelByAddress(address), comparables, and batchLookup. GraphiQL is enabled on staging.

query ($id: ID!) {
  parcel(id: $id) {
    parcel_id
    address
    scores {
      composite
      flood_risk
      insurance_cost_usd_per_year
      rogo_buildability
      vr_income
      climate_resilience
    }
  }
}

Code examples

Node (fetch)

const res = await fetch(
  "https://api.keysiq.xyz/api/v1/parcels/00046800-000000",
  { headers: { authorization: `Bearer ${process.env.KEYSIQ_API_KEY}` } }
);
const { data, meta } = await res.json();

Python

import os, requests
r = requests.get(
    f"https://api.keysiq.xyz/api/v1/parcels/00046800-000000",
    headers={"Authorization": f"Bearer {os.environ['KEYSIQ_API_KEY']}"})
print(r.json()["data"]["scores"])

Insurance figures are estimates only — not binding quotes. Always verify with a licensed Florida agent before relying on them.

See the changelog for version history.