> ## 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.

# Opportunity & Payment

> Mapping between WeGive Transactions (Payments in the UI) and Salesforce Opportunities and Payments.

# **Opportunity (Transactions/Donations) - Field Mapping**

**Salesforce Object:** Opportunity<br />**WeGive Model:** Transaction

## **How Opportunity Data Syncs**

This table shows all fields that sync between WeGive and Salesforce for transactions/donations.

**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:**

* **Configurable** - Can be customized via integration settings or mapping rules
* **Configurable (mapping rule)** - Reaches Salesforce only when a mapping rule for it exists
* **Hard-coded** - Built into the integration logic and cannot be changed

***

## **Sync Configuration**

Opportunity pulls and pushes are controlled by the **Pull transactions** and **Push transactions** toggles in the integration's Sync Configuration. The settings below shape the behavior once a pull or push runs:

| Setting | Effect |
| :- | :- |
| `uses_payments` | Create and update `npe01__OppPayment__c` records alongside Opportunities, and pull from the Payment object instead of the Opportunity object |
| `stage_success`, `stage_pending`, `stage_refunded`, `stage_failed` | Salesforce StageName written for each WeGive status. Also used to interpret StageName on import |
| `stage_status_map` | Optional explicit StageName-to-status map for import, checked before the `stage_*` settings |
| `send_processing_ach_as_success` | Treat a processing ACH (bank) transaction as successful when exporting |
| `tax_deductible_record_type_id`, `service_revenue_record_type_id` | Record Type assigned on export for tax-deductible and non-tax-deductible transactions |
| `service_revenue_record_types`, `hidden_record_types` | Record Type developer names that mark imported Opportunities as non-tax-deductible or hidden |
| `card_payment_method_name`, `bank_payment_method_name`, `paypal_payment_method_name` | Payment Method picklist value written for card, bank and PayPal transactions |
| `is_legacy` | Strips the newer NPSP Payment fields from the Payment payload |
| `pull_deleted_transactions` | Remove WeGive transactions whose Opportunity was deleted in Salesforce |
| `fund_api_name` | When set to a custom fund object, the legacy single GAU Allocation is not created |
| `enable_fund_allocations` (organization setting) | Sync GAU Allocations per transaction. See the GAU & Allocation page |

***

## **Sync Triggers**

### **From WeGive to Salesforce (Export)**

Opportunity data is exported from WeGive to Salesforce when:

* **Transaction Created:** A new donation/transaction is created in WeGive
* **Transaction Updated:** An existing transaction is modified in WeGive (e.g., status changed, amount updated, campaign assigned)

The export happens automatically after the create or update action in WeGive when **Push transactions** is enabled.

### **From Salesforce to WeGive (Import)**

Opportunity data is imported from Salesforce to WeGive based on:

* **Last Modified Date:** WeGive periodically polls Salesforce for Opportunities that have been modified since the last sync
* **Sync Frequency:** The integration checks for updated Opportunities on a scheduled basis (frequency varies by integration configuration)
* **Modified Field Tracking:** Only Opportunities with a `LastModifiedDate` newer than the last successful sync are pulled into WeGive

When `uses_payments` is enabled, the pull queries the **Payment object** (`npe01__OppPayment__c`) instead of Opportunities, and only Payments with `npe01__Paid__c = TRUE` are returned. A change to either the Payment or its parent Opportunity `LastModifiedDate` triggers the import.

This means:

* Creating a new Opportunity in Salesforce will import it to WeGive on the next sync cycle (with `uses_payments`, only once it has a paid Payment)
* Updating an existing Opportunity in Salesforce will trigger an import to WeGive on the next sync cycle
* The sync is based on Salesforce's `LastModifiedDate` field, not individual field changes

### **Deleted Opportunities**

When `pull_deleted_transactions` is enabled, the integration queries Opportunities with `IsDeleted = true` in the sync window and soft-deletes the matching WeGive transaction (matched by stored Salesforce ID).

***

## **Sync Process Overview**

### **Opportunity-Level Synchronization**

WeGive syncs donations and transactions at the Opportunity level in Salesforce, which is NPSP's standard object for tracking donations. Each transaction in WeGive corresponds to an Opportunity in Salesforce, maintaining the complete donation record including donor information, amount, campaign attribution, and tribute details.

