Falaah Falaah AI

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

  1. Go to Settings → Integrations → Webhooks
  2. Click Add Endpoint
  3. Enter your endpoint URL (must be publicly accessible HTTPS)
  4. Select the event types you want to receive
  5. 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:

  1. Get your endpoint’s Signing Secret from Settings → Integrations → Webhooks → [your endpoint] → Signing Secret
  2. Compute HMAC-SHA256(raw_body, signing_secret)
  3. Compare to the value in Muin-Signature header

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.

The inbound provider log is a different list

The log above covers webhooks Muin sends you. For webhooks your payment provider sends Muin, open Smart Payments → Settings → Webhook log. It lists each event received, with:

  • the provider
  • the event ID
  • whether the signature was Verified or Rejected
  • the payload

This is where to look when a payment happened at the provider but never appeared in Muin. A Rejected signature means Muin discarded the event because it could not verify it came from your provider, which is the correct behavior. If it is happening to legitimate events, reconnect the provider under Settings → Stripe Connect so the signing secret is refreshed.


Next Steps