Overview
Receive real-time payment, refund, and subscription events from GivePay
What are webhooks?
GivePay sends webhooks to your server whenever something interesting happens on your account — a donor pays, a subscription renews, a refund is issued. Each webhook is a POST request with a signed JSON body that you can verify and act on (e.g. update your CRM, send a thank-you email, reconcile your accounting).
Quick start
- Add a receiver in your app. Expose an HTTPS endpoint that accepts
POSTrequests with a JSON body, for examplehttps://yourcharity.org/webhooks/givepay. - Register the endpoint in the GivePay dashboard. Choose which events you want to receive.
- Save the signing secret. A
whsec_...secret is shown once on creation. Store it as an environment variable; you'll use it to verify every incoming webhook. - Verify the signature of every request before trusting the payload — see Signatures.
- Respond with a 2xx status code as soon as you've accepted the event. Defer any slow work to a background job.
Envelope
Every webhook delivered by GivePay has the same top-level envelope. The data object varies by event type.
{
"id": "evt_550e8400-e29b-41d4-a716-446655440000",
"type": "payment.succeeded",
"environment": "LIVE",
"source": "Stripe",
"api_version": "2026-05-11",
"created_at": "2026-05-11T12:34:56Z",
"data": { ... }
}| Field | Type | Description |
|---|---|---|
id | string | Unique event identifier (evt_ + UUID). Use this to deduplicate retried deliveries |
type | string | The event type — see Event types |
environment | string | "LIVE" or "SANDBOX" — matches the API key environment that produced the event |
source | string | Underlying payment provider that triggered the event ("Stripe" or "Ryft") |
api_version | string | Webhook scheme version. Bumped only when the envelope or any data shape changes in a breaking way |
created_at | string | ISO 8601 UTC timestamp of when the event was emitted |
data | object | Event-specific payload. Always contains a primary object (e.g. payment_session, subscription, refund) along with related resources |
Headers
Content-Type: application/json
X-GivePay-Signature: t=1715425696,v1=a1b2c3d4e5f6789a...
User-Agent: GivePay-Webhook/1.0The X-GivePay-Signature header is HMAC-SHA256 signed using your endpoint's signing secret — see Signatures for verification code in Node, Python, Go, and PHP.
Responding to webhooks
| Response | Behaviour |
|---|---|
2xx (200–299) | Delivery is marked as SUCCEEDED |
4xx / 5xx / network error | Delivery is retried with exponential backoff, up to 8 attempts total |
| No response within timeout (~30s) | Treated as a failure and retried |
You can return an empty body; the response body is logged for your debugging but otherwise ignored.
Acknowledge first, work later. Your receiver should respond within a few seconds. Push slow work (sending email, hitting third-party APIs) into a background job so you don't trip the timeout.
Idempotency
Each event has a stable id. Network hiccups or 5xx responses cause GivePay to retry, so the same event id may arrive more than once. Persist processed event IDs and short-circuit duplicates.
Test mode
- Register a separate endpoint with
environment: "SANDBOX"to receive sandbox events. - Use the dashboard to fire a synthetic event of any type against your receiver without making a real payment.
What's next?
- Event types — every event and the exact
datashape it delivers - Signatures — how to verify
X-GivePay-Signature - Delivery & retries — retry policy, observability, and best practices