Skip to main content
Payment failures are a normal part of running a donation platform. Cards expire, accounts close, balances run low, gateways have transient issues. Partner integrations that handle failures well — distinguishing transient errors from permanent ones, recovering recurring schedules promptly, and surfacing the right signals to the customer’s stewardship team — are much more useful than integrations that simply log errors and move on. This workflow covers the three classes of payment failures in Raise: one-time donation failures (from POST /api/Raise/give), recurring schedule failures (the hasPaymentFailed flag), and the recovery flows that bring failed schedules back to active.

Three classes of failure

Each class needs a different response. The next sections walk through them in detail.

One-time donation failures

When a donor submits a donation through POST /api/Raise/give and the gateway declines the charge, the request returns 400 Bad Request with a ProblemDetails body. The Gift record is not created in this case.

Classifying the failure

The most useful field is detail in the response body. Common payment-failure reasons:
The exact detail text returned by Raise depends on the payment gateway configured for the customer’s organization. Gateway-specific messages may vary (Stripe says one thing, Authorize.net says another). Don’t switch on exact detail strings — they’re not a stable contract. Use them for logging and user-facing surfacing, not for retry logic.⚠️ Spec gap: The OpenAPI spec doesn’t enumerate the standard payment-failure messages Raise produces. The list above is representative; the canonical mapping isn’t published. Coordinate with the platform team for the authoritative list if your integration’s classification logic needs it.

Handling a one-time failure

JavaScript
The right response by classification:

What the donor sees

For donor-facing flows (forms embedded on a customer’s site), the partner integration’s job is to display a clear, actionable error message. A few patterns: Don’t surface the raw detail string to donors — it may contain technical jargon, gateway-specific codes, or unhelpful messages. Map to a friendly message and log the raw detail server-side for diagnostics.

Recurring schedule failures

A failed payment on a recurring schedule produces a different signal: the schedule’s hasPaymentFailed flag becomes true. The schedule remains in the system but stops processing new charge cycles until the donor’s payment method is updated.

Detecting failed schedules

Query for failed schedules on a regular cadence — typically daily as part of the customer’s stewardship workflow:
JavaScript
For ongoing monitoring, store the last-known set of failed schedule IDs and compare to the latest query result on each cycle. New entries (schedules that flipped from healthy to failed since the last check) are the highest-priority candidates for donor outreach.

Inspecting payment history

To understand why a specific schedule failed, fetch its activity history:
cURL
The activity records typically include each cycle’s outcome (success or failure) and the reason. Useful for showing the customer’s stewardship team a clear picture before they contact the donor.

The recovery flow

The typical flow for recovering a failed schedule:
1

Detect the failure

Daily failed-schedules query identifies the schedule. New failures (not previously known) flow into the recovery queue.
2

Generate a personalized donor page

Use POST /api/Donor/{donorId}/generate-page to create a URL pre-filled with the donor’s identity. The donor will land on a page where they can update payment info and resume their schedule.
3

Send the outreach email

Email the donor with the personalized URL. Be clear and kind: explain that their support has paused, that updating their payment method takes a few seconds, and provide the direct link.
JavaScript
4

Track the outreach

Record that you’ve contacted the donor and when. On the next daily run, skip donors you’ve already notified within the past N days to avoid spamming.
5

Re-check the schedule

After the donor updates their payment method (typically through the personalized page), the next charge cycle will succeed and hasPaymentFailed flips back to false. Your daily query naturally stops returning the schedule.
6

Escalate persistent failures

Schedules that remain hasPaymentFailed: true after multiple outreach attempts (e.g., 30 days, 3 emails) should be escalated for human review by the customer’s stewardship team. They may need phone outreach or eventual schedule cancellation.

Proactive: detect upcoming card expirations

A more effective pattern: contact donors before their card actually fails. Check the expMonthAndYear field on active schedules:
JavaScript
The exact format of expMonthAndYear (MM/YYYY, MM/YY, or another shape) is not documented in the spec. Confirm against live data before parsing in production. See Recurring Gifts: Detecting upcoming card expirations.
Donors notified before their cards expire respond at much higher rates than donors notified after the failure has already happened. The proactive flow is the same as the recovery flow — generate a personalized page, send an email — but with friendlier framing (“just a heads up, your card on file expires next month”).

Gateway-level outages

The third class of failures: the payment gateway itself is temporarily unavailable. Symptoms include:
  • Multiple POST /api/Raise/give requests across different customers returning 5xx responses or timing out within a short window.
  • Multiple recurring schedules flipping to hasPaymentFailed: true in close succession.
  • Network errors connecting to the API host.
For partner integrations:

What to do during a likely outage

What not to do

See Error Recovery Patterns for the broader retry-with-circuit-breaker pattern that handles outages gracefully.

Webhook events for payment failures

The Raise webhook system delivers events when records change. For payment failures, the relevant events are typically:
⚠️ Spec gap: The Raise OpenAPI spec doesn’t label the EventType enum integers ([10, 11, 12, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51, 52]). Identifying the specific event type integers that correspond to payment-failure scenarios requires discovery against the live API or coordination with the platform team.Until the labels are published, the daily-polling pattern shown above is the most reliable detection method. When event type labels become available, the same recovery flow can be triggered in real time from webhook events instead of from the polling query.
The webhook log endpoints (GET /api/Webhook/{id}/log/list, GET /api/Webhook/{id}/log/{logId}) are particularly useful here — partner integrations can confirm which events have fired for a customer and inspect the payload shapes to map event type integers to their semantic meanings.

A complete failed-payment monitor

Pulling the pieces together as a daily monitor job:
JavaScript
Run this on a daily cron. Track outreach in a small database to avoid duplicate notifications. Monitor the counts over time — sudden spikes in failedCount may indicate a gateway issue rather than typical donor activity.

Where to go next

Configure a Recurring Gift

The full recurring schedule lifecycle including the failure detection patterns.

Process a Donation

The end-to-end donation flow including the one-time failure handling.

Error Recovery Patterns

The general retry, circuit-breaker, and dead-letter patterns that apply to payment failures.

Webhooks Overview

Subscribe to payment events for real-time failure detection.
Last modified on May 20, 2026