Skip to main content
Syncs let you maintain an up-to-date local copy of data from any external API. Nango polls the API on a schedule, detects additions, updates, and deletions, and notifies your backend via webhooks so you can process only what changed.

When to use syncs

Syncs are the right tool when you need to:
  • Store a local copy of external data and keep it up to date (CRM contacts, Drive files, call transcripts).
  • Feed a RAG pipeline — embed and index fresh documents as they change.
  • Build a search index — re-index records only when they change.
  • Trigger workflows on new or modified data without requiring the external API to support webhooks.
  • Combine polling with webhooks for a reliable, real-time stream of changes.
For use cases where you only need to read or write data on demand (not continuously), use Actions instead.

How syncs work

1

Sync function runs on a schedule

You define a sync function in TypeScript. Nango executes it on each connection at your chosen frequency (minimum 15 seconds). The function fetches data from the external API, transforms it to your model, and saves it with nango.batchSave().
2

Nango detects changes

Nango compares incoming records against the previous snapshot and identifies additions, updates, and deletions automatically.
3

Webhook notification

After each sync run, Nango sends a webhook to your backend with a modifiedAfter timestamp. You fetch only the changed records.
4

Your app processes records

You call nango.listRecords() (or the REST API) with the cursor or timestamp from the webhook, retrieve the delta, and store or process the records in your system.

Full sync vs. incremental sync

Checkpoints are saved with nango.saveCheckpoint() and retrieved with nango.getCheckpoint(). On the first run, getCheckpoint() returns null, so you fetch everything. On subsequent runs, you pass the saved timestamp to the API to fetch only the delta.

Building a sync

The following example syncs contacts from Salesforce incrementally:
Key utilities used in the function:
  • nango.getCheckpoint() — retrieves saved checkpoint; returns null on first run.
  • nango.saveCheckpoint() — persists progress so the next run resumes from here.
  • nango.batchSave(records, modelName) — writes records to Nango’s encrypted cache.
  • nango.get({ endpoint }) — makes an authenticated request to the external API.

Reading synced records

After receiving a webhook notification from Nango, fetch the changed records using the modifiedAfter timestamp or a cursor.

Fetch by timestamp

Cursor-based synchronization

Webhooks can occasionally be missed. Cursor-based synchronization is more reliable — it tracks exactly how far you’ve consumed the record stream per connection, regardless of missed notifications. Each record includes a _nango_metadata.cursor field. Store the cursor of the last record you processed. On the next fetch, pass that cursor to receive only records modified after it:
The recommended cursor synchronization loop:
  1. Receive a webhook notification from Nango.
  2. Look up the stored cursor for this connection and model.
  3. Call listRecords with that cursor.
  4. Process and store the records.
  5. Save the cursor from the last record for next time.

Record metadata

Every record returned by listRecords includes a _nango_metadata object automatically populated by Nango:
last_action is one of ADDED, UPDATED, or DELETED. Use it to decide whether to insert, update, or remove the record from your system.

Webhooks for real-time triggers

Nango sends a webhook to your backend after each sync run that produces changes. Configure your webhook endpoint in the Nango dashboard, then handle incoming events:
Nango automatically prunes record payloads not updated for 30 days, and deletes all records for syncs not executed in 60 days. Fetch records promptly after webhook delivery and store them in your own system. Do not use Nango’s cache as your primary long-term data store.

Polling vs. event-driven

Nango supports both approaches and lets you combine them: See the real-time syncs guide for instructions on configuring external webhook triggers.