Integration Nuances
Person Accounts are required
NPC’s donor model depends on Salesforce’s Person Account feature — Accounts with an embedded Contact record. WeGive discovers your org’s PersonAccount record type ID at OAuth time and stores it.
Implications:
- The Salesforce admin must enable Person Accounts in the org before connecting WeGive.
- WeGive can detect three Account record types: Person Account (individuals), Organization (companies), and a Household record type for family groupings. Other record types you’ve defined are ignored unless you list them in
hidden_record_types.
Polling-based pull, no inbound webhooks
NPC does not push change events to WeGive. All changes flow in through a scheduled pull job that uses Salesforce LastModifiedDate to fetch only changed records.
- The pull interval is set by
pull_frequencyin Configuration Options, default 15 minutes. - Deletions are detected by polling records with
IsDeleted = true. They are not real-time — expect deletes to reflect in WeGive within one pull interval. - Merges are also pull-only: WeGive queries deleted Account and Contact records and replays the merge target so the linkage stays correct.
Bulk API 2.0 for large syncs
Initial historical imports and large back-fills use Salesforce Bulk API 2.0:
- WeGive creates a Bulk API job, uploads records as a CSV stream, and polls for completion.
- This avoids per-record REST rate limits, which would otherwise make a large import take days.
- Implementation:
ProcessNpcBatchUploadsJobandProcessNpcBatchChunkJob.
Small incremental syncs continue to use the REST APIs for low latency.
SOQL subqueries on pull
GiftTransaction pulls use SOQL subqueries to fetch designation splits in the same round-trip:
SELECT Id, OriginalAmount, Status, DonorId, CampaignId, (SELECT Id, DesignationId, Amount FROM GiftTransactionDesignationRelation)FROM GiftTransactionWHERE LastModifiedDate > :lastSyncThis is efficient but means a single transaction with many splits can produce a larger payload than you’d expect. Splits are written into WeGive as Fund Allocation records.
Soft credits are split records
GiftSoftCredit records are pulled separately from their parent GiftTransaction. Each split is its own row with PartialAmount and Role. The role string maps to WeGive’s soft credit type — see Soft Credit mapping for the full table.
Account-Contact relations
When importing donors, WeGive batch-fetches AccountContactRelation records to determine which Contacts are tied to which Accounts as logins. This is intentional — fetching one-by-one for thousands of donors would be O(n) queries. The integration looks for the roles you configured in login_contact_roles.
API version
The integration is pinned to Salesforce REST API v59.0 by default. If Salesforce deprecates an endpoint we use, we’ll bump api_version in a future release — you can also override it per org in dashboard settings.
Currency conversion
WeGive stores all monetary amounts in cents. They are divided by 100 before pushing to NPC’s currency fields (OriginalAmount, Amount, etc.). Pulls convert dollars back to cents.
Status mapping is configurable
If your org has customized GiftTransaction.Status picklist values, override the defaults under Configuration Options → Status mapping overrides. Same goes for GiftCommitment.Status.
Rate limiting
NPC’s standard REST rate limits apply. WeGive uses exponential backoff (10s, 20s, 30s) on 429 responses and respects the Salesforce Sforce-Limit-Info headers. Bulk API jobs do not count against per-second REST limits.
What WeGive does NOT do
- No managed package install — unlike NPSP, NPC sync uses standard objects only.
- No automatic field creation — WeGive does not create custom fields on NPC objects. If you need a new custom field on
GiftTransactionto sync, your Salesforce admin creates it first, then we map to it. - No NPSP Opportunity reading — the NPC integration is wired to
GiftTransaction, not Opportunity. If you need to sync NPSP-era opportunities, use the NPSP integration on a separate org.