MuseMVP Docs
Billing

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, point the billing default gateway to muse_waffo:

MUSE_BILLING_DEFAULT_GATEWAY="muse_waffo"

Gateway selection

You can still override the gateway per checkout request. This variable only defines the default used by pricing and launch flows. If it is unset, Muse Billing falls back in this order: Creem → Stripe → Dodo → Waffo.

Get merchant credentials

Before deploying or running locally, configure the merchant ID and API private key.

# Merchant ID (starts with `MER_`)
MUSE_WAFFO_GATEWAY_MERCHANT_ID="MER_xxx"
# API private key (PEM). Use `\n` for newlines in `.env` files.
MUSE_WAFFO_GATEWAY_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
# Optional: force Waffo environment ("test" | "prod")
# If omitted, production uses prod and other environments use test.
MUSE_WAFFO_GATEWAY_ENV="test"

Sign in to the Waffo Merchant Dashboard and copy both values from API & Development:

  • Merchant ID: top of the page, copy button. Use this as MUSE_WAFFO_GATEWAY_MERCHANT_ID, not a store ID (STO_xxx).
  • API Key: API Keys section → create a key, then paste the PEM private key into MUSE_WAFFO_GATEWAY_PRIVATE_KEY.

Waffo is enabled only when both values are set. Setting just one of them logs a startup warning and leaves the gateway disabled.

Key security

MUSE_WAFFO_GATEWAY_MERCHANT_ID and MUSE_WAFFO_GATEWAY_PRIVATE_KEY are server-side only; 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_waffo

Subscribe to the event types Muse Billing maps (or all events):

  • order.completed
  • subscription.activated
  • subscription.payment_succeeded
  • subscription.updated
  • subscription.canceling
  • subscription.uncanceled
  • subscription.past_due
  • subscription.canceled
  • refund.succeeded
  • refund.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.

Optional environment flags:

# Accept sandbox (`test`) webhooks in a production Node build.
# MUSE_WAFFO_DEBUG=true

Events whose mode does not match MUSE_WAFFO_GATEWAY_ENV are ignored so test events cannot update production contracts.

Create products and get product IDs

Product IDs come from config.payments.productCatalog.*.gatewayProductIds.muse_waffo in src/config/index.ts by default, and can be overridden via environment variables. Waffo product IDs use the PROD_ prefix:

# Pro monthly subscription product ID
NEXT_PUBLIC_MUSE_WAFFO_PRICE_PRO_MONTHLY_ID="PROD_muse_waffo_monthly_xxx"
# Pro yearly subscription product ID
NEXT_PUBLIC_MUSE_WAFFO_PRICE_PRO_YEARLY_ID="PROD_muse_waffo_yearly_xxx"
# Lifetime one-time product ID
NEXT_PUBLIC_MUSE_WAFFO_PRICE_LIFETIME_ID="PROD_muse_waffo_lifetime_xxx"

After creating the corresponding products in the Waffo Dashboard (Products), copy each PROD_xxx ID from the product detail page or URL.

Environment match

The product IDs must belong to the same Waffo environment as MUSE_WAFFO_GATEWAY_ENV. 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 3000

Callback domain

Use the terminal domain shown above as the callback URL in your webhook configuration.

Switch to test mode

Ensure MUSE_WAFFO_GATEWAY_ENV is set to test and complete a payment in the Waffo test environment.

Test cardExpected result
4576750000000110Successful 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

src/modules/muse-billing/lib/gateways/waffo/gateway.ts
src/modules/muse-billing/lib/gateways/waffo/mappers.ts
src/backend/api/routes/muse-billing/router.ts
FilePurpose
waffo/gateway.tsWaffo gateway implementation: authenticated checkout launch, webhook verification, customer portal, subscription cancel.
waffo/mappers.tsMaps Waffo webhook events and order states into Muse contract snapshots.
router.tsAPI 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 ID from the config.payments.productCatalog mapping.

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 MUSE_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.

On this page