How WeGive Pulls Soft Credits from Salesforce NPSP
Last updated: April 22, 2026
Summary
WeGive syncs soft credits from Salesforce NPSP by pulling from three distinct sources, not from a single object. This is necessary because NPSP itself stores soft credits in different places depending on how they were created (split vs. full, contact vs. account). WeGive does NOT mimic the NPSP rollup engine's view of "hard" vs. "soft" credits on an Opportunity. Instead, WeGive reads the underlying source records directly and deduplicates between them.
The three soft credit sources
1. Partial Soft Credits (npsp__Partial_Soft_Credit__c)
Used when a soft credit is split among multiple contacts with specific amounts (for example, 50% to Contact A and 50% to Contact B on a $1,000 Opportunity).
Processed for individual donors only (type = individual)
Fields pulled: Id, npsp__Contact__c, Name, npsp__Amount__c, npsp__Opportunity__c, LastModifiedDate
2. Account Soft Credits (npsp__Account_Soft_Credit__c)
Used when the soft credit is attributed to an Account (company or organization) rather than a Contact.
Processed for company donors only (type = company)
Fields pulled: Id, npsp__Account__c, Name, npsp__Amount__c, npsp__Opportunity__c, LastModifiedDate
3. Opportunity Contact Role (role = "Soft Credit")
This is the gap a lot of customers ask about. NPSP only creates a Partial Soft Credit record when credit is being split across multiple contacts. When the full 100% of an Opportunity is soft credited to a single contact, NPSP does NOT create a Partial Soft Credit record. The credit only exists as an OpportunityContactRole with Role = "Soft Credit."
If WeGive only pulled from Partial Soft Credits, every full 100% soft credit would be missed. To solve for this, WeGive queries OpportunityContactRole records with a configurable list of role names and creates a soft credit using the full transaction amount.
Default role name: "Soft Credit"
Configurable via the soft_credit_contact_role_names setting (orgs can add roles like "Honoree," "Solicitor," etc.)
Gated by the pull_contact_role_soft_credits feature flag
Stores the Contact Role Id on the synced soft credit record so we can track the source
Deduplication
When both a Partial Soft Credit record and an OpportunityContactRole exist for the same donor and transaction, WeGive deduplicates so only one soft credit is written. The Partial Soft Credit takes precedence because it carries the explicit split amount.
Multiple transactions per Opportunity
When a customer is on uses_payments = true, a single Opportunity can be associated with multiple Transactions (for example, a pledge with multiple payments). In that case, the Contact Role method creates a separate soft credit for each Transaction tied to that Opportunity.
What WeGive does NOT do
WeGive does not read or mirror the NPSP rollup fields on Opportunity or Contact (for example, npo02__Soft_Credit_Total__c). Those fields are the output of NPSP's rollup batch jobs, not the source of truth.
WeGive does not infer hard vs. soft from Opportunity fields. Hard credits come from the Opportunity's primary contact / Account linkage and flow through the normal Opportunity and Transaction sync. Soft credits are always sourced from the three objects above.
Frequently asked questions
"We have soft credits showing in Salesforce that aren't in WeGive." Most common cause: the soft credit is stored as an OpportunityContactRole (full 100% credit) but the pull_contact_role_soft_credits flag is not enabled for that org, or the org uses a non-default role name that has not been added to soft_credit_contact_role_names.
"We use a custom role like 'Honoree' or 'In Memory Of', will those sync?" Yes, but only if the role name is added to the soft_credit_contact_role_names setting for the org.
"Why am I seeing what looks like duplicates?" Check whether the same donor has both a Partial Soft Credit and an OpportunityContactRole for the same Opportunity. WeGive deduplicates these, but if the Contact Role was created after the initial sync there can be a brief window before the dedupe catches up on the next run.
Troubleshooting checklist
Confirm which NPSP object the soft credit lives on in Salesforce (Partial Soft Credit, Account Soft Credit, or OpportunityContactRole).
If it's an OpportunityContactRole, confirm pull_contact_role_soft_credits is enabled and the role name is in soft_credit_contact_role_names.
Confirm the donor type matches the source object (individuals for Partial Soft Credit, companies for Account Soft Credit).
Check the last sync timestamp for the org and whether the record's LastModifiedDate is after it.