Skip to main content
When a donor gives a gift in CRM+, that gift is allocated to one or more specific purposes. This page covers the three-layer model that connects a Gift to those purposes: GiftDesignation (the allocation), Project (the destination), and Campaign (the organizing context).

Terminology bridge

If you are coming from another nonprofit platform (Blackbaud Raiser’s Edge, DonorPerfect, Salesforce NPSP, NetSuite), you may know this concept as a “fund.” In Virtuous, the equivalent resource is the Project.
Other platformsVirtuous
FundProject
Fund designation / Gift allocationGiftDesignation
Appeal / CampaignCampaign
The page title uses “Funds” because that is the partner-recognizable term, but every endpoint and field in the API uses Project. The rest of this page uses the Virtuous terminology.

The three-layer model

Each layer answers a different question about a donation:
  • Project answers “what does this gift fund?” — a specific program, initiative, or operational purpose.
  • GiftDesignation answers “how much of this gift goes to that purpose?” — the split. A gift can fund multiple projects with separate amounts.
  • Campaign answers “what fundraising effort is this gift part of?” — the time-bound context for reporting and analysis.

Projects — the funding destination

A Project is a fundable purpose. It has a name, a code, balances, and a set of flags controlling its visibility and behavior. A typical Project record:
{
  "id": 311,
  "name": "Clean Water Initiative",
  "projectCode": "CLEAN-WATER",
  "externalAccountingCode": "5101-001",
  "onlineDisplayName": "Clean Water",
  "type": "Program",
  "location": "International",
  "isPublic": true,
  "isActive": true,
  "isAvailableOnline": true,
  "isTaxDeductible": true,
  "currentBalance": 47823.50,
  "lifeToDateGiving": 285301.00,
  "lifeToDateGiftCount": 1247
}

Project codes — the partner integration’s anchor

Three fields can identify a Project in API calls:
FieldTypeUse
idintegerVirtuous’s internal Project ID. Unique within an organization.
projectCodestringThe organization’s short code for the Project (e.g., "CLEAN-WATER"). Often more stable across system migrations than the numeric ID.
externalAccountingCodestringThe Project’s accounting-system code (often the GL account number). Used for reconciliation with the nonprofit’s accounting software.
For partner integrations, projectCode is usually the right reference. It is human-readable, it can be configured to match your platform’s identifier for the same fund, and it stays stable even if Virtuous database IDs change in unusual recovery scenarios. The GiftDesignation accepts projectCode directly:
{
  "giftDesignations": [
    { "projectCode": "CLEAN-WATER", "amountDesignated": 300.00 },
    { "projectCode": "EDUCATION",    "amountDesignated": 200.00 }
  ]
}

Project lifecycle flags

Four boolean flags determine whether a Project is currently usable for gift designation:
FlagWhat it controls
isActiveWhether the Project accepts new designations. An inactive Project can still hold historical gifts but cannot be designated to on new gifts.
isPublicWhether the Project is visible in the organization-wide Project list. Internal Projects are excluded from most reports.
isAvailableOnlineWhether the Project can be designated to from a public donation form.
isTaxDeductibleWhether designations to this Project are tax-deductible for the donor. Affects receipt generation.
Partner integrations submitting gifts should respect isActive — designating to an inactive Project will produce a 400 or 422 error from the API. The defensive pattern is to query for active Projects at integration setup and surface them to your customer for mapping.

Sub-projects

Projects can have a parent-child hierarchy through the parentId field. Sub-projects roll up to their parent for reporting purposes — giving to “Clean Water → Sub-Saharan Africa” is also counted toward “Clean Water” totals.
FieldDescription
parentIdThe parent Project’s ID, if this is a sub-project.
parentNameThe parent’s display name.
isSubProjecttrue if this Project has a parent.
For partner integrations, the hierarchy is mostly transparent — designate to the most specific Project (the sub-project), and Virtuous handles the rollup automatically.

Reading Projects

Three patterns for discovering Projects in your integration:
EndpointWhen to use
GET /api/Project/{projectId}Look up one Project by Virtuous ID.
GET /api/Project/Code/{projectCode}Look up by projectCode — useful when your platform stores the code rather than the numeric ID.
POST /api/Project/QueryFiltered paginated retrieval. Filter by isActive: true and isPublic: true to get the set of Projects valid for new gift designations.
GET /api/Project/{projectId}/Balance returns the current balance and giving totals for a specific Project — useful for displaying progress in a donor portal or partner dashboard.

Campaigns — the organizing context

