Skip to main content
The /api/v1/sync/snapshot endpoint downloads every current record in a named dataset in a single paginated response. Each snapshot response includes a version object with a cursor string that acts as a bookmark — after loading the initial snapshot, pass that cursor to /api/v1/sync/changes to receive only the records that changed since your last sync. This two-step pattern (snapshot once, then poll changes) keeps your CRM or quoting database up to date without re-downloading entire datasets on every run. The endpoint supports conditional GET via the ETag / If-None-Match mechanism. If nothing has changed since your last snapshot, the API returns 304 Not Modified with an empty body, saving both bandwidth and API quota.

Request

GET https://homeservicedata.com/api/v1/sync/snapshot

Authentication

All requests must include your API key in the x-api-key header. The required access tier varies by dataset; most datasets require production tier.

Query Parameters

dataset
string
required
The dataset to snapshot. Must be one of the following keys:
KeyDescription
finance_feesDealer-fee and finance-program rows used by quote tools
finance_productsFinance product catalog
finance_eligibilityEligibility rules by trade, state, county, and measure
equipment_pricingEquipment catalog with pricing
utility_territoryUtility territory boundary data
electricity_ratesElectricity rate data by territory
hvac_incentivesHVAC-specific rebate and incentive programs
hvac_climateHVAC climate context by county
hvac_laborHVAC labor adder records
hvac_ahri_matchesAHRI-certified HVAC system match records
trade
string
Optional trade filter. When provided, only records for that trade category are returned. Must be one of solar, hvac, roofing, plumbing, or electrical. Not all datasets carry trade-scoped records — for trade-agnostic datasets the parameter is accepted but has no filtering effect.
limit
integer
Maximum number of records to return. The ceiling varies by dataset (up to 5000 for high-volume datasets like finance_fees). When omitted, the dataset’s default maximum is used. Lowering the limit is useful during development or when testing incremental sync without pulling full production volumes.

Conditional GET (ETag)

Every 200 response includes an ETag response header. Store that value and include it as If-None-Match on your next request. If the dataset version and limit parameters have not changed, the API returns 304 Not Modified with no body, and no quota is charged for the data transfer.
# First request — no ETag yet
curl https://homeservicedata.com/api/v1/sync/snapshot?dataset=finance_fees \
  -H "x-api-key: YOUR_API_KEY" \
  -i

# Subsequent request — send stored ETag
curl https://homeservicedata.com/api/v1/sync/snapshot?dataset=finance_fees \
  -H "x-api-key: YOUR_API_KEY" \
  -H 'If-None-Match: "v42:finance_fees:all:5000"' \
  -i
# → HTTP 304 Not Modified (no body, no data charge)

Response

data
object
Top-level data envelope containing the snapshot payload.

Examples

curl -G https://homeservicedata.com/api/v1/sync/snapshot \
  -H "x-api-key: YOUR_API_KEY" \
  --data-urlencode "dataset=finance_fees"

Response — 200 OK

{
  "data": {
    "dataset": {
      "key": "finance_fees",
      "title": "Finance Fee Records",
      "endpoint": "/api/v1/finance/fees",
      "source": "current_finance_fee_records",
      "trade": "all"
    },
    "version": {
      "id": "018f3a2b-1c4d-7e8f-9012-3b4c5d6e7f80",
      "number": 42,
      "cursor": "v42:finance_fees:all",
      "published_at": "2025-01-15T18:30:00.000Z",
      "row_count": 1248,
      "quote_safe_count": 1201,
      "change_summary": {
        "upserted": 14,
        "deleted": 2,
        "unchanged": 1232
      }
    },
    "records": [
      {
        "finance_program_version_id": "018f3a2b-0000-7e8f-0001-3b4c5d6e7f01",
        "trade_category": "solar",
        "financier_name": "GoodLeap",
        "financier_slug": "goodleap",
        "product_title": "GoodLeap 25-Year 5.99%",
        "quote_safe": true
        /* additional fields vary by dataset */
      }
    ],
    "sync": {
      "mode": "snapshot",
      "etag": "\"v42:finance_fees:all:5000\"",
      "cursor": "v42:finance_fees:all",
      "changes_url": "/api/v1/sync/changes?dataset=finance_fees&since=v42%3Afinance_fees%3Aall"
    }
  },
  "error": null,
  "meta": null
}

Response — 304 Not Modified

When If-None-Match matches the current ETag, the API returns an empty 304 response with no body.
HTTP/1.1 304 Not Modified
ETag: "v42:finance_fees:all:5000"
X-HSD-Dataset: finance_fees
X-HSD-Cursor: v42:finance_fees:all

Next Steps

Once you have a snapshot cursor, use Sync Changes to poll for incremental updates without re-downloading the full dataset.