Create donation
Record a pending donation row against a fundraiser. The Stripe fee is computed server-side and the donor is the session's account.
Requires a bearer session and a verified email address, is gated by the features.donations flag, and is protected by reCAPTCHA v3 (action donation) — send the token as recaptcha_token in the body or in the x-recaptcha-token header. Because this route already requires a verified email, a Cognito session may omit the token; an API key or impersonation session without one answers 400. A token that is sent is always verified: below the score threshold answers 403.
This is the bookkeeping half of a gift. Money is moved by POST /payments/create-intent + POST /payments/confirm.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Header Parameters
reCAPTCHA v3 token, action donation. Alternative to recaptcha_token in the body.
iOS only. The App Attest key id (standard base64, as DCAppAttestService.generateKey returns it) of a key registered with POST /app-attest/attest. Send with x-app-attest-assertion.
iOS only. base64 of the assertion from generateAssertion(keyId, clientDataHash: SHA256(raw request body)). The body must carry a fresh app_attest_challenge. A valid assertion replaces the reCAPTCHA token; the headers alone never do. An invalid one answers 403 with code APP_ATTEST_INVALID, APP_ATTEST_KEY_UNKNOWN (attest a new key) or APP_ATTEST_CHALLENGE_INVALID (fetch a new challenge), unless the request passes reCAPTCHA some other way.
Request Body
Responses
Donation created