Skip to main content
Calling the Home Service Data API on every quote request is fine when you are getting started, but it introduces network latency into the most time-sensitive part of your workflow. A local sync gives you sub-millisecond data access, protects your quote path from transient API availability, and lets you query HSD data with your own SQL joins and filters. Home Service Data is designed for this pattern: every dataset exposes a snapshot endpoint and a cursor-driven delta endpoint so you can keep a local mirror accurate without ever doing a full re-download.

Why sync locally?

Lower latency

Serve quote data from your own database with no outbound API call in the critical path. Response times drop from hundreds of milliseconds to single-digit milliseconds.

Offline resilience

Your quoting tool keeps working during a network interruption. The local table is the source of truth for your application; HSD keeps it current.

SQL flexibility

Join HSD datasets against your own tables. Filter, sort, and aggregate using your database’s native query planner instead of URL parameters.

Predictable API usage

Sync runs on a schedule you control. You consume API budget in planned batches rather than at the mercy of unpredictable quote volume.

Available dataset keys

The HsdDatasetKey type (exported from the SDK) defines the datasets available for sync:

Sync flow

The sync process follows five deterministic steps. The cursor is the key primitive — it is an opaque string that encodes the dataset version and position. Store it after every successful sync and pass it on the next delta call.
1

Fetch a full snapshot

Call /api/v1/sync/snapshot with the dataset key and optional trade filter. The response contains all current records plus a cursor you will store for future delta calls.
The snapshot response shape:
2

Store the cursor

Persist the cursor from snapshot.sync.cursor to a durable store — your database, a config table, or a key-value store. The cursor is opaque; treat it as a string you pass back verbatim.
Never skip the cursor update step. If your application crashes between applying changes and persisting the new cursor, you will reprocess the same changes on the next run — but that is safe because all change operations are idempotent. Skipping the cursor update entirely causes your local table to drift permanently.
3

Poll for changes with the cursor

On your scheduled interval (every 15–60 minutes is typical), read the stored cursor and call /api/v1/sync/changes. If the server responds with HTTP 304 Not Modified (ETag match), there are no new changes and you can skip the remaining steps.
4

Apply upserts and deletes

Iterate through delta.changes and apply each operation to your local table. Three operation types are possible:
5

Store the new cursor

After all changes are successfully applied, persist delta.latest_cursor to replace the previous cursor. Your next poll will start from this position.

Putting it together: a complete sync runner

Using ETags to skip no-op polls

The snapshot response includes an ETag header. On subsequent requests, pass the value as If-None-Match. If the dataset has not changed, the server returns 304 Not Modified with no body — saving bandwidth and processing time.

API reference

Sync Snapshot

Full parameter list and response schema for /api/v1/sync/snapshot.

Sync Changes

Full parameter list and response schema for /api/v1/sync/changes.