Payment Webhooks
Receive real-time notifications when payments are created, completed, refunded, or fail. Configure webhook endpoints and verify event signatures.
Muin sends webhook events to your server when payment-related events occur. Use webhooks to trigger fulfillment, update your own systems, or sync records in real time.
Setting Up a Webhook
- Go to Settings → Integrations → Webhooks
- Click Add Endpoint
- Enter your endpoint URL (must be publicly accessible HTTPS)
- Select the event types you want to receive
- Click Save — Muin immediately sends a test ping to verify the endpoint is reachable
Payment Event Types
| Event | Fires when |
|---|---|
payment.created | A new payment record is created |
payment.completed | Payment is fully settled |
payment.failed | Payment attempt fails (card declined, insufficient funds, etc.) |
payment.refunded | A full or partial refund is issued |
payment.disputed | A chargeback or dispute is opened |
payment_page.viewed | A payment page receives a visit |
donation.received | A new donation is processed |
pledge.fulfilled | A pledge payment completes |
subscription.created | A recurring subscription is set up |
subscription.renewed | A recurring billing cycle succeeds |
subscription.cancelled | A subscription is cancelled |
subscription.payment_failed | A recurring billing cycle fails |
Webhook Payload
Each event is delivered as an HTTPS POST with a JSON body:
{
"event": "payment.completed",
"id": "evt_01HXK2...",
"created_at": "2026-06-08T14:23:11Z",
"tenant_id": "ten_01HXK...",
"data": {
"payment_id": "pay_01HXK...",
"amount_cents": 5000,
"currency": "USD",
"method": "card",
"status": "completed",
"contact_id": "con_01HXK...",
"invoice_id": "inv_01HXK...",
"metadata": {}
}
}
Verifying Webhook Signatures
Every webhook delivery includes a Muin-Signature header. Verify it to confirm the request came from Muin and hasn’t been tampered with:
- Get your endpoint’s Signing Secret from Settings → Integrations → Webhooks → [your endpoint] → Signing Secret
- Compute
HMAC-SHA256(raw_body, signing_secret) - Compare to the value in
Muin-Signatureheader
Python example:
import hmac, hashlib
def verify(payload_bytes, signature_header, secret):
expected = hmac.new(secret.encode(), payload_bytes, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header)
Reject any delivery where verification fails.
Retries
If your endpoint returns a non-2xx response (or times out after 10 seconds), Muin retries delivery:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 5 minutes |
| 3 | 30 minutes |
| 4 | 2 hours |
| 5 | 6 hours |
After 5 failed attempts, the delivery is marked Failed in the webhook log. Failed events can be manually replayed from the endpoint detail view.
Webhook Logs
Every delivery attempt is logged in Settings → Integrations → Webhooks → [endpoint] → Logs:
- Request payload
- Response status and body
- Delivery timestamp
- Success / failure status
Use the log to debug integrations without waiting for events to recur.
Next Steps
- Payment Transactions — view all payment records
- Payment Pages — create public-facing payment links