Initial sync overview and best practices

Last updated: January 9, 2026

Overview

Your customer just integrated their account into your product with Merge Link, what happens next? This article explains the initial sync - how it works, what to expect, and how to monitor it, so you can design a smooth product and user experience.

What happens right after a Linked Account is connected?

Right after a Linked Account is successfully connected, Merge begins the initial sync. During the initial sync, Merge retrieves and normalizes all data that exists in the third-party that adheres to your configured common model scopes and selective sync filters.

Merge stores data as soon as we get it from the third-party - meaning you'll start to see data returned from Merge's endpoints while the initial sync is still running.

How long does the initial sync take?

This initial sync can take anywhere from a few minutes to hours, depending on:

  • amount of data to be synced (eg. 100 employees v/s 10K employees in HRIS)

  • the third‑party’s API rate limits (some 3P have harsh rate limits like 60 queries per min)

  • the integration connected (3P API performance and response formats)

For typical accounts, you can usually expect the initial sync to complete in few hours, but large accounts could take over 24 hours.

Because of the significant variability, Merge can't commit to specific initial sync completion times with customers.

How do I know when the initial sync is complete?

There are three ways to monitor initial sync progress:

  • Poll GET /sync-status for overall and per–common model sync progress

  • Subscribe to the Linked account synced webhook to be notified when the initial sync completes

  • Subscribe to the Common model synced webhook to be notified when the initial sync completes for a common model. This is useful if your product depends on a specific common model.

The /sync-status endpoint

Sample response from GET /sync-status during the initial sync:

{
  "results": [
    {
      "model_name": "Employee",
      "model_id": "hris.Employee",
      "last_sync_start": "2025-11-27T10:39:49.905833Z",
      "next_sync_start": null,
      "last_sync_result": null,
      "last_sync_finished": null,
      "status": "SYNCING",
      "is_initial_sync": true
    }
  ]
}

Note:

  • is_initial_sync = true identifies initial sync

  • status reflects current progress per common model (Employee model in above sample).

  • status = DONE would mean sync is complete. Sync status definitions

Recommended polling cadence:

  • Start at every 15–30 seconds for the first 2–3 minutes.

  • Back off to every 1–5 minutes

  • Stop polling once status= DONE is reported.

Linked account synced webhook

The Linked account synced webhook can notify when the initial sync completes. You can configure this webhook on the Webhooks management console in your Merge dashboard. Learn more

What it does:

  • Fires once per Linked Account when the sync is complete across common models.

  • Payload includes is_initial_sync = true so you can distinguish this event from subsequent routine syncs.

Sample Linked account synced webhook payload for a ticketing category linked account:

{
  "hook": {
    "id": "2fa2b314-33c6-48d5-9eb8-683dc5754429",
    "event": "LinkedAccount.sync_completed",
    "target": "https://david-merge.requestcatcher.com/"
  },
  "linked_account": {
    "id": "7841ee0a-5a1a-44db-bc7e-2912d8c17515",
    "integration": "Azure DevOps",
    "integration_slug": "azure-devops",
    "category": "ticketing",
    "end_user_origin_id": "TEST_AUM6QPMP",
    "end_user_organization_name": "MERGE Test User AUM6QPMP",
    "end_user_email_address": "[email protected]",
    "status": "COMPLETE",
    "webhook_listener_url": "https://api.merge.dev/api/integrations/webhook-listener/7hT4V5bFJBeu1fYD5Hy79rT_VCL6qBF7r1mJHGm5BRrNiJlwOEs6dg",
    "is_duplicate": null,
    "account_type": "TEST",
    "completed_at": "2025-11-26T23:54:25.835905Z"
  },
  "data": {
    "is_initial_sync": true,
    "sync_status": {
      "ticketing.TicketingAttachment": {
        "last_sync_result": "DONE",
        "last_sync_finished": "2025-11-27T00:16:19Z"
      },
      "ticketing.Ticket": {
        "last_sync_result": "DONE",
        "last_sync_finished": "2025-11-27T00:16:19Z"
      },
      "ticketing.Collection": {
        "last_sync_result": "DONE",
        "last_sync_finished": "2025-11-27T00:48:01Z"
      },
      "ticketing.Role": {
        "last_sync_result": "DONE",
        "last_sync_finished": "2025-11-27T00:22:49Z"
      },
      "ticketing.User": {
        "last_sync_result": "DONE",
        "last_sync_finished": "2025-11-27T00:22:49Z"
      },
      "ticketing.TicketingTeam": {
        "last_sync_result": "DONE",
        "last_sync_finished": "2025-11-27T00:22:49Z"
      }
    }
  }
}