### **Pulling Data from Salesforce**

When pulling data from Salesforce, WeGive queries Opportunities (or Payments) based on the last modified date. The base query always reads `Id`, `CreatedDate`, `Amount`, `StageName`, `RecordTypeId`, `ContactId`, `AccountId`, `CampaignId`, `npe03__Recurring_Donation__c` and `npe01__Is_Opp_From_Individual__c`; any additional fields come from your Opportunity (donation) mapping rules. When `uses_payments` is enabled, Payment-level mapping rules are also applied, with Opportunity-level values taking precedence when both map to the same WeGive field.

The import then:

* Matches the WeGive transaction by stored `salesforce_id` (or by `salesforce_payment_id` when `uses_payments` is enabled) and creates a new transaction if none is found
* Resolves the owner from the mapped Contact (`owner.salesforce_id`) or Account (`owner.salesforce_account_id`) according to `npe01__Is_Opp_From_Individual__c`, and fails the record if no owner exists in WeGive
* Resolves campaign, fund, pledge, campaign fundraiser and recurring donation links from mapped Salesforce IDs
* Maps `StageName` to a WeGive status (see Picklist Values)
* Derives `is_tax_deductible` and `hidden` from the Opportunity's Record Type unless a mapping rule supplies them directly
* Stores the imported amount in cents and sets the transaction date to the mapped date at 17:00:00

<Note>
  **Import overwrite guard.** If the WeGive transaction was charged through WeGive (it has a payment correlation) or is a future-dated pending transaction, the import does not overwrite its status, amount or transaction date. `is_tax_deductible` and `hidden` are also protected on charged transactions unless a mapping rule explicitly supplies them. This prevents Salesforce automation from closing a gift before WeGive has processed it.
</Note>

### **Pushing Data to Salesforce**

When a Transaction record is created or updated in WeGive, the integration first ensures the related records exist in Salesforce: the donor (Contact or Account), campaign, fund and recurring donation are pushed if they have no Salesforce ID yet, and the payment method is pushed as an accessory (a payment method failure never blocks the gift). It then compiles the Opportunity payload, which includes:

* **Automatic Name Generation:** On create, the name is `{donor name} {MM-YY}` (for example "John Smith 01-24") unless a mapping rule supplies one
* **Stage Name Mapping:** Transaction status is mapped to the configured `stage_*` values
* **Amount Calculation:** Net donation amount (amount minus fees) is calculated and converted to dollars
* **Type Assignment:** "Recurring" or "One-Time" based on whether the transaction is linked to a recurring donation
* **Record Type Assignment:** Based on whether the donation is tax-deductible
* **Tribute Handling:** Populates tribute/memorial information when present

**NPSP Payment Creation Prevention:**

The integration sets `npe01__Do_Not_Automatically_Create_Payment__c` to `true` on create to prevent NPSP from automatically creating Payment records. The WeGive integration handles Payment creation itself when `uses_payments` is enabled.

### Opportunity Field Mappings

