This recipe describes patterns that apply across the fundraising-platform category. Specific platforms (Classy, GiveLively, Donorbox, Bonterra, GoFundMe Charity, and others) have their own API shapes, event names, and data models — confirm against the specific platform’s current documentation when implementing.
Architecture
Three parallel sync paths flowing from the same source events:- Contact sync ensures both the donor and the fundraiser exist as Virtuous Contacts.
- Gift sync records the donation with the fundraiser-aware designation and references.
- Relationship sync (optional) creates Relationship records connecting donors to the fundraisers who recruited them — useful for fundraising-effectiveness reporting.
Field mapping
The three participants in a fundraiser donation
| Participant | Role | Virtuous representation |
|---|---|---|
| Donor | The person who gave the money. | Contact with referenceSource: "FundraisingPlatform" and referenceId = the platform’s donor ID. |
| Fundraiser | The individual or team whose page or campaign drove the gift. | Contact (if they’re a person) or organization Contact (if a team). |
| Nonprofit | The customer’s organization receiving the gift. | The Virtuous organization the integration writes to. Always the same; no per-gift mapping needed. |
Gift fields with fundraiser context
| Virtuous field | Source |
|---|---|
transactionSource | "FundraisingPlatform" |
transactionId | The platform’s unique donation ID |
contact.referenceId | The donor’s platform ID (used for matching against existing Contact) |
amount | The amount the donor pledged (gross, before platform fees) |
giftDate | When the donor’s payment processed |
giftType | Typically "Credit" for card payments through the platform |
giftDesignations[].projectCode | Maps to a Virtuous Project — see “Campaign mapping” below |
| Custom field or note | The fundraiser’s Contact ID — captured so Virtuous reporting can attribute the gift to them |
Campaign and Project mapping
The fundraising platform’s campaign concept needs to map to a Virtuous Campaign + Project hierarchy:| Source concept | Virtuous mapping |
|---|---|
| Platform Campaign (e.g., “2024 Annual Marathon”) | Virtuous Campaign |
| Platform Subcampaign or Fund (e.g., “Education program within the marathon”) | Virtuous Project (designation target) |
| Platform fundraiser page | Not directly modeled — captured via fundraiser Contact reference |
projectCode for each donation.
Step 1: ensure both Contacts exist
When a donation event arrives, your integration first ensures both the donor and the fundraiser have Virtuous Contacts. The donor is straightforward; the fundraiser needs more care because they may already be a known supporter, staff member, or board member.The donor
The standard Create a Contact pattern with the fundraising platform as the reference source:JavaScript
The fundraiser
Fundraisers are typically existing supporters of the nonprofit — staff, board members, regular donors who chose to set up a page, or community members. Try harder to match them against existing Contacts than for donors:JavaScript
- Multi-step lookup before creating. Fundraisers are far more likely than random donors to already exist in Virtuous.
- Email is the secondary key. A fundraiser who’s also a regular donor will have an email match even when the platform reference isn’t yet captured.
- The
Fundraisertag lets the customer’s team segment fundraisers in reporting without needing a custom field.
Teams as Contacts
If the fundraising platform supports team fundraising, the team itself is typically modeled as an Organization-type Contact:JavaScript
Step 2: submit the Gift with fundraiser context
The Gift Transaction records the donation. The challenge: standardPOST /api/v2/Gift/Transaction doesn’t have a built-in field for “this gift was credited to fundraiser X.” Two patterns work:
Pattern A: custom field on the Gift
If the customer has configured a Gift custom field for fundraiser attribution (e.g., a field called “Fundraiser Contact ID”), include it on the Transaction:JavaScript
"Fundraiser Contact ID" Is X to find all gifts credited to a specific fundraiser.
Pattern B: ContactNote with fundraiser linkage
If the customer doesn’t have Gift custom fields configured, record the fundraiser context as a ContactNote on the donor:JavaScript
Step 3: create the donor-fundraiser Relationship (optional)
For customers who want to track donor-fundraiser relationships explicitly — useful for stewardship workflows like “send a thank-you to the donor’s fundraiser when the donor gives again” — create a Virtuous Relationship record linking them:JavaScript
- The relationship type must already be configured in the customer’s Virtuous organization. Your integration cannot create relationship types via API. Discover the configured types via
GET /api/Relationship/Typesand gracefully skip relationship creation if the expected type isn’t present. - The relationship has no expiration — once created, it persists. This is usually what customers want, but for stewardship purposes it can produce confusing reporting if a donor was recruited five years ago but has been giving directly ever since. Consider whether your integration also tracks “most recent recruiter” separately, perhaps as a custom field that gets updated on each gift.
Step 4: handle event-tied fundraisers
Many fundraising platforms organize fundraisers around events (charity 5Ks, walk-a-thons, gala registrations with fundraising). The event itself is a separate entity that the gift, fundraiser, and donor should all link to. In Virtuous, events are first-class records (POST /api/Event and the eventCreate webhook). The recommended modeling:
| Source concept | Virtuous representation |
|---|---|
| The event (e.g., “2024 Charity 5K”) | Virtuous Event record |
| The Campaign for the event | Virtuous Campaign linked to the Event |
| Each fundraiser page tied to the event | Fundraiser Contact, optionally tagged with the event name |
| Each donation through a fundraiser | Gift designated to the Event’s Project; custom field links to fundraiser |
| Event registration (the ticket portion) | Separate Gift with appropriate gift type — see Auction/Event Platform recipe |
JavaScript
originSegmentCode on the Contact Transaction or a tag update) so segmentation works at the Contact level too.
Common edge cases
A fundraiser is also a donor
The same person might run a fundraising page and donate through someone else’s page. The patterns above handle this correctly —Contact/Find will return the same Contact in both cases, and the Fundraiser tag plus the donor’s giving history both attach to that single Contact.
A donor gives anonymously
Some platforms support anonymous donations — the donor’s identity is hidden from the fundraiser but the platform still passes it to the nonprofit. Submit the Contact Transaction normally (the nonprofit needs the donor record for tax receipting) but consider tagging the Contact with"Anonymous Through Fundraiser" so the customer’s team knows the donor doesn’t want to be publicly thanked.
Platform fees
Most platforms deduct a fee before the nonprofit receives the gift. Three handling options:- Gross with custom field: record
amountas the donor’s pledged amount, record the fee in a custom field. Most accurate for donor reporting. - Net: record only the amount the nonprofit received. Simpler but loses the donor’s intent.
- Two-Gift split: record the gross amount and a separate offsetting “Platform Fee” gift. Most complex but mirrors what an accountant would book.
Pledged-but-not-yet-paid
Some fundraising platforms support pledges (e.g., “I’ll give $1,000 if you reach your goal”). These are commitments, not collected money — record them as Virtuous Pledges, not Gifts, until the actual payment processes. Pledges have their own endpoint family (/api/v2/Pledge/*) outside the scope of this recipe.
A team gift
A team itself may receive a gift directly (someone donates “to the team” rather than to an individual fundraiser on the team). Submit the Gift with the team’s Organization-type Contact as the recipient:JavaScript
Production readiness checklist
- Both donor and fundraiser have Virtuous Contacts before the Gift is submitted.
- Fundraiser lookup tries platform reference, then email, before creating a new Contact.
- Campaign-to-Project mapping is configured at integration setup time, not inferred at runtime.
- Gift custom fields (or fallback ContactNotes) capture the fundraiser context.
- Donor-fundraiser Relationships are created only when the corresponding relationship type is configured in Virtuous.
- Platform fees are handled per the customer’s chosen pattern (gross + custom field is recommended).
- Event-tied fundraisers link to the appropriate Virtuous Event and Campaign.
- Anonymous donations are tagged so the customer’s team doesn’t surface them publicly.
- Reconciliation queries periodically check that submitted donations resulted in Gifts attributed to the right fundraiser.
Where to go next
Auction/Event Platform to Virtuous CRM
Event-specific patterns — ticket-vs-donation splitting, auction items, sponsorships.
Stripe to Virtuous CRM
The payment-processor recipe that powers most fundraising platforms under the hood.
Build a Two-Way Sync
Extend this one-way recipe with bidirectional sync if the customer wants Virtuous-side changes reflected back.
Relationships and IDs
The Relationship endpoints and lifecycle behavior used in Step 3.