Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.waffo.ai/llms.txt

Use this file to discover all available pages before exploring further.

What Are Webhooks?

Webhooks are automatic notifications that Waffo Pancake sends to your server when something happens — a payment succeeds, a subscription renews, a refund is processed, etc. Why you need them:
  • Automate delivery: Send download links or grant access immediately after payment
  • Keep your system in sync: Update your database when subscription status changes
  • React to events: Handle failed payments, cancellations, and refunds in real time

Step 1: Add a Webhook in the Dashboard

1

Go to Settings

In your Dashboard, navigate to Settings → Webhooks.
Webhooks settings page with Test Mode and Live Mode sections
2

Choose a Format

Select how the payload should be shaped for the destination — Raw JSON for your own backend, a chat-platform format (Slack / Discord / Feishu / Telegram) so messages render natively in that tool, or OpenClaw / Hermes (the self-hosted Pancake plugin) for custom routing and downstream logic. See Choose a payload format below.
Add Webhook modal with the Format dropdown open showing Raw, Feishu, Slack, Discord, Telegram, OpenClaw/Hermes
3

Set Your Webhook URL

Enter the URL where Waffo Pancake should send event notifications.
  • Test mode URL: Your development/staging server (e.g., https://staging.yoursite.com/webhooks/waffo)
  • Production URL: Your production server (e.g., https://yoursite.com/webhooks/waffo)
You can set different URLs for test and production environments. This keeps test events separate from real ones.
If you picked Telegram in the previous step, you’ll fill in a Bot Token and a Chat ID instead of a URL. See Telegram below for how to obtain them.
4

Pick the events

All events are subscribed by default. Untick the ones you don’t want.
5

Save

Click Save Webhook.
You can configure up to 10 webhooks per environment, so you can fan out the same events to multiple destinations (your backend, a Slack channel, an internal dashboard) without writing your own relay. The same URL cannot be added twice in the same environment.
Production note: Live Mode webhooks only deliver after your store passes review. While the store is still under review, use Test Mode webhooks against staging code paths.

Choose a payload format

Waffo can deliver each event in the format your destination expects, so you don’t have to write a translator. Pick the format when you add the webhook; you can re-add a webhook with a different format if you change your mind.
FormatUse when…Endpoint
Raw (default)You’re calling your own backend and want the canonical, signed JSON payload.Any HTTPS URL
Feishu / LarkYou want events posted into a Feishu group via a custom bot.https://open.feishu.cn/open-apis/bot/v2/hook/<hook-id>
SlackYou want events posted into a Slack channel via an Incoming Webhook.https://hooks.slack.com/services/T.../B.../<token>
DiscordYou want events posted into a Discord channel via a channel webhook.https://discord.com/api/webhooks/<id>/<token>
TelegramYou want events posted into a Telegram chat or group via a bot.Bot Token + Chat ID (URL is built for you)
OpenClaw / HermesYou’re routing events through the self-hosted Pancake plugin for custom downstream logic.https://relay.waffo.ai/webhook/<webhook-id>
Only Raw carries an RSA-SHA256 signature. The chat-platform formats authenticate via the URL-embedded token issued by the destination platform, so signature verification is not used for them.

Raw

  1. In your backend, expose an HTTPS endpoint that accepts POST application/json.
  2. Paste the URL into the Endpoint URL field.
  3. After saving, open the webhook detail page and copy the Signing Public Key — you’ll use it to verify deliveries (see API Reference — Webhooks).

Feishu / Lark

  1. In your Feishu group, add a Custom Bot and copy its webhook URL.
  2. The URL looks like https://open.feishu.cn/open-apis/bot/v2/hook/<hook-id> (or open.larksuite.com/... outside China — both work).
  3. Paste it into the Endpoint URL field.

Slack

  1. In your Slack workspace, install an Incoming Webhook for the destination channel.
  2. Copy the webhook URL — it looks like https://hooks.slack.com/services/T.../B.../<token>.
  3. Paste it into the Endpoint URL field.

Discord

  1. In the destination channel, open Edit Channel → Integrations → Webhooks → New Webhook and copy the URL.
  2. Format: https://discord.com/api/webhooks/<id>/<token>.
  3. Paste it into the Endpoint URL field.

Telegram

Telegram needs both a Bot Token and a Chat ID — Waffo builds the Telegram sendMessage URL for you.
  1. Talk to @BotFather and create (or pick) a bot. Copy its token, e.g. 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11.
  2. Add the bot to the destination chat or channel and grant it permission to send messages.
  3. Get the chat ID. The easiest way: send a message in the chat, then visit https://api.telegram.org/bot<TOKEN>/getUpdates and copy the chat.id from the response.
  4. In the Add Webhook modal, choose Telegram, paste the Bot Token and Chat ID, and save.
Behind the scenes Waffo posts to https://api.telegram.org/bot<TOKEN>/sendMessage with chat_id set to the value you provided.

OpenClaw / Hermes (Pancake plugin)

The Pancake plugin is Waffo’s self-hosted relay. It receives events from Waffo, runs your custom logic (templating, rate-limiting, multi-fan-out), and forwards messages to wherever you want. OpenClaw and Hermes are two ready-to-run flavors of the plugin; pick whichever matches your stack.
  1. Install the plugin with the matching setup command:
    # OpenClaw
    npx -p @waffo/pancake-plugin openclaw-setup
    
    # Hermes
    npx -p @waffo/pancake-plugin hermes-setup
    
    Full setup guide: github.com/waffo-com/waffo-pancake-plugin.
  2. After install, the plugin gives you a relay URL of the form https://relay.waffo.ai/webhook/<webhook-id>.
  3. In the Add Webhook modal, choose OpenClaw / Hermes, paste the relay URL, and save.

Step 2: Understand Event Types

Waffo Pancake sends these webhook events:

Order Events

EventWhen It FiresCommon Action
order.completedOrder completed successfullyDeliver product, grant access

Subscription Events

EventWhen It FiresCommon Action
subscription.activatedSubscription activatedCreate account, set limits
subscription.payment_succeededSubscription payment succeededExtend access period
subscription.updatedSubscription details changedUpdate access level
subscription.cancelingCancellation requestedNotify team, send retention offer
subscription.uncanceledSubscription reactivatedRestore full access
subscription.canceledSubscription fully endedRevoke access
subscription.past_duePayment failedNotify customer, retry

Refund Events

EventWhen It FiresCommon Action
refund.succeededRefund processedRevoke access, update records
refund.failedRefund processing failedNotify merchant, investigate

Step 3: Set Up Email Notifications

In addition to webhook events, you can configure email notifications for both you and your customers.

Merchant Notifications

Go to Settings → Notifications to choose which events trigger email alerts to you:
  • New orders
  • New subscriptions
  • Failed payments
  • Refund requests
Notification settings

Customer Notifications

Customers automatically receive emails for:
  • Order confirmation
  • Subscription confirmation
  • Subscription renewal
  • Subscription cancellation
  • Payment failure
You can toggle these in the notification settings.

How Webhooks Work

Event occurs (e.g., payment succeeds)

Waffo Pancake sends POST request to your webhook URL

Your server receives the event

Your server processes it (deliver product, update database, etc.)

Your server responds with 200 OK

Retry Policy

If your server doesn’t respond with a 2xx status code, Waffo Pancake retries:
AttemptDelay
1st retry5 minutes
2nd retry30 minutes
3rd retry2 hours
4th retry8 hours
5th retry24 hours
After 5 failed retries, the event is marked as failed.

For Developers: Code Integration

If you’re integrating webhooks with your server, here’s how the flow works:

1. Create a Webhook Endpoint

Your server needs a POST endpoint to receive events. The specific implementation depends on your tech stack.

2. Verify the Signature

Every webhook request includes a signature header for security. Verify it to ensure the request came from Waffo Pancake, not a malicious third party.

3. Process Events

Parse the event type and data, then take the appropriate action (deliver product, update subscription status, etc.).

4. Respond Quickly

Return a 200 status code as fast as possible. If you need to do heavy processing, do it asynchronously after responding.
For detailed code examples and signature verification, see the API Reference — Webhooks.

Testing Webhooks

1

Set Test Webhook URL

In Dashboard → Settings → Webhooks, enter your test server URL.
2

Make a Test Purchase

Use test mode to create a purchase. This triggers webhook events to your test URL.
3

Verify Receipt

Check your server logs to confirm the webhook was received and processed correctly.

Local development with ngrok

When you’re building your webhook handler locally, Pancake’s servers can’t reach http://localhost:3000 directly. You need a public HTTPS tunnel that forwards inbound requests to your local port. We recommend ngrok — it’s free for development and preserves all custom headers (including X-Waffo-Signature).

Why a tunnel is required

Webhook delivery is inbound to your server: Pancake POSTs to whatever URL you configure. A localhost URL is only reachable from your own machine, so without a tunnel the requests never arrive. The tunnel gives your local server a public HTTPS hostname for the duration of your dev session.

Install and start ngrok

1

Install

2

Authenticate (free tier is fine)

Sign up at ngrok.com, grab your authtoken from the dashboard, then run:
ngrok config add-authtoken <your-authtoken>
3

Start the tunnel

Point ngrok at your local server’s port. If your webhook handler runs on localhost:3000:
ngrok http 3000
ngrok prints a forwarding URL like:
Forwarding  https://abc-123-456-789.ngrok-free.app -> http://localhost:3000
Copy the https://...ngrok-free.app URL — that’s your public webhook endpoint.

Wire it into Pancake

1

Configure the Test Webhook URL

In the Merchant Dashboard, open your store and go to Settings → Webhooks. Paste the ngrok URL (with your handler path appended, e.g. https://abc-123.ngrok-free.app/api/webhooks/waffo) into Test Webhook URL and select the events you want to receive. Save.
Only configure Test environment with the ngrok URL. Never put a temporary tunnel URL into the Production webhook — production traffic must hit a stable, deployed endpoint.
2

Trigger an event

Either click Send test event in the Dashboard, or perform a real action in test mode (e.g., create a checkout and complete it with a test card).
3

Inspect the request

Open ngrok’s local web inspector at http://127.0.0.1:4040 — it shows every request that came through, including headers and body. Confirm the X-Waffo-Signature header is present.
4

Verify in your handler

Check your local server logs. You should see the webhook POST landing and verifyWebhook() succeeding. If verification fails, see the pitfalls below.

Common pitfalls

IssueWhy it happensFix
localtunnel always returns 401 on signature verificationlocaltunnel strips custom HTTP headers, so X-Waffo-Signature never reaches your handlerUse ngrok or cloudflared instead — both preserve all headers
The ngrok URL changed after restartThe free tier issues a new random subdomain on every ngrok http runUpdate the Test Webhook URL in the Dashboard each time. For frequent dev, ngrok’s paid tier offers reserved subdomains
Events stop arriving after a whileFree ngrok sessions expire after a few hoursRestart ngrok http 3000 and re-paste the new URL
Pancake retried the event multiple timesYour handler returned a non-2xx response and the delivery was retried with exponential backoffFix the handler, then either wait for the next retry or use Resend in the Dashboard’s webhook delivery log

Cloudflared as an alternative

If you prefer a no-account option, cloudflared works similarly:
cloudflared tunnel --url http://localhost:3000
It preserves headers, requires no signup for ad-hoc tunnels, and prints a *.trycloudflare.com URL you can paste into the Dashboard. The trade-off is no built-in request inspector UI — you’ll rely on your own server logs.

Quick verification checklist

  • Local server is running and listening on the expected port
  • ngrok http <port> is running, forwarding URL captured
  • Test Webhook URL in Dashboard matches the current ngrok URL (with handler path)
  • Inbound request visible at http://127.0.0.1:4040 with X-Waffo-Signature header
  • Local logs show verifyWebhook returning success and your event handler running

Best Practices

  1. Respond quickly: Return 200 immediately, process asynchronously
  2. Handle duplicates: Events may be sent more than once — make your processing idempotent
  3. Verify signatures: Always verify the webhook signature before processing
  4. Log everything: Keep logs of received webhooks for debugging
  5. Monitor failures: Check your Dashboard for failed webhook deliveries

Checklist

  • Webhook URLs configured for test and production
  • Email notifications configured for your team
  • Customer notification preferences set
  • Test webhook received and processed successfully
  • Signature verification implemented (if using code integration)

Next Steps

Manage Refunds

Handle refund requests and track refund status

API Reference — Webhooks

Detailed webhook payload format and code examples