> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wegive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Soft Credits

> Mapping between WeGive Soft Credits and Salesforce Soft Credits

# **Salesforce Objects:**

* `npsp__Partial_Soft_Credit__c` (NPSP standard object - for Contacts)
* `npsp__Account_Soft_Credit__c` (NPSP standard object - for Accounts)
* `OpportunityContactRole` (Salesforce standard object - optional, import only)

**WeGive Model:** SoftCredit

## Overview

This document describes how soft credit data syncs between WeGive and Salesforce. Soft Credits allow you to recognize individuals or organizations who influenced a donation without being the primary donor.

In Salesforce NPSP, there are two soft credit objects:

1. **Partial Soft Credits** - For crediting individual Contacts
2. **Account Soft Credits** - For crediting company Accounts

WeGive uses a single SoftCredit model that works with both types, automatically routing to the appropriate Salesforce object based on the donor type. Optionally, WeGive can also import full soft credits that NPSP records only as Opportunity Contact Roles.

***

## How Soft Credit Data Syncs

### Direction

* **Import from Salesforce** - Data imports from Salesforce into WeGive only
* **Export to Salesforce** - Data exports from WeGive to Salesforce only
* **Both Ways** - Data syncs in both directions

### Mapping Types

* **Hard-coded** - Built into the integration logic and cannot be changed. There are no mapping rules for soft credits.

***

## Sync Configuration

Soft credit pulls and pushes are controlled by the **Pull soft credits** and **Push soft credits** toggles in Sync Configuration. Related settings:

| Setting | Effect |
| :- | :- |
| `pull_deleted_soft_credits` | Remove WeGive soft credits whose Partial or Account Soft Credit was deleted in Salesforce |
| `pull_contact_role_soft_credits` | Import soft credits from `OpportunityContactRole` records |
| `soft_credit_contact_role_names` | Contact Role values treated as soft credits (default: "Soft Credit") |
| `pull_deleted_contact_role_soft_credits` | Remove WeGive soft credits whose Contact Role was deleted in Salesforce |

***

## Sync Triggers

### From WeGive to Salesforce (Export)

Soft Credit data is exported from WeGive to Salesforce when:

* **Soft Credit Created:** A new soft credit is created in WeGive
* **Soft Credit Updated:** An existing soft credit is modified in WeGive (e.g., amount changed)
* **Soft Credit Deleted:** A soft credit is removed in WeGive

Soft credits imported from Contact Roles are never pushed back to Salesforce as Partial or Account Soft Credits.

### From Salesforce to WeGive (Import)

* **Last Modified Date:** WeGive polls both soft credit objects for records modified since the last sync
* **Deleted Credits:** With `pull_deleted_soft_credits`, records with `IsDeleted = true` in the sync window are removed from WeGive
* **Contact Roles:** With `pull_contact_role_soft_credits`, Contact Roles whose `Role` is in `soft_credit_contact_role_names` are imported; with `pull_deleted_contact_role_soft_credits`, deleted Contact Roles remove the soft credits they created

In multi-entity Salesforce orgs, soft credit pulls are filtered to Opportunities belonging to the configured WeGive entity.

***

## Sync Process Overview

### Pulling Data from Salesforce

**Account Soft Credits (for Accounts):**

