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
| Class | When it happens | How to detect | Recovery path |
|---|---|---|---|
| One-time donation failure | A POST /api/Raise/give request fails at the gateway | 400 Bad Request with payment-specific detail in the ProblemDetails body | Surface to donor; let them try a different payment method |
| Recurring schedule failure | A scheduled charge cycle fails | hasPaymentFailed: true on the RecurringGift record | Donor outreach to update payment method |
| Gateway-level outage | The payment gateway is temporarily unavailable | 5xx responses, network errors, or batch failures across multiple submissions | Retry with backoff; escalate if sustained |
One-time donation failures
When a donor submits a donation throughPOST /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 isdetail in the response body. Common payment-failure reasons:
| Detail (representative) | Cause | Recoverable? |
|---|---|---|
"Card declined" | Gateway declined the charge (insufficient funds, fraud flag, etc.) | No — same card will fail again; donor needs a different method. |
"Card expired" | The card’s expiration date has passed | No — donor must use a different card. |
"Invalid card number" | Tokenization or transcription error | No — donor must re-enter card details. |
"Insufficient funds" | Account balance below the donation amount | Sometimes — donor can try again after funding the account. |
"Issuer unavailable" | The card issuer’s authorization system is temporarily unreachable | Yes — retry after a short delay (minutes). |
"Gateway timeout" | The payment gateway didn’t respond in time | Yes — retry with caution (could be a successful charge that didn’t complete the API response). |
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
| Classification | Response |
|---|---|
validation_error | Fix the request body and re-submit. Surface field-level errors to the UI. |
payment_declined | Display a clear “your payment was declined — please try a different method” message. Don’t retry the same card. |
auth_error | Don’t retry — the API token needs to be replaced. Alert the integration owner. |
rate_limited | Honor Retry-After and back off. See Rate Limits. |
gateway_error | Retry with caution — see “Idempotency considerations” in Process a Donation. |
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:| Failure type | Donor-facing message |
|---|---|
| Card declined | ”Your card was declined. Please try a different payment method.” |
| Card expired | ”Your card has expired. Please enter a card with a valid expiration date.” |
| Invalid card | ”We couldn’t process this card. Please check the card number and try again.” |
| Network/gateway error | ”We’re having trouble processing your donation right now. Please try again in a few minutes.” |
| Generic fallback | ”Your donation couldn’t be processed. Please try again or contact support.” |
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’shasPaymentFailed 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
Inspecting payment history
To understand why a specific schedule failed, fetch its activity history:cURL
The recovery flow
The typical flow for recovering a failed schedule:Detect the failure
Daily failed-schedules query identifies the schedule. New failures (not previously known) flow into the recovery queue.
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.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
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.
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.Proactive: detect upcoming card expirations
A more effective pattern: contact donors before their card actually fails. Check theexpMonthAndYear 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.Gateway-level outages
The third class of failures: the payment gateway itself is temporarily unavailable. Symptoms include:- Multiple
POST /api/Raise/giverequests across different customers returning5xxresponses or timing out within a short window. - Multiple recurring schedules flipping to
hasPaymentFailed: truein close succession. - Network errors connecting to the API host.
What to do during a likely outage
| Behavior | Description |
|---|---|
| Slow down submissions | Don’t hammer a struggling system with retries. Back off aggressively. |
| Queue retries for later | For non-time-sensitive donations, queue and retry after the outage resolves. |
| Alert on sustained failures | If >20% of recent submissions fail over 10+ minutes, alert the integration owner — this likely indicates an upstream issue, not random failures. |
| Surface to donors clearly | Real-time donation flows should show a clear “we’re having trouble — please try again in a few minutes” message rather than appearing broken. |
What not to do
| Anti-pattern | Why |
|---|---|
| Retry forever | A 5xx that persists for hours is a gateway outage, not a transient blip. Cap retries and surface for human review. |
Retry without Retry-After awareness | If Raise returns 429 Too Many Requests, honor the header. Adding more retries during throttling makes things worse. |
| Silently absorb failures | Failed donations are lost donations. Make sure the failure is logged, surfaced, and (where appropriate) queued for retry. |
Webhook events for payment failures
The Raise webhook system delivers events when records change. For payment failures, the relevant events are typically:| Likely event | What it signals |
|---|---|
| RecurringGift update events | The schedule’s hasPaymentFailed flag changed — useful for real-time detection without polling. |
| Gift events | A new Gift was created (successful charge) or a Gift was refunded. |
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
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.