| Salesforce Field | WeGive Field | WeGive API Field | Direction | Type | Notes |
| :- | :- | :- | :- | :- | :- |
| Name | Transaction Name | `name` | Export to Salesforce | **Hard-coded** default, overridable by mapping rule | Create only; default `{donor name} {MM-YY}`. On import a mapped `name` becomes the transaction description |
| Amount | Donation Amount | `amount` | Both Ways | **Hard-coded** | Export: (amount - fee) / 100. Import: `Amount` x 100 (with `uses_payments`: `npe01__Payment_Amount__c` x 100) |
| CloseDate | Transaction Date | `created_at` | Both Ways | **Hard-coded** export<br />**Configurable** import | Export: `Y-m-d` in the organization timezone. Import: `created_at` defaults from `CreatedDate`; map CloseDate with a rule to use it instead. Imported dates are stored at 17:00:00 |
| Type | Transaction Type | Dynamic | Export to Salesforce | **Hard-coded** | 'Recurring' or 'One-Time' based on `scheduled_donation_id`; sent on create and update |
| LeadSource | Lead Source | Static: 'Web' | Export to Salesforce | **Hard-coded** | Create only |
| RecordTypeId | Record Type | Dynamic | Both Ways | **Configurable** | Export: `tax_deductible_record_type_id` / `service_revenue_record_type_id`, falling back to the Record Types named "Donation" / "Service Revenue"; sent on create and update when resolved. Import: drives `is_tax_deductible` and `hidden` via `service_revenue_record_types` / `hidden_record_types` |
| AccountId | Donor Account ID | `owner.salesforce_account_id` | Both Ways | **Hard-coded** export<br />**Configurable** import | Create only on export |
| ContactId | Donor Contact ID | `owner.salesforce_id` | Both Ways | **Hard-coded** export<br />**Configurable** import | Create only on export |
| npe01\_\_Is\_Opp\_From\_Individual\_\_c | Owner Type | Dynamic | Import from Salesforce | **Hard-coded** | Selects Contact (true) or Account (false) as the owner |
| CampaignId | Campaign ID | `campaign.salesforce_id` | Both Ways | **Hard-coded** export<br />**Configurable** import | Sent on create and update |
| npe03\_\_Recurring\_Donation\_\_c | Recurring Donation ID | `scheduled_donation.salesforce_id` | Both Ways | **Hard-coded** export<br />**Configurable** import | Sent on create and update |
| StageName | Opportunity Stage | `stage_name` | Both Ways | **Configurable** | See Picklist Values below |
| npsp\_\_Tribute\_Type\_\_c | Tribute Type | Static: 'Honor' | Export to Salesforce | **Hard-coded** | Create only; only populated if a tribute exists |
| npsp\_\_Honoree\_Name\_\_c | Tribute Name | `tribute_name` | Export to Salesforce | **Hard-coded** | Create only |
| npe01\_\_Do\_Not\_Automatically\_Create\_Payment\_\_c | Disable Auto Payment | Static: true | Export to Salesforce | **Hard-coded** | Boolean true; create only |
| wegive\_\_WeGive\_Entity\_\_c | WeGive Entity | Organization setting | Export to Salesforce | **Hard-coded** | Only for multi-entity Salesforce orgs with an entity ID configured |
| Any custom field | Custom field or attribute | Mapping rule path | Per rule | **Configurable (mapping rule)** | Rule-level `create_only` controls whether the field is sent on update. Exposed values include `payout_date`, `original_payout_date`, `calculated_fees_paid`, fund, campaign, fundraiser, pledge and payout attributes, and the transaction's custom fields |

## **Picklist Values**

### **StageName (Opportunity Stage)**

**Export.** The StageName written is the configured stage setting for the transaction's status:

| WeGive Transaction Status | Salesforce StageName Setting |
| :- | :- |
| Successful | `stage_success` |
| Processing (card, PayPal, or ACH with `send_processing_ach_as_success` enabled) | `stage_success` |
| Processing ACH (bank) with `send_processing_ach_as_success` disabled | `stage_pending` |
| Refunded | `stage_refunded` |
| Failed | `stage_failed` |
| Any other status (pending, partially refunded, disputed, etc.) | `stage_pending` |

The stage values themselves are configured in your integration settings to match your Salesforce org's Stage picklist. The StageName is recalculated on every create and update.

**Import.** An Opportunity's StageName is mapped to a WeGive status in this order of precedence:

1. `stage_status_map`, if it contains the StageName
2. The configured `stage_success`, `stage_pending`, `stage_refunded`, `stage_failed` values (checked in that order, so push and pull agree)
3. A built-in fallback list:

| Salesforce StageName | WeGive Status |
| :- | :- |
| Completed, Complete, Posted, Closed Won, Received, Pledged, Fulfilled Pledge, Adjustment | Successful |
| Pending, Prospecting, Planned, Negotiation/Review | Pending |
| Refunded | Refunded |
| Anything else | Failed |

<Tip>
  If your org uses a non-standard StageName for successful gifts and it is not one of your `stage_*` settings, add it to `stage_status_map` so it is not imported as Failed.
</Tip>

***

## **Important Notes**

### **Amount Calculation**

When exporting to Salesforce, the Opportunity Amount is calculated as `(amount - fee) / 100` to show the net donation amount in dollars. WeGive stores amounts in cents internally, so the division by 100 converts to the dollar amount expected by Salesforce.

