The event types at a glance
| Event | Subscription field | Source resource | Fires when |
|---|---|---|---|
| Contact created | contactCreate | Contact | A new Contact record is created — including from a Contact Transaction batch resolution. |
| Contact updated | contactUpdate | Contact | An existing Contact is modified — manually, via API, or as the result of a matched Contact Transaction. |
| Gift created | giftCreate | Gift | A new Gift record is created — including from a Gift Transaction batch resolution. |
| Gift updated | giftUpdate | Gift | An existing Gift is modified — designation changes, batch reassignments, manual corrections. |
| Gift deleted | giftDelete | Gift | A Gift is removed from the system. Reversals are not deletes — see Donations / Gifts. |
| Project created | projectCreate | Project | A new Project is created. |
| Project updated | projectUpdate | Project | An existing Project is modified — name, code, lifecycle flags, balance. |
| Project deleted | projectDelete | Project | A Project is removed. Rare — usually Projects are archived (isActive: false) rather than deleted. |
| Form submission | formSubmission | Virtuous Form | A donor or constituent submits a Virtuous-hosted form. |
| Contact note created | contactNoteCreate | ContactNote | A new note is added to a Contact. |
| Contact note updated | contactNoteUpdate | ContactNote | An existing note is edited. |
| Contact note deleted | contactNoteDelete | ContactNote | A note is removed from a Contact. |
| Event created | eventCreate | Event | A new program or calendar Event is created. (Distinct from the webhook event itself — confusing but spec-accurate.) |
| Event updated | eventUpdate | Event | An existing program Event is modified. |
| Event deleted | eventDelete | Event | A program Event is removed. |
The general payload shape
While exact schemas are not published, every webhook delivery follows a recognizable shape:- HTTP
POSTto yourpayloadUrl. Content-Type: application/json.- A JSON body that identifies the event, the affected resource, and the change.
The field names shown above (
eventType, eventId, timestamp, organizationId, data) are illustrative of the typical webhook shape — they are not confirmed against the live CRM+ webhook payloads. Treat them as the structure your handler should expect to find something equivalent to, not as the literal field names.⚠️ Human input required: Publish the canonical webhook payload envelope used by CRM+ — including the exact field names for the event type, event ID, timestamp, and resource data, plus any other metadata fields present.- The event type is identifiable from the payload itself, not just from the HTTP request shape. Your handler can route events by inspecting the payload.
- An event identifier is present and unique — used as the idempotency key for safe reprocessing. See Idempotency and Safe Reprocessing.
- A timestamp identifies when the event occurred. Use this for ordering when processing events out of order is possible (e.g., a
contact.updatedarriving before the correspondingcontact.created). - The affected resource is included — partner integrations rarely need to make a follow-up API call to retrieve the resource because the payload already contains it.
Contact events
contactCreate — Contact created
Fires when a new Contact record is created in Virtuous. Sources include:
- Manual creation by a Virtuous user in the UI.
- Direct API calls via
POST /api/Contact. - A Contact Transaction processed during the nightly batch where no existing Contact matched (a brand-new Contact was created from the Transaction).
- A Gift Transaction where the embedded contact data did not match any existing Contact (a new Contact was created alongside the Gift).
contactUpdate — Contact updated
Fires when any field on an existing Contact changes. Sources include:
- Manual edits in the Virtuous UI.
PUT /api/Contact/{contactId}or related update endpoints.- Contact Transaction batch resolution where the incoming data merged into an existing Contact (the existing record was updated, not created).
- Archive or unarchive operations (
PUT /api/Contact/Archive/{contactId}/PUT /api/Contact/Unarchive/{contactId}).
Gift events
giftCreate — Gift created
Fires when a new Gift is recorded. Sources include:
- Direct API calls via
POST /api/Gift. - Gift Transaction batch processing where the Transaction resulted in a real Gift record (the most common partner-integration source).
- Manual gift entry in the Virtuous UI.
- Recurring gift payments that automatically generated a new Gift on schedule.
- Pledge payments processed during the nightly batch.
transactionSource and transactionId fields are present if the Gift originated from a Transaction submission — use this to correlate the event back to your platform’s record.
giftUpdate — Gift updated
Fires when any field on an existing Gift changes. Common sources:
- Designation changes (a Gift split being reallocated across Projects).
- Batch reassignment (moving a Gift from one batch to another).
- Manual corrections to gift type, date, or amount.
giftDelete — Gift deleted
Fires when a Gift is permanently removed from Virtuous. The payload identifies the deleted Gift but does not include the post-deletion record (it no longer exists).
Project events
projectCreate — Project created
Fires when a new Project is added. Sources include manual creation in the Virtuous UI and direct API calls via POST /api/Project. The payload includes the full Project record — see Funds, Campaigns, and Designations.
projectUpdate — Project updated
Fires when any field on an existing Project changes. Most commonly:
- Lifecycle flag changes (
isActive,isPublic,isAvailableOnline,isTaxDeductible). - Balance updates as new gifts are designated.
- Name, code, or accounting code corrections.
projectUpdate to keep their cached Project list current.
projectDelete — Project deleted
Fires when a Project is permanently removed. As with Gifts, deletion is uncommon — Projects are usually archived (isActive: false) rather than deleted.
ContactNote events
ContactNotes are free-text or structured notes attached to a Contact record — typically used to record interactions, donor preferences, or internal observations. The three ContactNote events (contactNoteCreate, contactNoteUpdate, contactNoteDelete) follow the same pattern as Contact events.
Partner integrations that surface donor interaction history (CRMs, communication platforms) may want to subscribe to ContactNote events. Most other integrations can ignore them.
Event events
TheeventCreate, eventUpdate, and eventDelete webhook events refer to Event records — program or calendar events tracked in Virtuous (galas, conferences, volunteer days). These are unrelated to the webhook events themselves, despite the shared terminology.
Partner integrations dealing with event management, attendance tracking, or auction platforms may want to subscribe. Most general donor-sync integrations can ignore them.
Form submission events
formSubmission — form submitted
Fires when a donor or constituent submits a Virtuous-hosted form. The payload includes the form’s submitted field values and any associated Contact or Gift records that were created or matched as a result of the submission.
This event is most relevant for partner integrations that:
- Power donor-facing forms hosted at the nonprofit’s domain.
- Process form submissions for follow-up communication (welcome emails, receipt confirmations).
- Track conversion analytics on form usage.
The
formSubmission event’s payload shape is not documented in the spec. The structure depends on the form’s configured fields, which vary per organization.Choosing which events to subscribe to
A reasonable starting subscription for most partner integrations:| Subscription | Why |
|---|---|
contactCreate, contactUpdate | Keep your donor records synchronized as Contacts are added or edited. |
giftCreate, giftUpdate | The two core gift-side events for any donation sync. |
projectUpdate | Catch lifecycle flag changes on Projects you reference. |
giftDelete and projectDelete if your integration needs to soft-delete records on the partner side when removed from Virtuous. Add contactNote and event family events only if your integration specifically uses them. Skip formSubmission unless your integration is form-aware.
Where to go next
Signature Verification
How to verify that incoming events came from Virtuous before processing them.
Idempotency and Safe Reprocessing
Why duplicate event deliveries can occur and how to make your handler safe against them.
Retry Behavior
What Virtuous does when your endpoint is unavailable or returns non-2xx.
Transactions
How
giftCreate events confirm your Gift Transactions resulted in real records.