The fundamental shape
For most partner integrations, Raise is the source and an external system is the destination: The customer’s fundraising team operates Raise (collecting donations, managing donors, configuring campaigns). The customer’s other teams need that data in their respective systems. The partner integration’s job is to keep those downstream systems aligned with what’s happening in Raise. The patterns on this page describe different ways to design that pipeline. Most production integrations use a combination of two or three.Pattern 1: webhook-driven push (the default)
The simplest pattern — Raise pushes events to the partner, the partner writes to the destination. The pattern in code:When this pattern fits
When this pattern doesn’t fit alone
Pattern 2: polled pull
For destinations that can’t receive webhooks (legacy systems, on-premise tools, batch-oriented warehouses), the partner integration polls Raise on a schedule: The pattern in code:When polled pull fits
Trade-offs vs. webhook-driven
Advancing the checkpoint correctly
A common bug in polled pull: advancing the checkpoint to “now” rather than to the last successful record’s timestamp:Pattern 3: hybrid (webhook + periodic reconciliation)
The most robust production pattern. Webhooks handle steady-state real-time sync; periodic reconciliation catches anything webhooks missed. The reconciler runs daily (or hourly for higher-stakes integrations) and verifies that every Raise record from yesterday made it to the destination. Gaps go back into the queue for re-processing. The pattern in code:Why hybrid is the production default
Tuning reconciliation cadence
Pattern 4: backfill + steady-state
For customers with existing data when the integration starts, a backfill pulls historical records before steady-state sync takes over. The full sequence:Customer onboarding triggers initial backfill
POST /api/Gift/query with pagination.Subscribe to webhooks (in parallel)
Backfill streams records to the same queue as the webhook
When backfill completes, mark the customer as live
Daily reconciliation begins after cutover
When backfill is needed
Backfill performance
A customer with 100,000 historical gifts is a substantial backfill — atTake=1000 with 1-second throttling, that’s ~100 minutes of constant API calls. Plan for this:
Resumable backfill
If the backfill crashes partway through, it should resume from where it left off rather than starting over. Track progress in a checkpoint:Pattern 5: two-way coordination (rare)
When the partner integration writes back to Raise — for example, syncing donor preferences from an external system into Raise — coordination between the two directions becomes important. The pattern in code:The echo problem
When the partner writes to Raise, Raise fires a webhook back. Without coordination, the partner integration would treat the echo as an external change and try to sync it back to the external system — producing a loop. The “write attribution” pattern records the partner’s intent before writing so the echo can be recognized and ignored.When two-way sync is needed
Combining patterns
Real production integrations combine these patterns. The most common combination:Destination-specific considerations
The patterns above apply broadly, but specific destination types have particular needs:Accounting destinations (QuickBooks, Xero, NetSuite)
BI / data warehouse destinations (Snowflake, BigQuery, Redshift)
External CRM destinations (HubSpot, Salesforce, ActiveCampaign)
Marketing automation destinations (Mailchimp, Klaviyo, Iterable)
Operational practices
A few practices that apply to any sync architecture:Monitor everything end-to-end
Track the full journey: gift creation in Raise → webhook delivery → queue depth → worker processing → destination write → reconciliation verification. Latency at each step. Failure rate at each step. The end-to-end view catches issues that any single stage’s metrics miss.Per-customer dashboards
For partner integrations with many customers, build per-customer dashboards that show sync health for each:- Last successful sync timestamp
- Records synced today / this week / this month
- Open dead-letter entries
- Webhook subscription status
- Recent reconciliation results
Customer-facing audit trail
Expose the sync history to the customer’s team. They should be able to look up any Raise gift ID and see where it is in the sync pipeline — synced to which destinations, with what destination ID, at what time. Turns “we’ll have to investigate” into “I can see exactly what happened.”Graceful degradation
When a destination is unavailable, the sync should pause for that destination rather than failing the whole pipeline. A workflow that writes to three destinations should continue to write to the two that are healthy when the third is down.Choosing an architecture
For a new integration, walk through these questions:Where does the data flow?
What's the acceptable latency?
Can the partner host a public webhook receiver?
Is there existing data to backfill?
How critical is data accuracy?
Are there multiple destinations?
Is bidirectional sync needed?