Bulk import and backfill

Import contacts or conversations safely within API limits and without duplicate writes.

The public API does not provide a general asynchronous import endpoint. Build imports as resumable jobs over the normal contact and conversation operations.

Import loop

  1. Normalize and validate input before enqueueing it.
  2. Assign every source row a stable external ID in your database.
  3. Search or look up the corresponding ThriveDesk record.
  4. Create or update only when necessary.
  5. Persist the ThriveDesk ID and result before acknowledging the job.
  6. Back off on 429 using Retry-After.

Keep concurrency below the global 300-requests-per-minute IP limit and reduce it further when other production traffic shares the same egress IP.

for await (const row of importRows()) {
  if (await mappings.has(row.sourceId)) continue;
  const contact = await createContact(row);
  await mappings.put(row.sourceId, contact.id);
}

Errors

Write validation failures to a dead-letter report with the source row, status code, and field errors. Do not retry 422 unchanged. Reconcile timeouts before repeating POST requests.