Skip to main content
Home Service Data is designed to run inside quoting tools, CRMs, and workflow systems that need fast local access to dataset records — not round-trip latency on every quote. The sync model lets you download a full dataset snapshot once, store a cursor that marks your position in dataset version history, and then poll for only the records that changed since that cursor. Your local store stays current without re-fetching thousands of rows on every poll cycle.

Core Concepts

Snapshot

A snapshot is a complete download of all currently published records for a dataset. It represents the state of the dataset at the moment of the most recently published version. When you call the snapshot endpoint, you receive:
  • Every record in the current version of the dataset
  • A version object with the version number, publish timestamp, total row count, and quote-safe count
  • A sync object containing an etag, a cursor string, and a changes_url pointing to the delta endpoint pre-seeded with your new cursor
Use the snapshot as your initial seed when you first integrate a dataset, or to perform a full reset if your local store diverges.

Delta / Changes

A delta (or changes response) contains only the records that changed after a given cursor. Rather than returning full records for unchanged rows, it returns a list of DatasetChange objects — each carrying the record ID, the operation type, and the new payload (for upserts) or just the ID (for deletes). Delta responses also return a latest_cursor you should store to use as the since parameter on your next poll. If has_changes is false, no records changed since your cursor — store the latest_cursor anyway because it advances through empty version windows.

Cursor

A cursor is an opaque string that represents a specific point in dataset version history. You should treat it as a token, not a timestamp or integer — its internal format may change between API versions. Cursors are stable: if you store a cursor from six months ago and pass it as since, the API returns all changes that occurred after that version. There is no cursor expiry window for standard polling intervals.
Never construct or parse a cursor value. Always store and replay the exact string returned by the API. Cursors from a snapshot response and from a changes response are interchangeable — they reference the same version namespace.

Supported Datasets

You can sync any of the following dataset keys using the snapshot and changes endpoints:

Change Operation Types

Every entry in a changes array carries an operation field with one of three values:
Apply operations in the order they appear in the changes array. A single poll window may contain both an upsert and a later delete for the same record_id. Applying them out of order will leave a stale record in your store.

The Sync Flow

Follow these steps to keep a local dataset store current:
1

Fetch the snapshot

Call the snapshot endpoint for your dataset. Store all returned records in your local store (database, cache, or in-memory map).
2

Store the cursor

Persist sync.cursor alongside the records. You will pass this as the since parameter on your next poll. Associate the cursor with the dataset key and trade filter you used so you can look it up correctly.
3

Poll for changes

On your polling schedule, call the changes endpoint with your stored cursor.
4

Apply upserts and deletes

Iterate changes in order. For upsert and supersede, replace the record in your local store using record_id as the key. For delete, remove the record.
5

Store the new cursor

Replace your stored cursor with latest_cursor from the changes response. This becomes your since value on the next poll. If has_changes was false, store the latest_cursor anyway — it may have advanced past empty version windows.

Using the TypeScript SDK

The hsd-client-sdk handles snapshot fetching, cursor storage, cache management, and change application for you. You supply a cache adapter; the SDK updates it automatically on every sync call.
Use MemoryHsdCacheAdapter for serverless functions where you want each invocation to start fresh, and createLocalStorageCacheAdapter for browser-based applications that should persist the cache across page loads.

ETag Headers and Conditional GET

The snapshot endpoint returns an ETag response header whose value matches sync.etag in the response body. On subsequent requests, you can pass this value as If-None-Match to receive a 304 Not Modified response when the dataset version has not changed since your last fetch — saving bandwidth and processing time.
When you receive 304, your local store is already current. No body is returned and no cursor update is needed. Always pass the ETag value exactly as returned by the API — including the W/ prefix and the surrounding double-quotes.
ETags and the delta endpoint serve different use cases. Use ETags for snapshot polling when you want to avoid re-processing an unchanged full dataset. Use the delta endpoint when you need to know exactly which records changed and want to apply targeted updates.

Pagination on Large Change Sets

If more changes exist than the default page limit, the sync.next_url field in the changes response contains a pre-built URL for the next page. Continue following next_url until it is null, then store the final latest_cursor. For full API parameter documentation, see the Sync Snapshot reference and Sync Changes reference.