A Campaign is a time-bound fundraising effort that groups Projects together. “Year-End Giving 2024”, “Capital Campaign Phase II”, “Giving Tuesday 2024” — each is a Campaign that combines one or more Projects toward a unified goal. A typical Campaign record:
{
  "campaignId": 22,
  "name": "Year-End Giving 2024",
  "startDateTimeUtc": "2024-11-01T00:00:00Z",
  "endDateTimeUtc": "2024-12-31T23:59:59Z",
  "givingGoal": 250000,
  "newGiverGoal": 100,
  "totalGiftGoal": 800,
  "isArchived": false
}
Campaigns are referenced indirectly by Gifts — through the Projects in their GiftDesignations. A gift designated to a Project that belongs to “Year-End Giving 2024” is part of that Campaign for reporting purposes.
Campaigns are read-only through the CRM+ API. The API exposes GET /api/Campaign/{campaignId}, POST /api/Campaign/Query, and GET /api/Campaign/QueryOptions — but there is no POST /api/Campaign, no PUT /api/Campaign/{campaignId}, and no DELETE /api/Campaign/{campaignId}.Partners cannot create Campaigns programmatically. If your integration needs a new Campaign, direct the nonprofit administrator to create it in the Virtuous UI under Campaigns, then reference its Projects in your gift submissions.

Campaign steps

Some Campaigns are structured as a sequence of activities or touchpoints (a “campaign plan”). GET /api/Campaign/GetStepsByCampaignId/{campaignId} returns the steps defined for a Campaign. Most partner integrations do not need to interact with campaign steps directly.

GiftDesignations — the allocation

A GiftDesignation records the allocation of a portion of a Gift to a specific Project. Every Gift has at least one designation. The total of all designation amounts must equal the Gift’s amount.
FieldTypeDescription
idintegerThe unique designation ID. Created when the Gift is recorded.
projectIdintegerReference to the funded Project.
projectstringDisplay name of the Project (read-only).
projectCodestringOrganization’s short code (read-only on response). On request, can be used in place of projectId.
externalAccountingCodestringThe Project’s accounting code (read-only on response).
amountDesignatednumberThe portion of the Gift allocated to this Project.

Split donations

A donor giving $500 split across two Projects produces a Gift with two designations:
{
  "amount": 500.00,
  "giftDesignations": [
    { "projectCode": "CLEAN-WATER", "amountDesignated": 300.00 },
    { "projectCode": "EDUCATION",    "amountDesignated": 200.00 }
  ]
}
The API rejects gifts where designation amounts don’t sum to the gift amount — the validation runs synchronously on Gift Transaction submissions and returns a 400 if the totals don’t match.

Single-Project gifts

The far more common case is a single designation for the full gift amount:
{
  "amount": 500.00,
  "giftDesignations": [
    { "projectCode": "CLEAN-WATER", "amountDesignated": 500.00 }
  ]
}
If your platform captures a single fund per donation, always submit one designation for the full amount. Do not omit giftDesignations — gifts without designations are rejected.

Reading designations

EndpointUse
POST /api/GiftDesignation/QueryFiltered retrieval of designation records — useful for reporting on giving by Project across many gifts.
GET /api/GiftDesignation/QueryOptionsDiscover the filter parameters and operators available for GiftDesignation queries.
Designations are also embedded in Gift responses (giftDesignations array on the Gift), so most workflows don’t need to query designations independently.

Segments

A Segment is a related concept worth a brief mention here even though it is not a Project or Campaign. Segments are groupings of Contacts (e.g., “Major Donors”, “Lapsed Givers”, “Board Members”) used for outreach targeting and campaign association. Unlike Projects and Campaigns, Segments are Contact-centric — they answer “who” rather than “what” or “when.” Endpoints:
EndpointUse
GET /api/Segment/{segmentId}Retrieve one Segment.
GET /api/Segment/Code/{segmentCode}Look up by Segment code.
POST /api/SegmentCreate a Segment.
PUT /api/Segment/{segmentId}Update a Segment.
Gifts can carry a segment (or segmentCode) field to associate the gift with a specific Segment for attribution and reporting. Some Campaign workflows use Segments to identify which donors received a particular appeal.

Partner integration patterns

A few common patterns for partner integrations touching this layer of the model:

Pattern 1: Static Project mapping

For partners with a fixed set of fund options (e.g., a peer-to-peer platform where donors choose from a curated list), the cleanest pattern is:
  1. At integration setup, present the customer with the list of active Projects (POST /api/Project/Query filtered to isActive: true).
  2. Store a mapping from your platform’s fund options to Virtuous Project codes.
  3. On each gift, look up the mapping and submit the gift with the appropriate projectCode in giftDesignations.

Pattern 2: Dynamic Project sync

For partners that need full visibility into all Projects (e.g., reporting integrations, accounting reconciliation), sync the full Project list:
  1. Run POST /api/Project/Query with take=1000 and paginate until exhausted.
  2. Filter for isActive and isPublic as needed.
  3. Subscribe to webhooks for Project changes if available, or re-sync periodically.

Pattern 3: Code-as-bridge

For partners working with the customer’s accounting system, use externalAccountingCode as the bridge:
  1. Your accounting integration has GL account codes.
  2. Virtuous Projects are configured with matching externalAccountingCode values.
  3. Submit gifts using the externalAccountingCode as a reference; reconciliation between the two systems happens on that code.

Where to go next

Donations / Gifts

The Gift resource and how designations connect a gift to projects.

Transactions

How designations are resolved during the nightly batch — including code-based lookups.

Custom Fields

Projects have their own custom fields — use them to store partner-specific metadata.

Create a Donation

A working example of recording a Gift with one or more designations.
Last modified on May 21, 2026