Skip to main content
CRM+ delivers 15 event types across five resource families: Contacts, Gifts, Projects, ContactNotes, and Events. Form submissions are a sixteenth, sixth-family event. This page covers what each event represents, when it fires, and the typical structure of its payload.
The CRM+ OpenAPI spec confirms the set of event types (via the boolean toggle fields on the webhook subscription object) but does not publish payload schemas for any individual event. The payload shapes described on this page reflect typical webhook patterns and the related resource schemas. Confirm the exact payload structure with Virtuous engineering before building production handlers.

The event types at a glance

EventSubscription fieldSource resourceFires when
Contact createdcontactCreateContactA new Contact record is created — including from a Contact Transaction batch resolution.
Contact updatedcontactUpdateContactAn existing Contact is modified — manually, via API, or as the result of a matched Contact Transaction.
Gift createdgiftCreateGiftA new Gift record is created — including from a Gift Transaction batch resolution.
Gift updatedgiftUpdateGiftAn existing Gift is modified — designation changes, batch reassignments, manual corrections.
Gift deletedgiftDeleteGiftA Gift is removed from the system. Reversals are not deletes — see Donations / Gifts.
Project createdprojectCreateProjectA new Project is created.
Project updatedprojectUpdateProjectAn existing Project is modified — name, code, lifecycle flags, balance.
Project deletedprojectDeleteProjectA Project is removed. Rare — usually Projects are archived (isActive: false) rather than deleted.
Form submissionformSubmissionVirtuous FormA donor or constituent submits a Virtuous-hosted form.
Contact note createdcontactNoteCreateContactNoteA new note is added to a Contact.
Contact note updatedcontactNoteUpdateContactNoteAn existing note is edited.
Contact note deletedcontactNoteDeleteContactNoteA note is removed from a Contact.
Event createdeventCreateEventA new program or calendar Event is created. (Distinct from the webhook event itself — confusing but spec-accurate.)
Event updatedeventUpdateEventAn existing program Event is modified.
Event deletedeventDeleteEventA program Event is removed.
Each event type is independently toggleable on the webhook subscription. Subscribe only to what your integration needs — fewer subscriptions means less load on your endpoint and clearer signal-to-noise.

The general payload shape

While exact schemas are not published, every webhook delivery follows a recognizable shape:
  • HTTP POST to your payloadUrl.
  • Content-Type: application/json.
  • A JSON body that identifies the event, the affected resource, and the change.
The typical payload structure:
{
  "eventType": "contact.created",
  "eventId": "evt_abc123",
  "timestamp": "2024-12-15T14:30:00Z",
  "organizationId": 67890,
  "data": {
    "id": 4821,
    "...": "the full resource record"
  }
}
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.
What is reliable about the payload regardless of exact field names:
  • 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.updated arriving before the corresponding contact.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).
The payload includes the full Contact record — id, name, contactType, ContactIndividuals, addresses, contact methods, tags, custom fields, and metadata. See Contacts for the field reference.
Because the payload includes the full Contact, your handler does not need to call GET /api/Contact/{contactId} to retrieve details. This is important for high-volume integrations — a follow-up GET would consume rate-limit budget for every event.

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}).
The payload includes the updated Contact record. For change-detection workflows, compare the payload against your stored copy to identify what changed — Virtuous does not publish a “changed fields” diff in the payload.

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.
The payload includes the Gift record with its designations, premiums, contact reference, and metadata. The 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.
For partner integrations that submit Gift Transactions and need to detect outcomes, the giftCreate event is the canonical signal that your Transaction succeeded. Match incoming events to in-flight Transactions by transactionSource + transactionId.

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.
The payload includes the updated Gift record.

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).
Gift deletion is rare in normal operation. Refunds and reversals are handled via POST /api/Gift/ReversingTransaction, which creates a separate offsetting record rather than deleting the original. If your integration receives a giftDelete event, it usually indicates manual administrative action — flag these in your sync logs for review.

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.
Partner integrations that present Project options to customers should subscribe to 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

The eventCreate, 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:
SubscriptionWhy
contactCreate, contactUpdateKeep your donor records synchronized as Contacts are added or edited.
giftCreate, giftUpdateThe two core gift-side events for any donation sync.
projectUpdateCatch lifecycle flag changes on Projects you reference.
Add 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.
Subscribing to events you do not process is a common partner mistake — it puts unnecessary load on your endpoint and makes log analysis harder. Start with the minimum set and add subscriptions as needs emerge.

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.
Last modified on May 27, 2026