**Example:** If a donor gives \$100 with a \$3 processing fee:

* WeGive stores: amount = 10000 (cents), fee = 300 (cents)
* Salesforce receives: Amount = \$97.00 (net donation)

On import, the Salesforce dollar amount is multiplied by 100 and rounded to the nearest cent.

### **Automatic Name Generation**

If no mapping rule supplies a name when creating an Opportunity, WeGive generates one using the format `{donor name} {MM-YY}`:

* "John Smith 01-24"
* "ABC Corporation 12-23"

### **Recurring vs One-Time Donations**

The `Type` field is automatically determined based on the transaction's relationship to a recurring donation:

* **Type = "Recurring"** - Transaction has a `scheduled_donation_id`
* **Type = "One-Time"** - Transaction has no `scheduled_donation_id`

### **Tribute/Honoree Logic**

Tribute fields are populated on create only:

* If tribute information exists, `npsp__Tribute_Type__c` is set to "Honor"
* `npsp__Honoree_Name__c` contains the honoree name (null when there is no tribute)

### **Record Type Assignment**

On export, the `RecordTypeId` is assigned from the transaction's `is_tax_deductible` flag:

* Tax-deductible: `tax_deductible_record_type_id`, or if unset, the Record Type named "Donation"
* Non-tax-deductible: `service_revenue_record_type_id`, or if unset, the Record Type named "Service Revenue"
* If neither resolves, no Record Type is sent

On import, an Opportunity whose Record Type developer name is in `service_revenue_record_types` is marked not tax-deductible, and one in `hidden_record_types` is marked hidden, unless a mapping rule supplies those fields directly.

### **Create-Only Fields**

The following defaults are only set when creating a new Opportunity:

* `Name`, `LeadSource`, `AccountId`, `ContactId`
* `npsp__Tribute_Type__c`, `npsp__Honoree_Name__c`
* `npe01__Do_Not_Automatically_Create_Payment__c`

Mapping-rule fields are create-only when the rule's `create_only` flag is set.

### **Update Behavior**

When updating an existing Opportunity, the default payload contains:

* `CloseDate`, `CampaignId`, `StageName`, `npe03__Recurring_Donation__c`, `Type`, `Amount`
* `RecordTypeId` when one resolves

plus any mapping-rule fields not flagged create-only.

***

## **Opportunity Matching & Create/Update Logic**

### **Step 1: Check for Existing Salesforce Opportunity ID**

* **If `salesforce_id` exists:** UPDATE the existing Opportunity
* **If not:** acquire a per-transaction lock (to prevent duplicate creation by concurrent jobs), then continue

### **Step 2: Recurring Installment Matching**

If the transaction belongs to a recurring donation that already has a Salesforce ID, the integration looks for an existing Opportunity on that Recurring Donation with `StageName = 'Pledged'`. If one exists, it is adopted and updated instead of creating a new Opportunity. With `uses_payments`, an existing Payment on that Opportunity is adopted as well.

### **Step 3: Create**

Otherwise a new Opportunity is inserted and its ID stored on the transaction.

### **Why This Matters**

Unlike Contacts and Accounts, Opportunities are **not** matched by email, name, or other identifying information. Apart from the Pledged installment match above, each transaction creates a unique Opportunity unless it already has a Salesforce ID stored.

<Warning>
  If a transaction loses its `salesforce_id` reference in WeGive, it will create a duplicate Opportunity in Salesforce on the next sync. Always maintain the Salesforce ID relationship for transactions.
</Warning>

### **Legacy Single Allocation**

When `enable_fund_allocations` is off, the transaction has a fund, and `fund_api_name` is not set, the integration creates or updates a single `npsp__Allocation__c` linking the Opportunity to the fund's GAU (adopting an NPSP-created default allocation if one already exists). See the GAU & Allocation page.

# **Payment (npe01\_\_OppPayment\_\_c) - Field Mapping**

**Salesforce Object:** npe01\_\_OppPayment\_\_c<br />**WeGive Model:** Transaction (when uses\_payments = true)

## **How Payment Data Syncs**

Payments are only created when the integration setting `uses_payments` is enabled.

***

