> ## Documentation Index
> Fetch the complete documentation index at: https://docs.virtuous.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Types

> The webhook event types CRM+ delivers — what each event represents, when it fires, and what its payload contains.

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.

<Warning>
  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.
</Warning>

## 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](/crm/concepts/gifts#reversals-and-refunds). |
| 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.                                                                                                        |

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:

```json theme={null}
{
  "eventType": "contact.created",
  "eventId": "evt_abc123",
  "timestamp": "2024-12-15T14:30:00Z",
  "organizationId": 67890,
  "data": {
    "id": 4821,
    "...": "the full resource record"
  }
}
```

<Note>
  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.
</Note>

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](/crm/webhooks/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](/crm/concepts/contacts) for the field reference.

<Tip>
  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.
</Tip>

### `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.

<Tip>
  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`.
</Tip>

### `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).

<Warning>
  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.
</Warning>

***

## 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](/crm/concepts/funds-campaigns-designations#projects-the-funding-destination).

### `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.

<Note>
  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.
</Note>

***

## 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.               |

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.

<Tip>
  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.
</Tip>

***

## Where to go next

<CardGroup cols={2}>
  <Card title="Signature Verification" icon="shield-check" href="/crm/webhooks/signature-verification">
    How to verify that incoming events came from Virtuous before processing them.
  </Card>

  <Card title="Idempotency and Safe Reprocessing" icon="copy" href="/crm/webhooks/idempotency-and-safe-reprocessing">
    Why duplicate event deliveries can occur and how to make your handler safe against them.
  </Card>

  <Card title="Retry Behavior" icon="arrows-rotate" href="/crm/webhooks/retry-behavior">
    What Virtuous does when your endpoint is unavailable or returns non-2xx.
  </Card>

  <Card title="Transactions" icon="arrow-down-to-line" href="/crm/concepts/transactions">
    How `giftCreate` events confirm your Gift Transactions resulted in real records.
  </Card>
</CardGroup>
