Waffo Pancake
Configure the Waffo Pancake gateway.
MuseMVP integrates Waffo Pancake as one of its payment gateways. Through the unified Muse Billing module, it handles subscriptions, one-time purchases, and the customer portal with the same contract and access model as Creem, Stripe, and Dodo Payments. This guide explains how to configure the Waffo gateway and understand how it works.
Official docs
Use the Waffo Pancake API reference while you configure credentials, products, and webhooks.
Set the default gateway
When Waffo Pancake is your primary checkout provider, set BILLING_DEFAULT_GATEWAY=muse_waffo.
Gateway selection
You can still override the gateway per checkout request. The environment default is used by pricing and launch flows. If no default is configured, Muse Billing falls back in this order: Creem → Stripe → Dodo → Waffo.
Get merchant credentials
Sign in to the Waffo Merchant Dashboard and copy both values from API & Development. Set WAFFO_MERCHANT_ID and WAFFO_PRIVATE_KEY. Store the private key as one line with \n escapes:
- Merchant ID: top of the page, copy button. Use the merchant ID (
MER_xxx), not a store ID (STO_xxx). - API Key: API Keys section → create a key, then paste the PEM private key.
- Environment:
testorprod.
Waffo is enabled only when both merchant ID and private key are saved.
Key security
Keep gateway secrets in env files or the platform secret store. Never expose them to the client or version control.
Configure the webhook URL
Waffo verifies webhooks with the SDK's embedded public keys. No webhook secret is required.
In the Waffo Merchant Dashboard, add an HTTP webhook and set the callback URL to:
https://example.com/api/muse-billing/notify/muse_waffoSubscribe to the event types Muse Billing maps (or all events):
order.completedsubscription.activatedsubscription.payment_succeededsubscription.updatedsubscription.cancelingsubscription.uncanceledsubscription.past_duesubscription.canceledrefund.succeededrefund.failed
Signature header
Muse Billing requires x-waffo-signature on every webhook, including local development. Requests without a valid signature are rejected. The adapter reads request.text() (raw body) before verification — do not parse JSON first.
Set WAFFO_ENVIRONMENT=test for sandbox checkout and webhook verification; WAFFO_DEBUG is not a signature or environment bypass.
Events whose mode does not match the configured Waffo environment are ignored so test events cannot update production contracts.
Create products and get product IDs
Waffo product IDs use the PROD_ prefix and are set with WAFFO_PRODUCT_ID_*. The public pricing UI uses stable app plan IDs.
After creating the corresponding products in the Waffo Dashboard (Products), copy each PROD_xxx ID from the product detail page or URL into the WAFFO_PRODUCT_ID_* environment variables.
Environment match
The product IDs must belong to the same Waffo environment as the configured gateway environment. A test-mode product ID in prod (or the reverse) returns a product-not-found error on launch.
Local development testing
Download Ngrok
Ngrok (https://dashboard.ngrok.com/get-started/setup/windows) is a reverse proxy tool that exposes your local development server to the public internet.
Run
ngrok http 3000Callback domain
Use the terminal domain shown above as the callback URL in your webhook configuration.
Switch to test mode
Set WAFFO_ENVIRONMENT=test and complete a payment in the Waffo test environment.
| Test card | Expected result |
|---|---|
4576750000000110 | Successful test payment |
Test mode
Payments in Waffo test mode do not result in real charges. After a successful checkout, confirm that order.completed (one-time) or subscription.activated / subscription.payment_succeeded (subscription) arrives at /api/muse-billing/notify/muse_waffo.
How it works
Learn how Muse Billing integrates Waffo Pancake into the system.
Integration files
| File | Purpose |
|---|---|
waffo/gateway.ts | Waffo gateway implementation: authenticated checkout launch, webhook verification, customer portal, subscription cancel. |
waffo/mappers.ts | Maps Waffo webhook events and order states into Muse contract snapshots. |
router.ts | API routes: exposes /api/muse-billing/* endpoints. |
Core workflow
The action flow for payment and accessing the customer portal:
Frontend calls POST /api/muse-billing/launch with productId, optional gatewayId (defaults to orchestrator selection), etc.
Server resolves the Waffo product or price ID from WAFFO_PRODUCT_ID_* environment variables.
Creates a Waffo authenticated checkout session (buyerIdentity = the signed-in user ID) and returns launchUrl for the frontend to redirect to the hosted checkout page. Checkout metadata includes referenceId and planProductId so the webhook can match the pending contract.
After payment, Waffo sends a webhook; the server verifies x-waffo-signature and syncs contract lifecycle and access window to the database. Subscription snapshots use the Waffo order ID (ORD_xxx) as gatewaySubscriptionId.
When the user needs to access the platform portal, call POST /api/muse-billing/customer-hub. Waffo uses a shared consumer portal (https://pancake.waffo.ai/consumer/portal/login) and does not require a merchant customer ID. Override the URL with WAFFO_CUSTOMER_PORTAL_URL if needed.
Discount codes
Waffo checkout has no discount-code field. If the pricing UI collects a discount code, Muse Billing ignores it for muse_waffo launches.
Related docs
- Creem Payment Gateway — Alternative payment gateway
- Stripe Payment Gateway — Alternative payment gateway
- Dodo Payments Gateway — Alternative payment gateway
- Environment Variables — Gateway credentials and checkout product IDs
- Basic Configuration — Pricing catalog and stable plan IDs
- Environment Variables