Skip to main content
For partner integrations that read data from both Raise and CRM+, reconciliation is the workflow that keeps the two views aligned. The platform-level sync between Raise and CRM+ is eventually consistent — most data flows through within seconds, but occasional records take longer, fail silently, or end up in inconsistent states. Reconciliation is how a partner integration detects and handles those cases. This page covers when reconciliation is needed, the three patterns that work, and the operational patterns that keep reconciliation running cleanly day-to-day. For the underlying mechanics of how data flows between the products, see How Raise Data Flows to CRM+.

When to use this workflow

For integrations that touch only one product (a Raise-only fundraising integration, a CRM+-only stewardship tool), reconciliation across the two isn’t needed. The remaining patterns assume both products are in scope.

What the integration is reconciling

The three reconcilable resource mappings (from How Raise Data Flows to CRM+): A reconciliation discrepancy is a record that exists on one side but not the other, or a pair where the linkage is broken.

Pattern 1: crmKey as the join key

The cheapest reconciliation pattern. For any given Raise record, the crmKey field tells you whether it has been synced and what its corresponding CRM+ record is.

Quick consistency check

JavaScript
The three non-consistent states this surfaces:

Bulk consistency check

For checking many donors at once, batch the lookups:
JavaScript
For very large donor sets, throttle the concurrent CRM+ lookups — Promise.all of thousands of fetches will hit rate limits or overwhelm the network. Use a controlled-concurrency pattern (e.g., a queue with N workers) and pace per-customer per-product limits.

Pattern 2: dual webhook subscription with deduplication

For real-time reconciliation, subscribe to webhook events from both products and deduplicate at the integration level.

The dual subscription

Set up one subscription per product, each pointing to your integration’s webhook endpoint:
cURL

The deduplication

When events arrive from both products for the same logical entity (a Raise Gift and the CRM+ Gift that’s its synced counterpart), the integration treats the first arrival as the primary signal and the second as confirmation:
JavaScript
The integration’s database ends up with one row per gift, with both raiseGiftSeenAt and crmGiftSeenAt populated when both events have arrived.

Detecting one-sided arrivals

The most valuable signal from this pattern: gifts that arrive from one product but never confirm from the other within an expected window. A periodic check:
JavaScript
onlyInRaise gifts older than an hour likely indicate a sync issue worth investigating. The customer’s admin team can use the gift ID to look up its sync state in the platform tools.

Pattern 3: periodic reconciliation backstop

For high-confidence reconciliation independent of webhook reliability, run a periodic backstop that queries both sides and compares.

The full daily reconciliation

JavaScript

Allowing for sync lag

Don’t reconcile the current day during the day itself — running at noon and complaining about gifts created at 11:55 AM that aren’t in CRM+ yet produces false positives. Reconcile yesterday during today’s run:
JavaScript

What “missing in CRM+” actually means

A gift in inRaiseNotInCrm after a 24-hour sync window is one of: Build the alert to include enough context for ops to investigate without re-running diagnostics. At minimum: the Raise gift ID, the Campaign ID, the gift amount, and the Campaign’s canSync flag.

Handling discrepancies

The three patterns surface discrepancies, but they don’t fix them automatically. The right response depends on the discrepancy type:

Missing in CRM+ after sync lag

The partner integration doesn’t have a “retry sync” API endpoint to call — the sync mechanism is platform-internal. The integration’s role is to detect and surface; the customer’s admin team and the platform team handle resolution.

Orphaned crmKey

A Raise record with a crmKey pointing at a non-existent CRM+ record means one of:
  • The CRM+ record was deleted after sync completed.
  • The crmKey was set incorrectly (e.g., by a partner integration that seeded a wrong value).
The fix is typically to clear the crmKey on the Raise side (via PATCH /api/Donor/{id}) and let sync re-establish the linkage — or coordinate with the customer’s admin team if the CRM+ record needs to be recreated.

Persistent inconsistency between fields

A Raise Donor and its CRM+ Contact should have matching identity fields (name, email) once they’re linked. If they drift apart — donor’s email is updated in Raise but not reflected in CRM+ — the sync should catch up eventually, but partner integrations that detect drift can choose to: The right strategy depends on the integration’s purpose. For analytics integrations, deferring to one product as canonical is usually best; for stewardship integrations that need real-time accuracy, surfacing for review is safer.

Operational patterns

Run reconciliation on a schedule

A daily reconciliation job that runs after sync lag has settled (e.g., 6 AM the next morning) catches most issues with minimal false-positive noise. For higher-stakes integrations, hourly reconciliation with a larger lag window (4 hours) is acceptable. Don’t run reconciliation every few minutes — the per-customer query cost is significant and the false-positive rate from sync lag is high.

Track reconciliation results over time

Each reconciliation run produces metrics:
  • Total Raise records found
  • Total CRM+ records found
  • Number of in-Raise-not-in-CRM discrepancies
  • Number of in-CRM-not-in-Raise discrepancies
  • Number of not-yet-linked records
Trend these over time. A baseline of ~0 discrepancies with occasional spikes is normal; a sustained spike indicates a sync issue worth investigating.

Provide a clear ops dashboard

When discrepancies are detected, ops needs to know:
  • Which customer is affected
  • The specific record IDs in question
  • The amounts involved (gifts, especially)
  • The likely cause (canSync false, sync lag, genuine failure)
  • A direct link to the records in the Raise admin UI and the CRM+ admin UI
The crmKeyUrls field on Raise records is helpful here — it provides the direct URL to the CRM+ record without requiring ops to assemble URLs by ID. See How Raise Data Flows to CRM+: crmKeyUrls.

Don’t auto-remediate without human review

Tempting as it is to write “if discrepancy detected, retry sync” logic, the platform sync isn’t partner-controlled and auto-remediation can mask underlying issues. Surface discrepancies for human review; let the customer’s admin team and the platform team handle resolution.

A complete reconciliation snippet

Putting it all together as a daily job:
JavaScript
Run this on a daily cron job (e.g., 6 AM) with date = yesterday. Track the metrics over time. Alert on actionable discrepancies but not on not_yet_linked or test-mode records.

Where to go next

How Raise Data Flows to CRM+

The underlying mechanics of the cross-product sync.

Query Gifts by Filters

The Gift-side queries that feed reconciliation.

Query Donors by Filters

The Donor-side queries that feed donor-level reconciliation.

Sync Architecture Patterns

The broader architectural patterns for sync-aware integration design.
Last modified on May 20, 2026