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

# Gift Mapping

> How WeGive transactions map to Virtuous gifts, including the batch and real-time push paths and pull behavior

# Gift Mapping

WeGive **Transactions** map to Virtuous **Gifts**. There are two push paths with slightly different payload shapes — a **batch** importer and a **real-time** single-gift path — plus a pull path. This page documents each exactly.

## Which transactions are sent

Before any push, the integration decides whether a transaction should go to Virtuous:

| Transaction status | Sent? | Amount sent |
| - | - | - |
| `success` | Always | `amount / 100` |
| `processing` | Yes, **unless** payment type is unknown, or it's ACH (`bank`) and `send_processing_ach_as_success` is off | `amount / 100` |
| `failed` / `refunded` | Only if it already has a real Gift ID (not a `btch_*` batch ID) | `0` (zeroes out the existing gift) |
| anything else | No | — |

## Push — batch path

The batch importer sends transactions to `POST v2/Gift/Transactions` in chunks of **100**, with `createImport: true`. Each transaction becomes one entry:

| Virtuous field | Source | Notes |
| - | - | - |
| `contact.id` | `owner.virtuous_contact_id` | The parent Contact |
| `contactIndividualId` | `owner.virtuous_contact_individual_id` | Only if set |
| `amount` | `amount / 100` | `0` for failed/refunded |
| `giftDate` | `created_at` in the destination's timezone | `Y-m-d` |
| `description` | `description` | |
| `notes` | `supporter_inputted_notes` | |
| `isTaxDeductible` | `is_tax_deductible` | |
| `isPrivate` | `anonymous` | |
| `designations` | fund / fund allocations | `[{ id: <project virtuous_id>, amountDesignated: <amount/100> }]` |
| `segmentId` / `segment` / `segmentCode` | campaign's Virtuous segment + its code | |
| `recurringGiftTransactionId` | `scheduledDonation.virtuous_id` | Links to the recurring gift |
| `customFields` | `{ "wg_id": <transaction.id> }` | Object form (batch only) |
| `giftType` | see below | |

After a successful batch send, each transaction's `virtuous_id` is set to a synthetic batch ID like `btch_WeGive_Import` (not a real Gift ID).

## Push — real-time single path

When `real_time` is enabled, individual transactions are sent to `POST Gift` (and updated with `PUT Gift/{id}`). The payload is similar but **the shapes differ from the batch path**:

| Virtuous field | Source | Notes |
| - | - | - |
| `contactId` | `owner.virtuous_contact_id` | |
| `contactIndividualId` | `owner.virtuous_contact_individual_id` | Only if set |
| `amount` | `amount / 100` | |
| `giftDate` | `created_at` in destination timezone | `Y-m-d` |
| `description` | `description` | |
| `notes` | `supporter_inputted_notes` | |
| `isTaxDeductible` | `is_tax_deductible` | |
| `isPrivate` | `anonymous` | |
| `giftDesignations` | fund / fund allocations | `[{ projectId: <project virtuous_id>, amount: <amount/100> }]` |
| `segmentId` / `segment` | campaign's Virtuous segment + code | |
| `recurringGiftPayments` | `[{ id: <recurring gift id>, amount }]` | Only if linked to a scheduled donation |
| `customFields` | `[{ "name": "wg_id", "value": <transaction.id> }]` | Array form (real-time only) |
| `giftType` | see below | |

On create, the returned Gift `id` is stored as the transaction's `virtuous_id`. On update, the integration `GET`s the existing gift, overwrites the WeGive-owned fields (amount, description, segment, tax/private flags, notes, designations, custom fields), and `PUT`s it back. Designation updates use Virtuous's **diff protocol**: every existing designation is marked `Delete` and the desired set is appended as `Add`, achieving replace semantics.

> The two paths differ deliberately: batch uses `designations` with `{ id, amountDesignated }` and a `customFields` object; real-time uses `giftDesignations` with `{ projectId, amount }` and a `customFields` array.

## Payment method (`giftType`)

`giftType` is set for four payment signals, checked in this order — `payment_type` takes priority over `source_type`. Anything else is sent **without** a `giftType`:

| Signal | Virtuous `giftType` |
| - | - |
| `payment_type === 'check'` | `Check` |
| `payment_type === 'cash'` | `Cash` |
| `source_type === 'card'` | `Credit` |
| `source_type === 'bank'` | `EFT` |
| anything else | *(not set)* |

## Amounts

WeGive stores amounts in cents; Virtuous in dollars. Amounts are divided by 100 on push (and multiplied by 100 on pull). There are no separate `Fee`, `CurrencyCode`, or `GiftStatus` fields in the payload.

## Pull (Virtuous → WeGive)

Gifts are pulled via `POST Gift/Query/FullGift` (1000 per page, filtered by the configured `pull_by` date). Each record is imported as a Transaction:

| WeGive field | Source | Notes |
| - | - | - |
| `virtuous_id` | gift `id` | |
| `amount` | `amount * 100` | Only set when not already present |
| `description` | `description`, else `"Virtuous Import"` | |
| `created_at` | `giftDate` | Midnight dates are stored as `17:00:00` |
| `status` | existing status, else `success` | |
| `is_tax_deductible` | `isTaxDeductible` | |
| `anonymous` | `isPrivate` | |
| `supporter_inputted_notes` | `notes` | |

**Matching:** a pulled gift is matched first by `virtuous_id`, then by the `wg_id` custom field (which links back to the original WeGive transaction); otherwise a new transaction is created.

**Owner resolution:** a company donor (by `virtuous_contact_id`, no individual) is tried first; otherwise the donor is matched by `contactIndividualId`, falling back to the Contact's primary individual.

**Designations:** the owning fund is taken from the first `giftDesignations` entry's `projectId`; the campaign from `segmentId`. When fund allocations are enabled, allocations are reconciled to WeGive from the gift's `giftDesignations` (`projectId` → fund, `amountDesignated * 100` → amount). Recurring-gift linkage is **not** restored on pull.

This reflects the integration as implemented in `app/Integrations/Virtuous.php`.


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