Note:

  • is_initial_sync = true identifies initial sync.

  • status = COMPLETE reflects all the common models in the Linked account have been synced.

Recommendation:

  • Do not rely solely on the webhook. If you miss it, /sync-status polling will still show completion.

  • For maximum reliability, combine both approaches: listen for the webhook for immediate updates, but poll /sync-status periodically as a safety net.

Common model synced webhook

In most scenarios, your product wouldn't need the entire data to be synced but require certain common models to start letting your users to use the integration. For example - if there is a configuration step after the initial connection that only requires data from Groups common model, you wouldn't want to wait for all the common models to sync. Common model synced webhook would be useful in this case which can notify with sync status of each common model.

Sample Common model synced webhook payload for Candidates common model in ATS category:

{
  "hook": {
    "id": "e8affe31-8ae0-4b37-8c50-d86303094dc4",
    "event": "Candidate.synced",
    "target": "https://yoururl.com"
  },
  "linked_account": {
    "id": "a3602c03-aba7-4d9d-a349-dbc338504092",
    "integration": "Workday",
    "integration_slug": "workday",
    "category": "ats",
    "end_user_origin_id": "",
    "end_user_organization_name": "Test",
    "end_user_email_address": "[email protected]",
    "status": "COMPLETE",
    "webhook_listener_url": "https://api.merge.dev/api/integrations/webhook-listener/IDS",
    "is_duplicate": null,
    "account_type": "PRODUCTION"
  },
  "data": {
    "integration_name": "Ashby",
    "integration_id": "ashby",
    "synced_fields": ["first_name", "last_name"],
    "sync_status": {
      "model_name": "Candidate",
      "model_id": "ats.Candidate",
      "last_sync_start": "2023-09-27T20:50:47.490402Z",
      "next_sync_start": "2023-09-11T23:24:52.242660Z",
      "status": "COMPLETE",
      "last_sync_result": "DONE",
      "last_sync_finished": "2023-09-27T20:53:47.490402Z",
      "is_initial_sync": true
    }
  }
}

Note:

  • is_initial_sync = TRUE identifies initial sync.

  • model_name identifies the common model

  • status = COMPLETE reflects all data in the particular common model has been synced.

Recommendation:

  • Do not rely solely on the webhook. If you miss it, /sync-status polling will still show completion.

  • For maximum reliability, combine both approaches: listen for the webhook for immediate updates, but poll /sync-status periodically as a safety net.

Make your product “ready” based on sync status

A tight integration between your product and the sync status is necessary to ensure a smooth user experience for your customer. No one would like to keep clicking on "Show Employees" to not find anyone or see an incomplete list. The following are some ideas on how you can use the intial sync status in your product to design a smooth experience for your users:

  • Show a “Syncing your data” banner until initial sync complete

  • Gate features that require all/some common models to be synced

  • Surface high-level error with GET /issues endpoint or issues webhook and provide “Retry” or “Contact support” guidance wherever necessary.

Common issues and fixes

status = Partially Synced

You could see the status for some common models is "Partially Synced" which would mean that one or more fields for the specific Common Model failed to sync. Learn how you can investigate the Partially synced status.

Sync failures

A sync could fail due to various reasons- issue with the 3rd party or with Merge servers. But in any case, Merge has a robust retry mechanism built which will automatically restart the sync.