isPrivate, isArchived), Projects use a mix of flags (isActive, isPublic, isAvailableOnline), RecurringGifts and Pledges have an explicit status string field, and Gifts have no explicit status at all — their lifecycle is expressed through related records (reversing transactions, pledge payments).
This page maps the lifecycle conventions for each resource and the patterns partner integrations should use to interpret and respect them.
Why lifecycle states matter
Lifecycle states drive three behaviors that any partner integration needs to handle correctly:- Query inclusion or exclusion. Most list endpoints exclude archived records by default. If your sync needs to find deleted records, you must opt in.
- Write acceptance or rejection. Designating a gift to an inactive Project, or creating a payment on a cancelled RecurringGift, will fail.
- Downstream behavior. A private Contact’s data may not be visible to your integration; a deceased ContactIndividual’s email should not receive automated communications.
Contact lifecycle
Contacts use three boolean flags:Archive and unarchive
CRM+ provides dedicated endpoints for archiving and unarchiving Contacts:
These are state transitions, not deletions — the Contact’s data is preserved. Use these rather than
DELETE /api/Contact/{id} when you need a record removed from active use but kept on file.
Including archived records in queries
Handling deceased individuals
When a ContactIndividual hasisDeceased: true:
- Their associated emails and phones should be excluded from outbound communications.
- The household Contact remains active if other living individuals remain.
- The household name typically updates (the deceased individual’s name is removed from joint salutations) but this is managed in the Virtuous UI, not automatically.
isDeceased before sending. The flag is on the ContactIndividual, not the Contact — read it per-individual when iterating a household.
Project lifecycle
Projects expose four lifecycle flags. The combination of values determines whether a Project can accept new gift designations and whether it appears in various views:
For partner integrations submitting gifts: filter to
isActive: true and isPublic: true when presenting Project options to your customer. These are the Projects safe to designate gifts toward.
Temporary inventory status changes
A separatePUT /api/Project/{projectId}/Status endpoint exists for temporarily changing a Project’s inventory status — for example, marking a Project as temporarily unavailable during a fulfillment pause. The endpoint accepts an inventoryStatus value and an optional durationMinutes for an automatic revert.
This is distinct from the long-term isActive flag — inventory status is a short-term override, while isActive is the persistent state. Most partner integrations do not need to call the Status endpoint; it is used for operational pauses rather than ongoing lifecycle management.
The valid
inventoryStatus values are not enumerated in the spec — the parameter is typed as string. Confirm with the Virtuous team before using this endpoint, or restrict your integration to reading the field rather than writing it.Campaign lifecycle
Campaigns have a singleisArchived flag. Archived Campaigns are excluded from most listing endpoints by default but remain readable by campaignId.
startDateTimeUtc, endDateTimeUtc) define the active window. A Campaign whose endDateTimeUtc has passed is still gettable and still associated with its historical gifts, but most workflows would not designate new gifts to a closed Campaign.
RecurringGift lifecycle
RecurringGifts have an explicitstatus field plus a cancelDateTimeUtc timestamp:
The CRM+ spec does not enumerate the valid
status values for RecurringGift — the field is typed as string. Common values include Active, Cancelled, Paused, and Failed, but the authoritative list depends on the organization’s configuration and the platform version. Treat unknown status values defensively in your integration.⚠️ Human input required: Confirm the canonical enum of status values for RecurringGift, and update this page with the authoritative list and what each state means for downstream behavior (e.g., does Paused resume automatically, or require manual reactivation?).Cancelling a RecurringGift
CRM+ provides a dedicated cancellation endpoint:cURL
status becomes Cancelled and cancelDateTimeUtc is set to the current time. Cancellation is not reversible through the API — re-creating a recurring schedule for the donor requires a new POST /api/RecurringGift.
Pledge lifecycle
Pledges have a parallel structure to RecurringGifts — an explicitstatus field plus dedicated state-transition endpoints:
As with RecurringGift, the CRM+ spec does not enumerate the valid Pledge
status values. Common values include Active, Written Off, and Completed, but treat unknown values defensively. Confirm the canonical list with the Virtuous team.Writing off a Pledge
When a donor cannot fulfill a pledge, the pledge is written off rather than deleted. This preserves the historical commitment record while removing the pledge from active obligations:cURL
status: "Written Off" (or equivalent) and historical payment records are preserved.
Gift lifecycle
Gifts do not have an explicitstatus field. A Gift exists once recorded; its “state” is expressed through related records and metadata:
There is no archived-Gift state in the spec. Gifts are immutable once posted and reversals are explicit accounting entries, not state changes.
Timestamps as a temporal lifecycle anchor
Every resource carriescreateDateTimeUtc and modifiedDateTimeUtc fields. These are the foundation of incremental sync workflows:
modifiedDateTimeUtc field updates whenever any field on the record changes — including lifecycle flag changes. This means a single query filtered by modifiedDateTimeUtc > {last_sync} catches all changes regardless of whether they were content edits, status transitions, or archive/unarchive actions.
See Query Contacts by Filters for the full incremental-sync pattern.
Cross-API lifecycle conventions
If your integration spans multiple Virtuous products, note that lifecycle conventions differ:- Raise API uses its own
archivedboolean on most resources and a separate refund flow for gifts. - Volunteer API uses
active/inactiveflags on most resources and a different convention for participation state.
Where to go next
Query Contacts by Filters
Build an incremental sync that picks up lifecycle changes automatically via
modifiedDateTimeUtc.Handle Duplicate Records
Including archived records in deduplication queries.
Sync Recurring Donor Updates
A worked recipe for keeping RecurringGift state synchronized with your platform.
Transactions
The holding state for in-flight Contact and Gift submissions — a lifecycle of its own.