## **Sync Triggers**

### **From WeGive to Salesforce (Export)**

Payment data is exported alongside the Opportunity when a transaction is created or updated in WeGive and `uses_payments` is enabled.

### **From Salesforce to WeGive (Import)**

When `uses_payments` is enabled, the transaction pull queries `npe01__OppPayment__c` records where `npe01__Paid__c = TRUE` and either the Payment or its Opportunity was modified since the last sync. Unpaid Payments are never imported. Each imported Payment becomes (or updates) one WeGive transaction, matched by `salesforce_payment_id`, so an Opportunity with several paid Payments produces several WeGive transactions.

***

## **Sync Process Overview**

### **Pulling Data from Salesforce**

The Payment pull reads `Id`, `CreatedDate` and `npe01__Payment_Amount__c` from the Payment, plus the parent Opportunity's `StageName`, `RecordTypeId`, `ContactId`, `AccountId`, `CampaignId`, `npe03__Recurring_Donation__c` and `npe01__Is_Opp_From_Individual__c`. Opportunity-level mapping rules are applied to the parent Opportunity and Payment-level mapping rules to the Payment; when both map to the same WeGive field, the Opportunity value wins. Other Payment fields (date, method, paid flag) are imported only if a Payment-level mapping rule maps them.

<Note>
  GAU Allocations cannot be fetched during a Payment-based pull. Allocations for these orgs are reconciled by the separate allocation pull described on the GAU & Allocation page.
</Note>

### **Pushing Data to Salesforce**

The Payment payload includes:

* **Payment Amount:** Net amount after fees, in dollars
* **Payment Date:** Transaction date, `Y-m-d` in the organization timezone
* **Payment Method:** From the payment method name settings (see Picklist Values)
* **Paid flag:** Based on transaction status (see Payment Status Logic)
* **Processing Details:** Fee, fee covered amount, payout and card details are available to Payment mapping rules

The Payment is linked to its parent Opportunity via `npe01__Opportunity__c` on create.

### Payment Field Mappings

| Salesforce Field | WeGive Field | WeGive API Field | Direction | Type | Notes |
| :- | :- | :- | :- | :- | :- |
| npe01\_\_Payment\_Amount\_\_c | Payment Amount | `amount` | Both Ways | **Hard-coded** | Export: (amount - fee) / 100. Import: value x 100 becomes the transaction amount |
| npe01\_\_Payment\_Date\_\_c | Payment Date | `created_at` | Export to Salesforce | **Hard-coded** | `Y-m-d` in the organization timezone. Import only via a Payment mapping rule |
| npe01\_\_Payment\_Method\_\_c | Payment Method | `source_type` | Export to Salesforce | **Configurable** | See Picklist Values. Import only via a Payment mapping rule |
| npe01\_\_Paid\_\_c | Paid | Dynamic | Export to Salesforce | **Hard-coded** | See Payment Status Logic. Always overrides any mapping rule value. Pull filter requires TRUE |
| npe01\_\_Opportunity\_\_c | Opportunity ID | `salesforce_id` | Export to Salesforce | **Hard-coded** | Create only |
| npsp\_\_Batch\_Number\_\_c | Payout ID | `payout_id` | Export to Salesforce | **Configurable (mapping rule)** | Removed when `is_legacy` |
| npsp\_\_Gateway\_Payment\_ID\_\_c | WeGive Transaction ID | `id` | Export to Salesforce | **Configurable (mapping rule)** | Removed when `is_legacy` |
| npsp\_\_Total\_Transaction\_Fees\_\_c | Transaction Fee | `fee_amount` | Export to Salesforce | **Configurable (mapping rule)** | Dollars. Removed when `is_legacy` |
| npsp\_\_Donor\_Cover\_Amount\_\_c | Fee Covered Amount | `fee_covered_amount` | Export to Salesforce | **Configurable (mapping rule)** | Dollars; 0 when the donor did not cover fees. Removed when `is_legacy` |
| npsp\_\_Card\_Last\_4\_\_c | Card Last 4 Digits | `paymentMethod.last_four` | Export to Salesforce | **Configurable (mapping rule)** | From the transaction's payment method |
| npsp\_\_Card\_Network\_\_c | Card Network | `paymentMethod.issuer` | Export to Salesforce | **Configurable (mapping rule)** | From the transaction's payment method |