1. Queries `npsp__Account_Soft_Credit__c` (`Id`, `npsp__Account__c`, `npsp__Amount__c`, `npsp__Opportunity__c`, the Opportunity's `CloseDate`)
2. Loads WeGive transactions matching the Opportunity IDs
3. Loads **company** donors matching the Account IDs **that have no Contact ID** (`salesforce_id` empty)
4. Creates or updates the SoftCredit, matched by `salesforce_id`

**Partial Soft Credits (for Contacts):**

1. Queries `npsp__Partial_Soft_Credit__c` (`Id`, `npsp__Contact__c`, `npsp__Amount__c`, `npsp__Opportunity__c`, the Opportunity's `CloseDate`)
2. Loads WeGive transactions matching the Opportunity IDs
3. Loads **individual** donors matching the Contact IDs
4. Creates or updates the SoftCredit, matched by `salesforce_id`

Both imports set the soft credit's `transaction_date` to the Opportunity's `CloseDate` at 17:00:00 when it is present.

**Contact Role Soft Credits:**

NPSP only creates Partial Soft Credit records when credit is split among several contacts. A full soft credit to one person exists only as an `OpportunityContactRole` with a soft credit role. When `pull_contact_role_soft_credits` is enabled, the integration:

1. Queries `OpportunityContactRole` where `Role` is in `soft_credit_contact_role_names`
2. Finds the individual donor matching `ContactId` and every WeGive transaction matching `OpportunityId` (an Opportunity can have several when `uses_payments` is on)
3. For each transaction, creates a SoftCredit for the **full transaction amount** with the Contact Role ID stored as `salesforce_contact_role_id` and `transaction_date` set from the Opportunity `CloseDate`
4. Skips any (donor, transaction) pair that already has a soft credit, including soft-deleted ones, so intentionally deleted credits are not recreated. On an existing match, only the `transaction_date` is refreshed

**Deleted Soft Credits:** The integration queries both soft credit objects for `IsDeleted = true` within the sync window and removes the matching WeGive soft credits. Deleted Contact Roles are handled the same way, matched on `salesforce_contact_role_id`.

### Pushing Data to Salesforce

When a SoftCredit is created, updated or deleted in WeGive, the integration:

1. **Ensures Prerequisites Exist:**
   * If the donor has no Contact ID (`salesforce_id`), the donor is pushed first. This check uses the Contact ID for all donor types
   * If the transaction has no `salesforce_id`, the transaction is pushed first
2. **Determines Object Type:**
   * Company donors use `npsp__Account_Soft_Credit__c`
   * All other donors use `npsp__Partial_Soft_Credit__c`
3. **Creates, Updates or Deletes:**
   * If the soft credit has a `salesforce_id` and is deleted: **DELETE** in Salesforce
   * If it has a `salesforce_id` and is not deleted: **UPDATE**
   * If it has no `salesforce_id` and is not deleted: **CREATE** (under a per-record lock)
   * If it has no `salesforce_id` and is deleted: nothing is sent

### Complete Field Mapping - Partial Soft Credits (Contacts)

| Salesforce Field | WeGive Field | WeGive API Field | Direction | Type | Notes |
| :- | :- | :- | :- | :- | :- |
| Id | Salesforce ID | `salesforce_id` | Import from Salesforce | Hard-coded | Salesforce's unique identifier |
| npsp\_\_Opportunity\_\_c | Transaction Salesforce ID | `transaction.salesforce_id` | Both Ways | Hard-coded | Links to the Opportunity (transaction) |
| npsp\_\_Contact\_\_c | Donor Salesforce ID | `donor.salesforce_id` | Both Ways | Hard-coded | Links to the Contact being credited |
| npsp\_\_Amount\_\_c | Amount | `amount` | Both Ways | Hard-coded | Dollars in Salesforce, cents in WeGive |
| npsp\_\_Opportunity\_\_r.CloseDate | Transaction Date | `transaction_date` | Import from Salesforce | Hard-coded | Stored at 17:00:00 |

### Complete Field Mapping - Account Soft Credits (Accounts)

| Salesforce Field | WeGive Field | WeGive API Field | Direction | Type | Notes |
| :- | :- | :- | :- | :- | :- |
| Id | Salesforce ID | `salesforce_id` | Import from Salesforce | Hard-coded | Salesforce's unique identifier |
| npsp\_\_Opportunity\_\_c | Transaction Salesforce ID | `transaction.salesforce_id` | Both Ways | Hard-coded | Links to the Opportunity (transaction) |
| npsp\_\_Account\_\_c | Donor Salesforce Account ID | `donor.salesforce_account_id` | Both Ways | Hard-coded | Links to the Account being credited |
| npsp\_\_Amount\_\_c | Amount | `amount` | Both Ways | Hard-coded | Dollars in Salesforce, cents in WeGive |
| npsp\_\_Opportunity\_\_r.CloseDate | Transaction Date | `transaction_date` | Import from Salesforce | Hard-coded | Stored at 17:00:00 |

### Field Mapping - Contact Role Soft Credits (Import Only)

| Salesforce Field | WeGive Field | WeGive API Field | Direction | Type | Notes |
| :- | :- | :- | :- | :- | :- |
| Id | Contact Role ID | `salesforce_contact_role_id` | Import from Salesforce | Hard-coded | Used for de-duplication and deletion |
| OpportunityId | Transaction Salesforce ID | `transaction.salesforce_id` | Import from Salesforce | Hard-coded | One soft credit per WeGive transaction on the Opportunity |
| ContactId | Donor Salesforce ID | `donor.salesforce_id` | Import from Salesforce | Hard-coded | Individual donors only |
| Role | Role | n/a | Import from Salesforce | Configurable | Filter via `soft_credit_contact_role_names` |
| Opportunity.CloseDate | Transaction Date | `transaction_date` | Import from Salesforce | Hard-coded | Stored at 17:00:00 |
| (none) | Amount | `amount` | Import from Salesforce | Hard-coded | Set to the full transaction amount |

## Important Notes

### Two Object Types

* **Company donors** use `npsp__Account_Soft_Credit__c`
* **All other donors** use `npsp__Partial_Soft_Credit__c`

You do not specify which object to use; the integration determines it from the donor type.

### Amount Conversion

* **WeGive:** cents as an integer (5000 = \$50.00)
* **Salesforce:** dollars as a decimal (50.00)
* **On export:** divided by 100
* **On import:** multiplied by 100. Contact Role soft credits copy the transaction's amount directly

### Automatic Prerequisite Push

When pushing a soft credit, the donor is pushed first if it has no Contact ID and the transaction is pushed first if it has no Opportunity ID.

<Note>
  The donor prerequisite check looks at the donor's Contact ID (`salesforce_id`) for every donor type. A company donor that already has an Account ID but no Contact ID will still be pushed before the soft credit.
</Note>

### Account Soft Credit Import Restriction

On import, Account Soft Credits are matched only to company donors whose Contact ID is empty. A company donor in WeGive that also carries a Contact ID will not be matched and the record fails with "Unable to find donor".

### Multiple Soft Credits

A single transaction can have multiple soft credits. There is no validation that soft credit totals match the transaction amount.

### Deletion Handling

When a soft credit is deleted in WeGive and has a Salesforce ID, the Salesforce record is deleted on the next push. The transaction and donor remain.

When a soft credit is deleted in Salesforce and `pull_deleted_soft_credits` (or `pull_deleted_contact_role_soft_credits` for Contact Roles) is enabled, the WeGive soft credit is removed on the next pull.

***

## Soft Credit Matching & Create/Update Logic

### When WeGive Exports a Soft Credit to Salesforce

1. Push the donor if it has no Contact ID; push the transaction if it has no Opportunity ID
2. With a `salesforce_id`: delete if the soft credit is deleted, otherwise update
3. Without a `salesforce_id` and not deleted: create
4. Object chosen by donor type (company vs everything else)

### When Salesforce Exports a Soft Credit to WeGive

**Partial Soft Credits:**

* Find the transaction by `npsp__Opportunity__c`; fail if not found
* Find the individual donor by `npsp__Contact__c`; fail if not found
* Find or create the soft credit by `salesforce_id`; set donor, transaction, amount, transaction date and Salesforce ID

**Account Soft Credits:**

* Find the transaction by `npsp__Opportunity__c`; fail if not found
* Find the company donor (with no Contact ID) by `npsp__Account__c`; fail if not found
* Find or create the soft credit by `salesforce_id`; set donor, transaction, amount, transaction date and Salesforce ID

**Contact Role Soft Credits:** see Pulling Data from Salesforce above.

***

## Required Fields

**For WeGive to Salesforce (Partial Soft Credits):** `npsp__Opportunity__c`, `npsp__Contact__c`, `npsp__Amount__c`

**For WeGive to Salesforce (Account Soft Credits):** `npsp__Opportunity__c`, `npsp__Account__c`, `npsp__Amount__c`

**For Salesforce to WeGive (Both Types):** `Id`, `npsp__Opportunity__c`, `npsp__Contact__c` or `npsp__Account__c`, `npsp__Amount__c`

## Usage in WeGive

Soft Credits in WeGive are used for recognition, reporting, donor engagement, major gift attribution, matching gift tracking and household giving.

## Usage in Salesforce NPSP

Soft Credits in Salesforce feed NPSP rollup summaries, reports, acknowledgment letters, campaign attribution and donor scoring.

***

## Integration Rules

Soft credit field mappings are entirely hard-coded. There are no configurable mapping rules for soft credits.

***

## Troubleshooting

**Soft credit not syncing:**

* Verify the donor has a Salesforce Contact ID and the transaction has a `salesforce_id`
* Ensure the integration user can access both soft credit objects

**Account soft credit fails with "Unable to find donor":**

* The matching WeGive company donor must have an Account ID and no Contact ID

**Full soft credits missing after import:**

* NPSP stores full (100%) soft credits as Opportunity Contact Roles, not Partial Soft Credits. Enable `pull_contact_role_soft_credits` and confirm the role name is in `soft_credit_contact_role_names`

**Deleted soft credits reappearing:**

* Confirm `pull_deleted_soft_credits` / `pull_deleted_contact_role_soft_credits` are enabled
* Contact Role imports never recreate a soft credit that was soft-deleted in WeGive

**Duplicate soft credits:**

* Partial and Account soft credits are matched only by Salesforce ID; Contact Role soft credits are matched by Contact Role ID and by (donor, transaction) pair

## Related Documentation

* [Data Mapping Overview](./overview) - object index and cross-cutting data conventions
* [Opportunity & Payment](./opportunity) - the transaction a soft credit is attached to
* [Contact](./contact) and [Account](./account) - the credited donor

*Verified against the integration source, September 2026.*


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.