Miracle Docs

Webhook Testing

Test your webhook handler during development to make sure it correctly processes payment events, verifies signatures, and handles edge cases before going live.


Local development with ngrok

Your webhook endpoint must be publicly accessible for Miracle to deliver events. During local development, use a tunneling tool like ngrok to expose your local server:

  1. Install ngrok:

    # macOS
    brew install ngrok
    
    # or via npm
    npm install -g ngrok
  2. Start your local server on the port it listens on (e.g., port 3000).

  3. Start ngrok to create a public tunnel:

    ngrok http 3000

    ngrok outputs a public URL like https://a1b2c3d4.ngrok-free.app.

  4. Register the ngrok URL as your webhook endpoint in the Miracle Portal:

    • Go to Settings > Webhooks.
    • Click Add Endpoint.
    • Enter your ngrok URL followed by your webhook path, e.g., https://a1b2c3d4.ngrok-free.app/webhooks/miracle.
    • Copy the signing secret (whsec_...) for signature verification.
  5. Run a test payment using a test card — the webhook event will be delivered to your local server through the ngrok tunnel.

ngrok URLs change every time you restart the tunnel (on the free plan). Update your webhook endpoint in the Portal when the URL changes.


Test webhooks from the Portal

You can send test webhook events directly from the Miracle Portal without creating a real transaction:

  1. Go to Settings > Webhooks in the Miracle Portal.
  2. Select the endpoint you want to test.
  3. Click Send Test Event.
  4. Choose the event type to simulate (e.g., payment.succeeded, payment.failed, refund.created).
  5. The Portal sends a properly signed event to your endpoint.

This is useful for testing your handler's response to specific event types without going through the full payment flow.

You can also replay previous deliveries from the delivery log. Select any past delivery and click Replay to re-send the exact same event payload to your endpoint. This is useful for debugging failed deliveries without recreating the original transaction.


Verifying webhook delivery

The Miracle Portal provides a delivery log for every webhook endpoint:

  1. Go to Settings > Webhooks in the Portal.
  2. Select your endpoint.
  3. Open the Delivery Log tab.

Each delivery entry shows:

FieldDescription
Event typeThe event that triggered the delivery (e.g., payment.succeeded)
StatusSuccess or failed
Response codeThe HTTP status code your endpoint returned
TimestampWhen the delivery was attempted
Response bodyThe body your endpoint returned (for debugging)
Error detailsIf delivery failed — timeout, connection refused, non-2xx response

Failed deliveries are retried automatically with exponential backoff. The log shows each retry attempt.


End-to-end testing checklist

Use this checklist to verify your webhook integration before going live:

  • Successful payment (payment.succeeded) — does your server fulfill the order?
  • Failed payment (payment.failed) — does your server notify the customer?
  • 3DS required (payment.requires_action) — does your server handle the redirect flow?
  • Refund (refund.succeeded) — does your server update the order status?
  • Signature verification — does your server reject events with invalid signatures?
  • Duplicate events — does your server handle receiving the same event twice?
  • Unknown event types — does your server return 200 OK for events it does not handle?

Troubleshooting

Webhook not received?

  • Check that your endpoint URL is publicly accessible. Local URLs (localhost, 127.0.0.1) cannot receive webhooks — use ngrok or a similar tunnel.
  • Verify the endpoint is registered in the Portal and the URL is correct.
  • Check the Delivery Log in the Portal for error details.

Getting 4xx errors?

  • 400 — check your signature verification code. Make sure you are using the raw request body (not a parsed JSON object) for signature computation.
  • 401 / 403 — make sure your endpoint does not require authentication that blocks Miracle's requests.

Timeout errors?

  • Your endpoint must respond within 10 seconds. Process webhook events asynchronously — acknowledge with 200 OK immediately, then handle the business logic in a background job.
  • If your handler is slow, queue the event and return 200 right away.

Duplicate events?

  • Miracle guarantees at-least-once delivery. Use event.id to deduplicate. If you have already processed an event with that ID, return 200 OK and skip processing.

On this page