Other values exposed to Payment mapping rules: `payout`, `payout_date`, `original_payout`, `original_payout_date`, `fund`, `calculated_fees_paid`, `calculated_fees_paid_dollars`, and the transaction's custom fields. Whether a rule field is create-only depends on the rule's `create_only` flag.

## **Picklist Values**

### **npe01\_\_Payment\_Method\_\_c (Payment Method)**

The Payment Method value is taken from three integration settings keyed by the transaction's payment source:

| WeGive Payment Source (`source_type`) | Salesforce Payment Method |
| :- | :- |
| card | `card_payment_method_name` |
| bank | `bank_payment_method_name` |
| paypal | `paypal_payment_method_name` |

If the resolved name is blank, the integration falls back on the transaction's `payment_type`: `check` writes "Check" and `cash` writes "Cash". Any other combination leaves the field empty. There are no other built-in values; set the three name settings to values that exist in your org's Payment Method picklist.

<Note>
  The same three settings drive `npsp__PaymentMethod__c` on Recurring Donations, so both objects carry the same vocabulary. NPSP Enhanced Recurring Donations copies the Recurring Donation's payment method onto installment Payments, so a mismatch would surface as a picklist error on the Payment.
</Note>

***

## **Important Notes**

### **When Payments Are Created**

Payment records are **only** created when `uses_payments = true`. When disabled, all transaction data goes into the Opportunity record only.

**When to Enable `uses_payments`:**

* You want detailed payment tracking separate from donation commitments
* You want to use NPSP's payment rollup features
* You need payment-level reporting

**When to Disable `uses_payments`:**

* You prefer one record per donation
* Your organization does not use NPSP's payment features
* You rely on the allocation subquery during transaction pulls

### **Payment Status Logic**

The `npe01__Paid__c` flag is set from the transaction status and always overrides any mapping rule value:

| Transaction Status | npe01\_\_Paid\_\_c |
| :- | :- |
| successful | true |
| refunded | true |
| partially refunded | true |
| disputed | true |
| processing (card, PayPal, or ACH with `send_processing_ach_as_success` enabled) | true |
| processing ACH (bank) with `send_processing_ach_as_success` disabled | false |
| pending, failed, any other status | false |

Marking a still-pending Payment as paid would trigger NPSP automation that closes the Opportunity and syncs back as successful, which can prevent a scheduled charge from running. The integration therefore only sends `true` when money has actually moved.

### **Legacy Integration Note**

When `is_legacy` is enabled, the following fields are removed from the Payment payload:

* `npsp__Donor_Cover_Amount__c`
* `npsp__Batch_Number__c`
* `npsp__Gateway_Payment_ID__c`
* `npsp__Total_Transaction_Fees__c`

### **Create-Only Fields**

`npe01__Opportunity__c` is only set on create. Mapping-rule fields are create-only when the rule's `create_only` flag is set.

### **Update Behavior**

When updating an existing Payment, the default payload contains `npe01__Paid__c`, `npe01__Payment_Amount__c`, `npe01__Payment_Date__c` and `npe01__Payment_Method__c`, plus any mapping-rule fields not flagged create-only.

***

## **Payment Matching & Create/Update Logic**

### **Step 1: Check for Existing Salesforce Payment ID**

* **If `salesforce_payment_id` exists:** UPDATE the existing Payment
* **If not:** INSERT a new Payment linked to the Opportunity and store its ID

When a recurring installment adopts an existing Pledged Opportunity (see above), the first Payment already on that Opportunity is adopted too.

### **Why This Matters**

Payments are matched only by stored Salesforce Payment ID. If a transaction loses its `salesforce_payment_id` reference in WeGive, a duplicate Payment is created on the next push.

## Related Documentation

* [Data Mapping Overview](./overview) - object index and cross-cutting data conventions
* [Recurring Donation](./recurring-donation) - how installment Opportunities link to Recurring Donations
* [GAU & Allocation](./gau) - fund allocations on Opportunities
* [Soft Credits](./soft-credit) - soft credits on Opportunities

*Verified against the integration source, September 2026.*


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