Track Import Progress

Once a CRM Import is running, you have three ways to check on it: a summary poll, a full per-record breakdown, and a single-id lookup, plus a webhook so you don't have to poll at all. This tutorial covers all four.

Before You Begin

Make sure you have the request_id returned by Start CRM Import. All of the services below also work without it, if you omit request_id, DealHub uses the tenant's most recent import, but passing it explicitly avoids ambiguity if multiple imports have been kicked off over time.

Poll the Summary

Send a GET request to the status endpoint to get aggregate counts and any failures so far.

  • Endpoint: /api/v1/accounts/crm-import/status?request_id=<REQUEST_ID>
{
  "request_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
  "status": "RUNNING",
  "total": 1200,
  "processed": 850,
  "succeeded": 800,
  "failed": 12,
  "skipped": 38,
  "failures": [
    { "crm_id": "0011t00000XYZAB", "reason": "HubSpot rate limit (429)" }
  ]
}

Keep polling until status is COMPLETED or INTERRUPTED.

❗️

COMPLETED Doesn't Mean Zero Failures

A COMPLETED status only means every id reached a terminal state. Check the failed count (and failures) to know whether anything needs a retry.

Drill Into Per-Account and Per-Contact Detail

The status summary doesn't tell you which contacts within an account succeeded or failed. For that, call the detail endpoint.

  • Endpoint: /api/v1/accounts/crm-import/detail?request_id=<REQUEST_ID>
{
  "request_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
  "status": "COMPLETED",
  "total": 2, "processed": 2, "succeeded": 1, "failed": 0, "skipped": 1,
  "accounts": [
    {
      "crm_id": "0011t00000ABCDE",
      "state": "SUCCEEDED",
      "reason": null,
      "contacts": [
        { "crm_id": "0031t00000AAA11", "email": "[email protected]", "state": "SUCCEEDED", "reason": null },
        { "crm_id": null,              "email": "[email protected]", "state": "FAILED",    "reason": "duplicate email" }
      ]
    },
    { "crm_id": "0011t00000FGHIJ", "state": "SKIPPED", "reason": null, "contacts": [] }
  ]
}

Note that a contact can fail independently of its account: the account above is SUCCEEDED overall even though one of its contacts failed on a duplicate email.

Resolve a Single Id

If you only need to know the fate of one specific CRM id (for example, answering a support ticket about a single account or contact) use lookup instead of scanning the full detail response.

  • Endpoint: /api/v1/accounts/crm-import/lookup?crm_id=<CRM_ID>&request_id=<REQUEST_ID>
{
  "request_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
  "crm_id": "0031t00000AAA11",
  "type": "CONTACT",
  "account_crm_id": "0011t00000ABCDE",
  "state": "SUCCEEDED",
  "reason": null
}

type tells you whether the id resolved to an ACCOUNT, a CONTACT (in which case account_crm_id gives you the parent account), or NOT_FOUND if the id isn't part of this import.

Skip Polling with the Webhook

Instead of polling status in a loop, subscribe to the crmImport webhook event and react when the import finishes:

{
  "event": "crmImport",
  "import_status": "COMPLETED",
  "total": 1200,
  "succeeded": 1150,
  "failed": 12,
  "skipped": 38,
  "event_info": { "request_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "...": "..." }
}
📘

Tip

The webhook carries the same request_id you started the import with, so you can match it back to the import you're tracking. See Webhooks Overview and How to Configure Webhooks to set up a subscription.

Next Steps

If failed is greater than zero, learn how to retry a failed import.

📘

Related API Reference

The following API Reference pages document the endpoints used in this guide:



Did this page help you?