The Raise webhook event type catalog — the 15 documented event type integers, the resource-group pattern they follow, and the discovery path for the integer-to-label mapping.
The Raise webhook system supports 15 distinct event types. The OpenAPI spec exposes them as an integer enum ([10, 11, 12, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51, 52]) without labels. This page covers what the integer pattern suggests, the discovery path for confirming the labels, and the practical patterns for subscribing to and handling events.
The grouping is striking — five tens (10s, 20s, 30s, 40s, 50s) with three consecutive integers in each group. This pattern almost certainly corresponds to 5 resource families × 3 event actions per family.
⚠️ Spec gap: The Raise OpenAPI spec doesn’t label the EventType enum integers. The pattern suggests resource × action semantics (e.g., 10 = gift created, 11 = gift updated, 12 = gift deleted), but the canonical mapping is not documented.The discovery path below identifies labels by inspecting webhook delivery logs — the eventTypeDisplay field on WebhookLogListModel provides the human-readable label for each integer. Subscribe to a broad set of events on a test webhook, generate sample activity, and read the resulting log entries to learn the labels.
Based on the integer pattern and the Raise data model, the 5 groups likely correspond to:
Integer group
Likely resource family
10, 11, 12
Gifts
20, 21, 22
RecurringGifts
30, 31, 32
Donors
40, 41, 42
Campaigns
50, 51, 52
Pages / Donation Forms
And the three per-family integers likely correspond to lifecycle actions — typically created, updated, deleted or similar. So 10 would be “gift created”, 11 “gift updated”, 12 “gift deleted” — with the same pattern applying to each family.Treat this mapping as a working hypothesis, not as the spec’s contract. The discovery path below confirms it for any specific event integer your integration cares about.
The WebhookLogListModel schema (returned by GET /api/Webhook/log/list and the per-webhook log endpoints) carries both eventType (integer) and eventTypeDisplay (human-readable label). Inspecting log entries reveals the mapping for each integer that has fired in the customer’s environment.
Run this once against a customer’s webhook subscription to learn the integer-to-label mapping:
JavaScript
async function discoverEventTypeLabels(webhookId) { const params = new URLSearchParams({ Take: '500', SortBy: 'createddatetime' }); const response = await fetch( `https://prod-api.raisedonors.com/api/Webhook/${webhookId}/log/list?${params}`, { headers: { Authorization: `Bearer ${process.env.RAISE_API_TOKEN}` } } ); const logs = await response.json(); // Build the integer-to-label map from observed events const mapping = new Map(); for (const log of logs.items) { if (!mapping.has(log.eventType)) { mapping.set(log.eventType, log.eventTypeDisplay); } } return Object.fromEntries(mapping);}const mapping = await discoverEventTypeLabels(123);console.log('Event type labels:', mapping);// Example output:// {// 10: 'Gift Created',// 11: 'Gift Updated',// ...// }
The script returns whatever event types have been delivered through the subscription. For a complete mapping of all 15 event types, the customer’s account needs to have generated activity across all 5 resource families with each action type — which may take time to accumulate naturally.
For most integrations, subscribing to a focused subset is better than subscribing to everything — fewer events to filter, less noise in logs, and clearer integration semantics.
The exact payload shape varies by event type. The Raise OpenAPI spec doesn’t document each event’s payload schema explicitly — the schemas come from inspecting actual deliveries via the log endpoints.In general, partner integrations should expect:
Element
Description
Event type identifier
The integer matching the EventType enum
The triggering resource
The Gift, Donor, RecurringGift, etc. that the event is about, typically as a complete record matching the relevant *Model schema
# 1. Find a recent delivery log for the event type you're interested incurl "https://prod-api.raisedonors.com/api/Webhook/123/log/list?Take=10" \ -H "Authorization: Bearer YOUR_API_TOKEN"# 2. Fetch the specific log's payloadcurl https://prod-api.raisedonors.com/api/Webhook/123/log/456 \ -H "Authorization: Bearer YOUR_API_TOKEN"
The single-log response includes payLoad — the exact body delivered to the partner endpoint. Inspect this to understand the JSON structure for the event types your integration handles.
Tolerate unknown event types. If Raise adds new event types in the future or the customer subscribes to additional types after deployment, your handler should log and skip unknown types rather than throw.
The most common event partners subscribe to — a new donation completed. Typical handlers:
JavaScript
async function handleGiftCreated(payload) { const gift = payload; // 1. Send a thank-you email (if your integration handles donor stewardship) await emailService.sendThankYou(gift.donor.email, { amount: gift.formattedAmount, project: gift.projects[0]?.projectName, }); // 2. Sync to your external system (if your integration is a data pipeline) await externalSystem.recordDonation({ raiseGiftId: gift.id, amount: gift.amount, date: gift.date, donorEmail: gift.donor.email, }); // 3. Alert internal team for major gifts (if applicable) if (gift.amount >= 1000) { await slackNotifier.alert(`Major gift: ${gift.formattedAmount} from ${gift.donor.name}`); }}
A common integration question: when a Gift event fires (event 10, likely “Gift Created”), is the gift one-time or one of a recurring schedule’s payments?The answer is in the Gift payload itself: check the recurringGiftId field.
JavaScript
async function handleGiftCreated(payload) { const gift = payload; if (gift.recurringGiftId) { // This gift is a payment in a recurring schedule await handleRecurringPayment(gift); } else { // This is a one-time donation await handleOneTimeDonation(gift); }}
This pattern matters for thank-you flows — donors signing up for recurring giving typically get a “thanks for signing up for monthly support!” email, while donors making subsequent recurring payments get a lighter-touch acknowledgment. Distinguishing the two cases at the integration level produces a better donor experience.
Webhook events for the same resource are typically delivered in order — a gift created event arrives before a gift updated event for the same gift. But ordering across resources isn’t guaranteed, and rare delivery hiccups can cause out-of-order arrival.Two patterns help:
async function handleGiftUpdated(payload) { const gift = payload; // Check if we've already seen this gift const existing = await db.findByRaiseGiftId(gift.id); if (!existing) { // We're seeing an update before the create — treat as a create await handleGiftCreated(gift); return; } // Normal update flow await db.update(existing.id, gift);}
This pattern handles out-of-order updates by upgrading the update to a create if needed.
When an update event arrives for a record you already have, compare timestamps before applying:
JavaScript
async function handleGiftUpdated(payload) { const gift = payload; const existing = await db.findByRaiseGiftId(gift.id); if (existing && existing.modifiedDate >= gift.modifiedDate) { // We already have a newer version of this record — ignore the older update return; } await db.update(existing.id, gift);}
This produces last-writer-wins semantics keyed on modifiedDate rather than on arrival order.
Pulling the patterns together: for a typical partner integration that needs to react to donation activity, the recommended subscription strategy:
Event
Subscribe?
Why
Gift created (likely 10)
Yes
Primary signal — new donations
Gift updated (likely 11)
Optional
Useful for integrations syncing gift state
Gift deleted (likely 12)
Optional
Useful for integrations that need to handle deletions
RecurringGift created (likely 20)
Yes for stewardship integrations
Signals donor commitment
RecurringGift updated (likely 21)
Optional
Catches hasPaymentFailed changes if no polling
RecurringGift cancelled (likely 22)
Yes for stewardship
Triggers retention workflows
Donor events (30, 31, 32)
Yes for sync integrations
Two-way sync with external CRM
Campaign events (40, 41, 42)
Rare
Most integrations don’t react to Campaign changes
Page events (50, 51, 52)
Rare
Most integrations focus on Donor/Gift activity
A typical partner subscription might cover [10, 11, 20, 21, 22, 30, 31] — the events that drive most donor-and-gift workflows without subscribing to everything.