# Authentication Source: https://waffo.mintlify.app/api-reference/authentication Secure your API requests with API Key authentication ## Authentication Overview Waffo Pancake supports two authentication methods for API access: | Method | Use Case | Description | | -------------- | ---------------------- | -------------------------------------------------------------- | | **API Key** | Server-to-server calls | Permanent authentication using Merchant ID and private key | | **Store Slug** | Public checkout flows | Public access using `X-Store-Slug` and `X-Environment` headers | *** ## API Key Authentication API Keys provide permanent server-to-server authentication. The private key never leaves your server. API Key authentication is handled automatically by the SDK. Install `@waffo/pancake-ts`, provide your Merchant ID and private key, and the SDK will handle request signing automatically. ### Using the SDK (Recommended) ```typescript theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); // All requests are automatically authenticated const { store } = await client.stores.create({ name: "My Store" }); ``` API Key authentication does not require the `X-Environment` header. The environment is determined by the key's registered environment (test or prod). *** ## Store Slug Authentication For public-facing checkout flows, use Store Slug authentication. This allows visitors to interact with checkout endpoints without API Key credentials. | Header | Description | | --------------- | ----------------------------------- | | `X-Store-Slug` | Your store's unique slug identifier | | `X-Environment` | `test` or `prod` (required) | ```bash theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/checkout/create-session \ -H "X-Store-Slug: my-store-abc123" \ -H "X-Environment: test" \ -H "Content-Type: application/json" \ -d '{"productId": "...", "productType": "onetime", "currency": "USD"}' ``` *** ## Creating API Keys Navigate to Dashboard --> Developers --> API Keys Click "Create API Key" to generate a new key pair. The public key is sent to the server automatically. Give it a descriptive name (e.g., "Production Server") and select the target environment (Test or Production). Download your private key immediately. It will not be shown again. Deleting an API key is immediate and irreversible. Any requests using the deleted key will fail with `401 Unauthorized`. *** ## Security Best Practices * **Never expose private keys** in client-side code, version control, or public repositories * **Use environment variables** to store keys in your server application * **Separate test and production keys** -- create distinct keys for each environment * **Rotate keys regularly**, especially after team member changes * **Monitor API usage** in the Dashboard for unusual activity ```bash theme={"dark"} # Store key as environment variable export WAFFO_PRIVATE_KEY="your-private-key-content" export WAFFO_MERCHANT_ID="your-merchant-uuid" ``` *** ## Authentication Errors | Status | Message | Solution | | ------ | ------------------------ | ---------------------------------------------------- | | 401 | Invalid API key | Verify your Merchant ID and private key are correct | | 401 | Missing authentication | Ensure the SDK is initialized with valid credentials | | 403 | Insufficient permissions | Use a key with the required permissions | # Authentication Endpoints Source: https://waffo.mintlify.app/api-reference/endpoints/auth Authentication is handled through API Key signatures ## Authentication Authentication endpoints are for internal use only and are not available through the public API. To authenticate your API requests, use **API Key authentication**. API Keys provide permanent server-to-server authentication. The SDK handles request signing automatically. Learn how to create API Keys, sign requests, and authenticate with the Waffo Pancake API. *** ## Store Slug Authentication For public-facing checkout flows, use **Store Slug** authentication. This allows visitors to create checkout sessions without requiring API Key credentials. | Header | Description | | --------------- | ------------------------ | | `X-Store-Slug` | Your store's unique slug | | `X-Environment` | `test` or `prod` | See how to create checkout sessions with Store Slug authentication. # GraphQL API Source: https://waffo.mintlify.app/api-reference/endpoints/graphql Query data with GraphQL read-only queries ## Overview The Waffo Pancake GraphQL API provides read-only access to all your data. Use it to query merchants, stores, products, orders, payments, and more. ``` POST /v1/graphql ``` **Authentication:** API Key The GraphQL API supports **queries only**. All write operations (create, update, delete) use the REST action endpoints. *** ## Making a Request ```typescript SDK theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); // Typed GraphQL queries interface StoresQuery { stores: Array<{ id: string; name: string; status: string }>; } const result = await client.graphql.query({ query: `{ stores { id name status } }`, }); // result.stores is fully typed ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/graphql \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "query": "{ stores { id name status } }" }' ``` ### Request Body | Field | Type | Required | Description | | ----------- | ------ | -------- | -------------------- | | `query` | string | Yes | GraphQL query string | | `variables` | object | No | Query variables | *** ## Available Queries ### Stores ```graphql theme={"dark"} query { stores { id name status createdAt updatedAt } } ``` ### One-Time Products ```graphql theme={"dark"} query($storeId: String!) { onetimeProducts(filter: { storeId: { eq: $storeId } }) { id name description prices status version media createdAt updatedAt } } ``` ### Subscription Products ```graphql theme={"dark"} query($storeId: String!) { subscriptionProducts(filter: { storeId: { eq: $storeId } }) { id name description billingPeriod prices status version createdAt updatedAt } } ``` ### Orders ```graphql theme={"dark"} query { orders { id status currency amount buyerEmail createdAt } } ``` ### Payments ```graphql theme={"dark"} query($paymentId: String!) { payments(filter: { id: { eq: $paymentId } }) { id orderId amount currency status createdAt } } ``` ### Refund Tickets ```graphql theme={"dark"} query { refundTickets { id paymentId status requestedAmount reason createdAt } } ``` ### Merchants ```graphql theme={"dark"} query { merchants { id email status createdAt } } ``` *** ## Filtering GraphQL queries support filters using typed filter objects: ### Filter Types | Type | Operators | Example | | ---------------- | ------------------------------ | -------------------------------------- | | `StringFilter` | `eq`, `ne`, `in`, `contains` | `{ storeId: { eq: "uuid" } }` | | `DateTimeFilter` | `eq`, `gt`, `lt`, `gte`, `lte` | `{ createdAt: { gte: "2026-01-01" } }` | | `IntFilter` | `eq`, `gt`, `lt`, `gte`, `lte` | `{ amount: { gte: 1000 } }` | | `BooleanFilter` | `eq` | `{ isActive: { eq: true } }` | ### Example with Filters ```graphql theme={"dark"} query { onetimeProducts( filter: { storeId: { eq: "store-uuid" } status: { eq: "active" } } ) { id name prices status } } ``` *** ## Pagination Use `limit` and `offset` for pagination. Use `*Count` queries to get total counts. ```graphql theme={"dark"} query { onetimeProducts( filter: { storeId: { eq: "store-uuid" } } limit: 10 offset: 0 ) { id name } onetimeProductsCount( filter: { storeId: { eq: "store-uuid" } } ) } ``` | Parameter | Type | Description | | --------- | ------- | ----------------------------------- | | `limit` | integer | Maximum number of results to return | | `offset` | integer | Number of results to skip | *** ## Environment-Specific Fields The `X-Environment` header affects which product data is returned: * `version` -- Returns the version for the specified environment * `status` -- Returns the status in the specified environment A product may be `active` in test but `inactive` in production if it hasn't been published yet. *** ## Example: Full Product Query with Variables ```bash theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/graphql \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "query": "query GetProducts($storeId: String!) { onetimeProducts(filter: { storeId: { eq: $storeId } }, limit: 20) { id name prices status version createdAt } onetimeProductsCount(filter: { storeId: { eq: $storeId } }) }", "variables": { "storeId": "your-store-uuid" } }' ``` ### SDK Example ```typescript theme={"dark"} // Query with variables and nested relationships const result = await client.graphql.query<{ store: { id: string; name: string; onetimeProducts: Array<{ id: string; name: string; prices: any }>; subscriptionProducts: Array<{ id: string; name: string; billingPeriod: string }>; }; }>({ query: `query ($id: ID!) { store(id: $id) { id name onetimeProducts { id name prices status } subscriptionProducts { id name billingPeriod status } } }`, variables: { id: "store-uuid" }, }); ``` # One-Time Product Endpoints Source: https://waffo.mintlify.app/api-reference/endpoints/onetime-products Create and manage single-purchase products ## Create Product Create a new one-time purchase product. ``` POST /v1/actions/onetime-product/create-product ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | ------------- | ------ | -------- | --------------------------------------- | | `storeId` | string | Yes | UUID of the store | | `name` | string | Yes | Product name | | `description` | string | No | Product description (supports Markdown) | | `prices` | object | Yes | Multi-currency pricing (see below) | | `media` | array | No | Product images/videos | | `successUrl` | string | No | Redirect URL after successful purchase | | `metadata` | object | No | Custom key-value data | ### Price Object Format Prices are a map of ISO 4217 currency codes to price info: ```json theme={"dark"} { "USD": { "amount": 2900, "taxIncluded": false, "taxCategory": "saas" }, "EUR": { "amount": 2700, "taxIncluded": true, "taxCategory": "saas" } } ``` | Field | Type | Description | | ------------- | ------- | ----------------------------------------------------------------------------------------------------------- | | `amount` | integer | Price in smallest currency unit (e.g., cents) | | `taxIncluded` | boolean | Whether the amount includes tax | | `taxCategory` | string | One of: `digital_goods`, `saas`, `software`, `ebook`, `online_course`, `consulting`, `professional_service` | ### Media Item Format ```json theme={"dark"} { "type": "image", "url": "https://example.com/product.png", "alt": "Product screenshot", "thumbnail": "https://example.com/product-thumb.png" } ``` | Field | Type | Description | | ----------- | ------ | -------------------------- | | `type` | string | `image` or `video` | | `url` | string | Media URL | | `alt` | string | Alt text for accessibility | | `thumbnail` | string | Thumbnail URL (optional) | ### Example Request ```typescript SDK theme={"dark"} import { WaffoPancake, TaxCategory } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); const { product } = await client.onetimeProducts.create({ storeId: "store-uuid", name: "Premium Template Pack", description: "50 premium design templates for your next project.", prices: { USD: { amount: 4900, taxIncluded: false, taxCategory: TaxCategory.DigitalGoods }, EUR: { amount: 4500, taxIncluded: true, taxCategory: TaxCategory.DigitalGoods }, }, successUrl: "https://example.com/thank-you", }); ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/onetime-product/create-product \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "storeId": "store-uuid", "name": "Premium Template Pack", "description": "50 premium design templates for your next project.", "prices": { "USD": { "amount": 4900, "taxIncluded": false, "taxCategory": "digital_goods" } }, "successUrl": "https://example.com/thank-you" }' ``` *** ## Update Product Update a product's content. If content has changed, a new immutable version is created automatically. ``` POST /v1/actions/onetime-product/update-product ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | ------------- | ------ | -------- | -------------------- | | `id` | string | Yes | Product UUID | | `name` | string | Yes | Updated product name | | `description` | string | No | Updated description | | `prices` | object | Yes | Updated pricing | | `media` | array | No | Updated media | | `successUrl` | string | No | Updated redirect URL | | `metadata` | object | No | Updated metadata | Product updates create **new immutable versions**. Existing orders and subscriptions retain their original version. New purchases use the latest version. *** ## Update Status Activate or deactivate a product. ``` POST /v1/actions/onetime-product/update-status ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | -------- | ------ | -------- | ---------------------- | | `id` | string | Yes | Product UUID | | `status` | string | Yes | `active` or `inactive` | ### Example Request ```typescript SDK theme={"dark"} import { ProductVersionStatus } from "@waffo/pancake-ts"; await client.onetimeProducts.updateStatus({ id: "product-uuid", status: ProductVersionStatus.Inactive, }); ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/onetime-product/update-status \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{"id": "product-uuid", "status": "inactive"}' ``` Setting a product to `inactive` hides it from checkout but does not affect existing orders. *** ## Publish Product Publish a product from test to production. This is a one-way operation that copies the current test version to production. ``` POST /v1/actions/onetime-product/publish-product ``` **Authentication:** API Key Do **not** include the `X-Environment` header for this endpoint. Publishing is always one-way from test to production. ### Request Body | Field | Type | Required | Description | | ----- | ------ | -------- | ------------ | | `id` | string | Yes | Product UUID | ### Example Request ```typescript SDK theme={"dark"} await client.onetimeProducts.publish({ id: "product-uuid" }); ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/onetime-product/publish-product \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{"id": "product-uuid"}' ``` This enables a workflow where you develop and test products in the test environment, then promote them to production when ready. Only the first publish is supported. Once a product has been published to production, subsequent updates in test are not automatically synced. # Order Endpoints Source: https://waffo.mintlify.app/api-reference/endpoints/orders Create checkout sessions and manage orders ## Create Checkout Session Create a checkout session that locks product version, pricing, and currency. This is the first step in the checkout flow for both one-time and subscription products. ``` POST /v1/actions/checkout/create-session ``` **Authentication:** API Key or Store Slug ### Request Body (API Key) | Field | Type | Required | Description | | ------------------ | ------- | -------- | ---------------------------------------- | | `storeId` | string | Yes | UUID of the store | | `productId` | string | Yes | UUID of the product | | `productType` | string | Yes | `onetime` or `subscription` | | `currency` | string | Yes | ISO 4217 currency code | | `withTrial` | boolean | No | Enable trial period (subscriptions only) | | `buyerEmail` | string | No | Pre-fill buyer's email | | `billingDetail` | object | No | Pre-fill billing details | | `successUrl` | string | No | Override redirect URL on success | | `expiresInSeconds` | number | No | Custom session TTL | | `metadata` | object | No | Custom key-value data | | `priceSnapshot` | object | No | Override pricing (API Key only) | ### Request Body (Store Slug) | Field | Type | Required | Description | | --------------- | ------- | -------- | --------------------------- | | `productId` | string | Yes | UUID of the product | | `productType` | string | Yes | `onetime` or `subscription` | | `currency` | string | Yes | ISO 4217 currency code | | `billingDetail` | object | No | Pre-fill billing details | | `buyerEmail` | string | No | Pre-fill buyer's email | | `withTrial` | boolean | No | Enable trial period | | `successUrl` | string | No | Override redirect URL | | `metadata` | object | No | Custom key-value data | Store Slug authentication does not support `priceSnapshot` to prevent price tampering from the client side. ### Example Request ```typescript SDK theme={"dark"} import { WaffoPancake, CheckoutSessionProductType } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); const session = await client.checkout.createSession({ storeId: "store-uuid", productId: "product-uuid", productType: CheckoutSessionProductType.Onetime, currency: "USD", buyerEmail: "customer@example.com", successUrl: "https://example.com/thank-you", }); // => session.checkoutUrl, session.sessionId, session.expiresAt ``` ```bash API Key theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/checkout/create-session \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "storeId": "store-uuid", "productId": "product-uuid", "productType": "onetime", "currency": "USD" }' ``` ```bash Store Slug theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/checkout/create-session \ -H "X-Store-Slug: my-store-abc123" \ -H "X-Environment: test" \ -H "Content-Type: application/json" \ -d '{ "productId": "product-uuid", "productType": "onetime", "currency": "USD" }' ``` ### Success Response ```json theme={"dark"} { "data": { "sessionId": "session-uuid", "checkoutUrl": "https://checkout.waffo.ai/store-slug/checkout/session-uuid", "expiresAt": "2026-01-22T10:30:00.000Z" } } ``` Checkout sessions have a 7-day TTL. The session locks the product version and pricing at creation time, so price changes won't affect existing sessions. *** ## Preview Tax Preview tax calculation for a checkout session before creating the order. ``` POST /v1/actions/checkout/preview-tax ``` **Authentication:** Store Slug ### Request Body | Field | Type | Required | Description | | ------------------- | ------ | -------- | ----------------------------------- | | `checkoutSessionId` | string | Yes | UUID of the checkout session | | `billingDetail` | object | Yes | Billing details for tax calculation | ### Billing Detail | Field | Type | Required | Description | | -------------- | ------- | ----------- | ----------------------------------- | | `country` | string | Yes | ISO 3166-1 alpha-2 country code | | `isBusiness` | boolean | Yes | Whether this is a business purchase | | `state` | string | Conditional | Required for US, CA | | `businessName` | string | No | Business name | | `taxId` | string | No | Tax ID (for EU B2B exemption) | ### Success Response ```json theme={"dark"} { "data": { "subtotal": 2900, "taxAmount": 261, "total": 3161, "taxRate": 0.09 } } ``` *** ## Create One-Time Order Create an order for a one-time product using a checkout session. ``` POST /v1/actions/onetime-order/create-order ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | ------------------- | ------ | -------- | ---------------------------------------- | | `checkoutSessionId` | string | Yes | UUID of the checkout session | | `billingDetail` | object | Yes | Billing details | | `buyerEmail` | string | No | Buyer's email address | | `buyerIp` | string | No | Buyer's IP address (for tax calculation) | | `successUrl` | string | No | Override redirect URL on success | ### Billing Detail | Field | Type | Required | Description | | -------------- | ------- | ----------- | --------------------------------------- | | `country` | string | Yes | ISO 3166-1 alpha-2 country code | | `isBusiness` | boolean | Yes | Whether this is a business purchase | | `state` | string | Conditional | Required for US, CA | | `postcode` | string | No | Postal/ZIP code | | `businessName` | string | No | Business name (when `isBusiness: true`) | | `taxId` | string | No | Tax ID (required for EU B2B) | ### Example Request ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/onetime-order/create-order \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "checkoutSessionId": "session-uuid", "billingDetail": { "country": "US", "isBusiness": false, "state": "CA", "postcode": "94105" }, "buyerEmail": "customer@example.com" }' ``` ```javascript Node.js theme={"dark"} // Use the @waffo/pancake-ts SDK for automatic request signing import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); const { checkoutUrl } = await client.orders.createOnetimeOrder({ checkoutSessionId: "session-uuid", billingDetail: { country: "US", isBusiness: false, state: "CA", postcode: "94105", }, buyerEmail: "customer@example.com", }); // Redirect buyer to checkoutUrl ``` ### Success Response ```json theme={"dark"} { "data": { "checkoutUrl": "https://checkout.waffo.ai/store-slug/checkout/token" } } ``` Redirect the buyer to `checkoutUrl` to complete payment. The checkout page handles payment collection, tax calculation, and 3D Secure authentication. *** ## Cancel One-Time Order Cancel a pending (unpaid) order. ``` POST /v1/actions/onetime-order/cancel-order ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | --------- | ------ | -------- | --------------------------- | | `orderId` | string | Yes | UUID of the order to cancel | ### Success Response ```json theme={"dark"} { "data": { "orderId": "order-uuid", "status": "canceled" } } ``` Only orders with `pending` status can be canceled. Completed orders require a refund request instead. *** ## One-Time Order Status Values | Status | Description | | ----------- | ---------------------------------------- | | `pending` | Order created, payment not yet completed | | `completed` | Payment successful, order fulfilled | | `canceled` | Order canceled before payment | # Refund Endpoints Source: https://waffo.mintlify.app/api-reference/endpoints/refunds Request and manage refunds ## Create Refund Ticket Request a refund for a payment. The refund goes through a review workflow. ``` POST /v1/actions/refund-ticket/create-ticket ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | ----------- | ------- | -------- | ---------------------------------------------------------------------- | | `paymentId` | string | Yes | UUID of the payment to refund | | `reason` | string | Yes | Reason for the refund request | | `amount` | integer | No | Partial refund amount in smallest currency unit (omit for full refund) | ### Example Request ```bash cURL (Full Refund) theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/refund-ticket/create-ticket \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "paymentId": "payment-uuid", "reason": "Product did not meet expectations" }' ``` ```bash cURL (Partial Refund) theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/refund-ticket/create-ticket \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "paymentId": "payment-uuid", "reason": "Partial service used", "amount": 1500 }' ``` ### Success Response ```json theme={"dark"} { "data": { "ticketId": "refund-ticket-uuid", "status": "pending", "requestedAmount": 2900 } } ``` *** ## Refund Ticket Status Values | Status | Description | | ------------ | ----------------------------------------- | | `pending` | Refund request submitted, awaiting review | | `approved` | Refund approved, awaiting processing | | `rejected` | Refund request denied | | `processing` | Refund is being processed | | `succeeded` | Refund completed, funds returned | | `failed` | Refund processing failed | *** ## Business Rules * One-time product refunds must be requested within **7 days** of payment * Partial refunds cannot exceed the original payment amount * Each payment can have multiple refund tickets (for partial refunds) *** ## Refund Workflow ``` Refund request submitted (pending) | v Merchant reviews | +-- Approve --> processing --> succeeded (funds returned) | --> failed (retry needed) | +-- Reject --> rejected ``` Use GraphQL to query refund tickets and their current status. Filter by `storeId`, `paymentId`, or `status` to find specific tickets. # Store Endpoints Source: https://waffo.mintlify.app/api-reference/endpoints/stores Create, update, and manage stores ## Create Store Create a new store for a merchant. ``` POST /v1/actions/store/create-store ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | ------ | ------ | -------- | ----------------------------- | | `name` | string | Yes | Store name (1-100 characters) | ### Example Request ```typescript SDK theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); const { store } = await client.stores.create({ name: "My Digital Store" }); ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/store/create-store \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{"name": "My Digital Store"}' ``` ### Success Response ```json theme={"dark"} { "data": { "store": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "My Digital Store", "status": "active", "createdAt": "2026-01-15T10:30:00.000Z", "updatedAt": "2026-01-15T10:30:00.000Z" } } } ``` Each merchant can create up to **20 stores**. The store creator is automatically assigned the `owner` role. *** ## Update Store Update an existing store's name or status. ``` POST /v1/actions/store/update-store ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | -------- | ------ | -------- | ------------------------------------ | | `id` | string | Yes | Store UUID | | `name` | string | No | New store name (1-100 characters) | | `status` | string | No | `active`, `inactive`, or `suspended` | ### Example Request ```typescript SDK theme={"dark"} const { store } = await client.stores.update({ id: "store-uuid", name: "Updated Store Name", supportEmail: "help@example.com", webhookSettings: { testWebhookUrl: "https://example.com/webhooks", prodWebhookUrl: null, }, }); ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/store/update-store \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "id": "store-uuid", "name": "Updated Store Name", "status": "active" }' ``` ### Store Roles and Permissions | Role | Create | Update | Delete | Read | | -------- | ------ | ------ | ------ | ---- | | `owner` | -- | Yes | Yes | Yes | | `admin` | -- | Yes | No | Yes | | `member` | -- | No | No | Yes | *** ## Delete Store Soft-delete a store. Only the store owner can perform this action. ``` POST /v1/actions/store/delete-store ``` **Authentication:** API Key (owner role required) ### Request Body | Field | Type | Required | Description | | ----- | ------ | -------- | -------------------- | | `id` | string | Yes | Store UUID to delete | ### Example Request ```typescript SDK theme={"dark"} const { store } = await client.stores.delete({ id: "store-uuid" }); ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/store/delete-store \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{"id": "store-uuid"}' ``` Deleting a store is a soft delete. The store data is retained but the store becomes inaccessible. This action cannot be undone through the API. *** ## Store Status Values | Status | Description | | ----------- | --------------------------------------- | | `active` | Store is live and operational | | `inactive` | Store is disabled but data is preserved | | `suspended` | Store is suspended (typically by admin) | # Subscription Product Endpoints Source: https://waffo.mintlify.app/api-reference/endpoints/subscription-products Create and manage subscription products and product groups ## Create Subscription Product Create a subscription product with a billing period and multi-currency pricing. ``` POST /v1/actions/subscription-product/create-product ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | --------------- | ------ | -------- | --------------------------------------------------------------------------------------------------- | | `storeId` | string | Yes | UUID of the store | | `name` | string | Yes | Product name | | `billingPeriod` | string | Yes | `weekly`, `monthly`, `quarterly`, or `yearly` | | `prices` | object | Yes | Multi-currency pricing (see [Price Format](/api-reference/endpoints/onetime-products#price-format)) | | `description` | string | No | Product description | | `media` | array | No | Product images/videos | | `successUrl` | string | No | Redirect URL after subscription | | `metadata` | object | No | Custom key-value data | ### Example Request ```typescript SDK theme={"dark"} import { WaffoPancake, BillingPeriod, TaxCategory } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); const { product } = await client.subscriptionProducts.create({ storeId: "store-uuid", name: "Pro Plan", billingPeriod: BillingPeriod.Monthly, prices: { USD: { amount: 2900, taxIncluded: false, taxCategory: TaxCategory.SaaS }, EUR: { amount: 2700, taxIncluded: false, taxCategory: TaxCategory.SaaS }, }, }); ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/subscription-product/create-product \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "storeId": "store-uuid", "name": "Pro Plan", "billingPeriod": "monthly", "prices": { "USD": { "amount": 2900, "taxIncluded": false, "taxCategory": "saas" }, "EUR": { "amount": 2700, "taxIncluded": false, "taxCategory": "saas" } } }' ``` ### Success Response ```json theme={"dark"} { "data": { "id": "product-uuid", "storeId": "store-uuid", "prodVersionId": null, "testVersionId": "version-uuid", "prodStatus": "inactive", "testStatus": "active", "createdAt": "2026-01-15T10:30:00.000Z", "updatedAt": "2026-01-15T10:30:00.000Z", "version": { "id": "version-uuid", "productId": "product-uuid", "versionNumber": 1, "name": "Pro Plan", "description": null, "prices": { "USD": { "amount": 2900, "taxIncluded": false, "taxCategory": "saas" }, "EUR": { "amount": 2700, "taxIncluded": false, "taxCategory": "saas" } }, "media": [], "successUrl": null, "metadata": null, "createdAt": "2026-01-15T10:30:00.000Z" } } } ``` ### Billing Periods | Period | Frequency | | ----------- | -------------------- | | `weekly` | Every 7 days | | `monthly` | Every calendar month | | `quarterly` | Every 3 months | | `yearly` | Every 12 months | *** ## Update Subscription Product Update a subscription product's content. Creates a new immutable version if content has changed. ``` POST /v1/actions/subscription-product/update-product ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | --------------- | ------ | -------- | --------------------------------------------- | | `id` | string | Yes | Product UUID | | `name` | string | Yes | Updated product name | | `billingPeriod` | string | Yes | `weekly`, `monthly`, `quarterly`, or `yearly` | | `prices` | object | Yes | Updated multi-currency pricing | | `description` | string | No | Updated description | | `media` | array | No | Updated media | | `successUrl` | string | No | Updated redirect URL | | `metadata` | object | No | Updated metadata | *** ## Update Status Activate or deactivate a subscription product. ``` POST /v1/actions/subscription-product/update-status ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | -------- | ------ | -------- | ---------------------- | | `id` | string | Yes | Product UUID | | `status` | string | Yes | `active` or `inactive` | Deactivating a subscription product prevents new signups but does not cancel existing active subscriptions. *** ## Publish Product Publish a subscription product from test to production environment. This is a one-way operation. ``` POST /v1/actions/subscription-product/publish-product ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | ----- | ------ | -------- | ------------ | | `id` | string | Yes | Product UUID | Publishing copies the current test version to production. This action is only available for the first publish. Subsequent version updates in test require re-publishing. *** ## Subscription Product Groups Product groups organize related subscription products (e.g., Free, Pro, Enterprise plans) and enable shared trial management. ### Create Group ``` POST /v1/actions/subscription-product-group/create-group ``` **Authentication:** API Key #### Request Body | Field | Type | Required | Description | | ------------- | ------ | -------- | ---------------------------------------------- | | `storeId` | string | Yes | UUID of the store | | `name` | string | Yes | Group name (e.g., "Pricing Plans") | | `description` | string | No | Group description | | `rules` | object | No | Group rules (see below) | | `productIds` | array | No | Array of subscription product UUIDs to include | #### Rules | Field | Type | Default | Description | | ------------- | ------- | ------- | ----------------------------------------------------------------- | | `sharedTrial` | boolean | false | When true, trial usage is shared across all products in the group | #### Example Request ```typescript SDK theme={"dark"} const { group } = await client.subscriptionProductGroups.create({ storeId: "store-uuid", name: "Pricing Plans", description: "Free, Pro, and Enterprise tiers", rules: { sharedTrial: true }, productIds: ["product-uuid-1", "product-uuid-2", "product-uuid-3"], }); ``` ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/subscription-product-group/create-group \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "storeId": "store-uuid", "name": "Pricing Plans", "description": "Free, Pro, and Enterprise tiers", "rules": { "sharedTrial": true }, "productIds": ["product-uuid-1", "product-uuid-2", "product-uuid-3"] }' ``` #### Success Response ```json theme={"dark"} { "data": { "group": { "id": "group-uuid", "storeId": "store-uuid", "name": "Pricing Plans", "description": "Free, Pro, and Enterprise tiers", "rules": { "sharedTrial": true }, "productIds": ["product-uuid-1", "product-uuid-2", "product-uuid-3"], "environment": "test", "createdAt": "2026-01-15T10:30:00.000Z", "updatedAt": "2026-01-15T10:30:00.000Z" } } } ``` ### Update Group ``` POST /v1/actions/subscription-product-group/update-group ``` **Authentication:** API Key #### Request Body | Field | Type | Required | Description | | ------------- | ------ | -------- | ------------------------------------------- | | `id` | string | Yes | Group UUID | | `name` | string | No | Updated group name | | `description` | string | No | Updated description | | `rules` | object | No | Updated rules | | `productIds` | array | No | Updated product list (replaces entire list) | The `productIds` field replaces the entire product list. To add a product, include all existing product IDs plus the new one. ### Delete Group ``` POST /v1/actions/subscription-product-group/delete-group ``` **Authentication:** API Key #### Request Body | Field | Type | Required | Description | | ----- | ------ | -------- | ----------- | | `id` | string | Yes | Group UUID | This is a permanent deletion (not soft delete). The products within the group are not deleted — only the grouping is removed. ### Publish Group ``` POST /v1/actions/subscription-product-group/publish-group ``` **Authentication:** API Key #### Request Body | Field | Type | Required | Description | | ----- | ------ | -------- | ----------- | | `id` | string | Yes | Group UUID | Unlike product publishing, group publishing supports repeated UPSERT operations. You can re-publish a group after making changes. # Subscription Order Endpoints Source: https://waffo.mintlify.app/api-reference/endpoints/subscriptions Create and manage subscription orders ## Create Subscription Order Create a subscription order using a checkout session. Requires a checkout session created via [Create Checkout Session](/api-reference/endpoints/orders#create-checkout-session). ``` POST /v1/actions/subscription-order/create-order ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | ------------------- | ------ | -------- | -------------------------------- | | `checkoutSessionId` | string | Yes | UUID of the checkout session | | `billingDetail` | object | Yes | Billing details (see below) | | `buyerEmail` | string | No | Buyer's email address | | `buyerIp` | string | No | Buyer's IP address | | `successUrl` | string | No | Override redirect URL on success | ### Billing Detail | Field | Type | Required | Description | | -------------- | ------- | ----------- | --------------------------------------- | | `country` | string | Yes | ISO 3166-1 alpha-2 country code | | `isBusiness` | boolean | Yes | Whether this is a business purchase | | `state` | string | Conditional | Required for US, CA | | `postcode` | string | No | Postal/ZIP code | | `businessName` | string | No | Business name (when `isBusiness: true`) | | `taxId` | string | No | Tax ID (required for EU B2B) | ### Example Request ```bash theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/subscription-order/create-order \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "checkoutSessionId": "session-uuid", "billingDetail": { "country": "US", "isBusiness": false, "state": "CA", "postcode": "94105" }, "buyerEmail": "customer@example.com" }' ``` ### Success Response ```json theme={"dark"} { "data": { "checkoutUrl": "https://checkout.waffo.ai/store-slug/checkout/token" } } ``` Redirect the buyer to `checkoutUrl` to complete payment. The checkout session locks the product version, pricing, and currency at creation time. *** ## Cancel Subscription Cancel an active subscription. The subscription enters `canceling` status and remains active until the end of the current billing period, when it transitions to `canceled`. ``` POST /v1/actions/subscription-order/cancel-order ``` **Authentication:** API Key ### Request Body | Field | Type | Required | Description | | --------- | ------ | -------- | ------------------------------ | | `orderId` | string | Yes | UUID of the subscription order | ### Example Request ```bash theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/subscription-order/cancel-order \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{"orderId": "subscription-order-uuid"}' ``` ### Success Response ```json theme={"dark"} { "data": { "orderId": "subscription-order-uuid", "status": "canceling" } } ``` The subscriber retains access until the end of the current billing period. The status changes from `canceling` to `canceled` when the period ends. No further charges will be made. *** ## Change Product Change a subscription to a different product (upgrade/downgrade). ``` POST /v1/actions/subscription-order/change-product ``` **Authentication:** API Key This endpoint is not yet implemented (returns 501). It will be available in a future release. ### Request Body | Field | Type | Required | Description | | ----------------- | ------ | -------- | --------------------------------------- | | `orderId` | string | Yes | UUID of the current subscription order | | `targetProductId` | string | Yes | UUID of the target subscription product | *** ## Reactivate Subscription Reactivate a canceled subscription. ``` POST /v1/actions/subscription-order/reactivate-order ``` **Authentication:** API Key This endpoint is not yet implemented (returns 501). It will be available in a future release. ### Request Body | Field | Type | Required | Description | | ------------- | ------ | -------- | ------------------------------ | | `orderId` | string | Yes | UUID of the subscription order | | `productName` | string | Yes | Product name for confirmation | *** ## Subscription Status Values | Status | Description | | ----------- | ----------------------------------------------- | | `pending` | Subscription created, awaiting first payment | | `active` | Active and billing normally | | `trialing` | In free trial period | | `canceling` | Cancellation requested, active until period end | | `past_due` | Payment failed, retrying | | `canceled` | Subscription ended, no further billing | | `expired` | Subscription expired | # Errors Source: https://waffo.mintlify.app/api-reference/errors Handle API errors gracefully ## Error Format All error responses follow a consistent structure: ```json theme={"dark"} { "data": null, "errors": [ { "message": "Missing required field: name", "layer": "product" } ] } ``` ### Reading the Errors Array The `errors` array is ordered from root cause to top-level caller: * `errors[0]` -- the **root cause** of the failure (most useful for debugging) * `errors[n]` -- the top-level caller that surfaced the error In most cases, you only need to inspect `errors[0].message` for the actionable error description. *** ## HTTP Status Codes | Code | Meaning | Description | | ---- | --------------- | ---------------------------------------------- | | 200 | Success | Request processed successfully | | 400 | Bad Request | Invalid parameters or malformed request body | | 401 | Unauthorized | Missing or invalid authentication credentials | | 403 | Forbidden | Valid credentials but insufficient permissions | | 404 | Not Found | Requested resource does not exist | | 409 | Conflict | Idempotent request is already being processed | | 429 | Rate Limited | Too many requests in a short period | | 500 | Server Error | Internal server error | | 501 | Not Implemented | Requested feature is not yet available | | 502 | Bad Gateway | Upstream service error | *** ## Error Layers Each error includes a `layer` field indicating where in the system the error originated: | Layer | Description | Common Causes | | --------- | ------------------------------ | ---------------------------------------- | | `gateway` | Request routing | Invalid URL, server unavailable | | `user` | Authentication / authorization | Expired token, wrong role | | `store` | Store operations | Missing store, permission denied | | `product` | Product operations | Invalid prices, missing fields | | `order` | Order operations | Invalid product version, checkout errors | | `graphql` | GraphQL queries | Invalid query, unknown fields | *** ## Common Error Scenarios ### Authentication Errors (401) ```json theme={"dark"} { "data": null, "errors": [ { "message": "Token has expired", "layer": "user" } ] } ``` **Solutions:** * Verify your Merchant ID and private key are correct * Ensure the SDK is initialized with valid credentials * Check that your private key matches the registered public key ### Validation Errors (400) ```json theme={"dark"} { "data": null, "errors": [ { "message": "Store name must be between 1 and 100 characters", "layer": "store" } ] } ``` **Solutions:** * Check required fields are present * Verify field value formats and constraints * Ensure amounts are in smallest currency units (integers) ### Permission Errors (403) ```json theme={"dark"} { "data": null, "errors": [ { "message": "Only store owner can delete store", "layer": "store" } ] } ``` **Solutions:** * Verify the API Key has the required permissions * Ensure the user belongs to the correct store ### Idempotency Conflicts (409) ```json theme={"dark"} { "data": null, "errors": [ { "message": "Request with this idempotency key is already being processed", "layer": "gateway" } ] } ``` **Solutions:** * Wait for the original request to complete * Use a different `X-Idempotency-Key` for a new request *** ## Handling Errors in Code ### TypeScript SDK ```typescript theme={"dark"} import { WaffoPancake, WaffoPancakeError } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); try { const { store } = await client.stores.create({ name: "My Store" }); } catch (err) { if (err instanceof WaffoPancakeError) { const rootCause = err.errors[0]; console.error(`Error [${rootCause.layer}]: ${rootCause.message}`); // err.status contains the HTTP status code } } ``` *** ## Retry Strategy Retry these status codes with exponential backoff: * **429** -- Rate limited (respect `Retry-After` header if present) * **500** -- Internal server error * **502** -- Bad gateway ```javascript theme={"dark"} async function retryRequest(fn, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { try { return await fn(); } catch (error) { const status = error.status; if (![429, 500, 502].includes(status) || attempt === maxRetries - 1) { throw error; } const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s await new Promise(resolve => setTimeout(resolve, delay)); } } } ``` Do not retry `400`, `401`, `403`, or `404` errors. These indicate issues that must be fixed in the request itself. *** ## Idempotency for Safe Retries Use the `X-Idempotency-Key` header to safely retry write operations without creating duplicates: ```bash theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/checkout/create-session \ -H "Content-Type: application/json" \ -H "X-Store-Slug: your-store-slug" \ -H "X-Environment: test" \ -H "X-Idempotency-Key: order-abc-123" \ -d '{"productId": "...", "productType": "onetime", "currency": "USD"}' ``` * Idempotency keys are cached for **24 hours** * Sending the same key returns the cached response * If the original request is still processing, returns `409 Conflict` # API Reference Source: https://waffo.mintlify.app/api-reference/introduction Integrate Waffo Pancake into your application ## Overview The Waffo Pancake API lets you programmatically manage your entire payment infrastructure: * Create and manage stores * Create products (one-time and subscription) * Generate checkout sessions and process orders * Manage subscriptions and billing * Query data via GraphQL * Handle refunds ## Base URL All API requests are made to: ``` https://waffo-pancake-auth-service.vercel.app/v1 ``` ## Architecture The API uses a hybrid approach: * **REST endpoints** (`/v1/actions/...`) for all write operations (create, update, delete) * **GraphQL** (`/v1/graphql`) for all read operations (queries) All REST endpoints use `POST` method exclusively. There are no GET, PUT, PATCH, or DELETE methods. ## TypeScript SDK The official [`@waffo/pancake-ts`](https://www.npmjs.com/package/@waffo/pancake-ts) SDK wraps the entire API with full type safety. It handles authentication, request signing, idempotency keys, and webhook verification automatically. ```bash theme={"dark"} npm install @waffo/pancake-ts ``` ```typescript theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); ``` Every endpoint documented below includes an SDK example alongside the REST/cURL examples. [Full SDK documentation →](/integrate/sdks) *** ## Authentication Waffo Pancake uses **API Key authentication** for all programmatic API access. API Keys provide secure server-to-server communication. API Key authentication is handled automatically by the SDK. Install `@waffo/pancake-ts`, provide your Merchant ID and private key, and the SDK will handle request signing automatically. For public-facing checkout flows, use **Store Slug** authentication with the `X-Store-Slug` header. [Learn more about authentication -->](/api-reference/authentication) *** ## Common Headers | Header | Required | Description | | ------------------- | ----------- | ------------------------------------------------ | | `Content-Type` | Yes | Always `application/json` | | `X-Store-Slug` | Conditional | Store slug (for public checkout flows) | | `X-Environment` | Conditional | `test` or `prod` (required with Store Slug auth) | | `X-Idempotency-Key` | Optional | Unique ID for write operations (cached 24h) | *** ## Request Format * **Method**: All write endpoints use `POST` * **Body**: JSON * **IDs**: UUID v4 format (e.g., `550e8400-e29b-41d4-a716-446655440000`) * **Timestamps**: ISO 8601 UTC (e.g., `2026-01-23T00:00:00.000Z`) * **Amounts**: Smallest currency unit as integers (e.g., `2900` = \$29.00 USD) * **Currencies**: ISO 4217 codes (e.g., `USD`, `EUR`, `JPY`) * **Status values**: Always lowercase (e.g., `active`, not `ACTIVE`) ### Example Request ```typescript theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); const { store } = await client.stores.create({ name: "My Store" }); ``` *** ## Response Format ### Success ```json theme={"dark"} { "data": { "store": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "My Store", "status": "active", "createdAt": "2026-01-15T10:30:00.000Z", "updatedAt": "2026-01-15T10:30:00.000Z" } } } ``` ### Error ```json theme={"dark"} { "data": null, "errors": [ { "message": "Store name is required", "layer": "store" } ] } ``` In the `errors` array, `errors[0]` is the **root cause** of the failure. Subsequent entries represent higher-level callers in the request chain. ### Error Layers | Layer | Description | | --------- | ------------------------------------ | | `gateway` | Request routing / infrastructure | | `user` | User authentication or authorization | | `store` | Store operations | | `product` | Product operations | | `order` | Order operations | | `graphql` | GraphQL query errors | *** ## HTTP Status Codes | Code | Description | | ---- | -------------------------------------------------- | | 200 | Success | | 400 | Bad Request -- invalid parameters | | 401 | Unauthorized -- authentication failed | | 403 | Forbidden -- insufficient permissions | | 404 | Not Found | | 409 | Conflict -- idempotent request already in progress | | 429 | Rate Limited -- too many requests | | 500 | Internal Server Error | | 501 | Not Implemented | | 502 | Bad Gateway | *** ## Environments Switch between test and production using the `X-Environment` header: | Environment | Header Value | Description | | ----------- | --------------------- | ------------------------------ | | Test | `X-Environment: test` | No real charges, isolated data | | Production | `X-Environment: prod` | Real transactions | API Key authentication does not require the `X-Environment` header -- the environment is determined by the key's registered environment. The `X-Environment` header is required when using Store Slug authentication. *** ## Idempotency Prevent duplicate write operations by including an `X-Idempotency-Key` header: ```bash theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/checkout/create-session \ -H "Content-Type: application/json" \ -H "X-Store-Slug: your-store-slug" \ -H "X-Environment: test" \ -H "X-Idempotency-Key: unique-request-id-12345" \ -d '{"productId": "...", "productType": "onetime", "currency": "USD"}' ``` * Keys are cached for **24 hours** * Same key returns the same response without re-executing * If the original request is still processing, returns `409 Conflict` *** ## Endpoint Groups API Key signatures and Store Slug auth Create, update, and delete stores Create and manage one-time purchase products Create tiered subscription products Create orders and checkout sessions Manage subscription lifecycle Request and process refunds Query data with GraphQL # Webhooks Source: https://waffo.mintlify.app/api-reference/webhooks Receive real-time event notifications ## Overview Webhooks push events to your server in real-time. No polling needed. ``` Your App <-- Webhook <-- Waffo Pancake ``` When an event occurs (order completed, subscription activated, etc.), Waffo Pancake sends an HTTP POST request to your registered endpoint with the event data. *** ## Setup Build an HTTPS endpoint that accepts POST requests. Go to [Dashboard --> Developers --> Webhooks](https://dashboard.waffo.ai/settings/developers) Choose which events to receive. Save your webhook configuration. *** ## Event Types ### Order Events | Event | Description | | ----------------- | ---------------------------- | | `order.completed` | Order completed successfully | ### Subscription Events | Event | Description | | -------------------------------- | ----------------------------------- | | `subscription.activated` | Subscription activated | | `subscription.payment_succeeded` | Subscription payment succeeded | | `subscription.updated` | Subscription updated | | `subscription.canceling` | Subscription cancellation requested | | `subscription.uncanceled` | Subscription reactivated | | `subscription.canceled` | Subscription canceled | | `subscription.past_due` | Subscription payment past due | ### Refund Events | Event | Description | | ------------------ | ----------------------------- | | `refund.succeeded` | Refund processed successfully | | `refund.failed` | Refund processing failed | *** ## Payload Format Webhook payloads follow the standard Waffo Pancake API response format: ```json theme={"dark"} { "event": "order.completed", "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "orderId": "660e8400-e29b-41d4-a716-446655440001", "amount": 2900, "currency": "USD", "status": "completed", "createdAt": "2026-01-15T10:30:00.000Z" } } ``` All IDs are UUID v4 format. Amounts are in the smallest currency unit (e.g., 2900 = \$29.00). Timestamps are ISO 8601 UTC. ### Subscription Event Example ```json theme={"dark"} { "event": "subscription.activated", "data": { "id": "770e8400-e29b-41d4-a716-446655440002", "status": "active", "billingPeriod": "monthly", "amount": 2900, "currency": "USD", "currentPeriodEnd": "2026-02-15T10:30:00.000Z" } } ``` ### Refund Event Example ```json theme={"dark"} { "event": "refund.succeeded", "data": { "id": "880e8400-e29b-41d4-a716-446655440003", "paymentId": "550e8400-e29b-41d4-a716-446655440000", "amount": 2900, "currency": "USD", "status": "succeeded", "createdAt": "2026-01-20T14:00:00.000Z" } } ``` *** ## Respond Correctly Return `200 OK` quickly. Process asynchronously if your handler needs to do heavy work. ```typescript SDK (Next.js App Router) theme={"dark"} import { verifyWebhook, WebhookEventType } from "@waffo/pancake-ts"; export async function POST(req: Request) { const body = await req.text(); const signature = req.headers.get("x-signature") ?? ""; const timestamp = req.headers.get("x-timestamp") ?? ""; // Built-in signature verification — no webhook secret needed const { event, data } = verifyWebhook({ body, signature, timestamp, environment: "test", // or "prod" }); switch (event) { case WebhookEventType.OrderCompleted: await handleOrderCompleted(data); break; case WebhookEventType.SubscriptionActivated: await handleSubscriptionActivated(data); break; case WebhookEventType.SubscriptionPaymentSucceeded: await handleSubscriptionPaymentSucceeded(data); break; case WebhookEventType.SubscriptionCanceling: await handleSubscriptionCanceling(data); break; case WebhookEventType.SubscriptionCanceled: await handleSubscriptionCanceled(data); break; case WebhookEventType.SubscriptionPastDue: await handleSubscriptionPastDue(data); break; case WebhookEventType.RefundSucceeded: await handleRefundSucceeded(data); break; case WebhookEventType.RefundFailed: await handleRefundFailed(data); break; } return new Response("OK", { status: 200 }); } ``` ```javascript Node.js (Express) theme={"dark"} app.post('/webhooks/waffo', (req, res) => { // Respond immediately res.status(200).send('OK'); // Process async const { event, data } = req.body; switch (event) { case 'order.completed': handleOrderCompleted(data); break; case 'subscription.activated': handleSubscriptionActivated(data); break; case 'subscription.payment_succeeded': handleSubscriptionPaymentSucceeded(data); break; case 'subscription.canceling': handleSubscriptionCanceling(data); break; case 'subscription.canceled': handleSubscriptionCanceled(data); break; case 'subscription.past_due': handleSubscriptionPastDue(data); break; case 'refund.succeeded': handleRefundSucceeded(data); break; case 'refund.failed': handleRefundFailed(data); break; } }); ``` ```python Python (Flask) theme={"dark"} from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/webhooks/waffo', methods=['POST']) def handle_webhook(): payload = request.get_json() event = payload.get('event') data = payload.get('data') if event == 'order.completed': handle_order_completed(data) elif event == 'subscription.activated': handle_subscription_activated(data) elif event == 'subscription.payment_succeeded': handle_subscription_payment_succeeded(data) elif event == 'subscription.canceling': handle_subscription_canceling(data) elif event == 'subscription.canceled': handle_subscription_canceled(data) elif event == 'subscription.past_due': handle_subscription_past_due(data) elif event == 'refund.succeeded': handle_refund_succeeded(data) elif event == 'refund.failed': handle_refund_failed(data) return jsonify({'received': True}), 200 ``` The TypeScript SDK's `verifyWebhook()` function handles signature verification with embedded public keys for both test and production environments. No webhook secret configuration needed -- just pass the request body, signature header, timestamp header, and environment. *** ## Retry Policy Failed deliveries retry automatically: | Attempt | Delay | | ------- | ---------- | | 1 | Immediate | | 2 | 5 minutes | | 3 | 30 minutes | | 4 | 2 hours | | 5 | 24 hours | After 5 failures, the webhook is disabled. Re-enable in the Dashboard. *** ## Idempotency Events may be delivered more than once. Use the event data (such as the order or payment ID) for deduplication to ensure your handler processes each event only once. ```javascript theme={"dark"} const processedEvents = new Set(); app.post('/webhooks/waffo', (req, res) => { const { event, data } = req.body; const eventKey = `${event}:${data.id}`; if (processedEvents.has(eventKey)) { return res.status(200).send('Already processed'); } processedEvents.add(eventKey); res.status(200).send('OK'); // Process the event processWebhook(event, data); }); ``` For production, store processed event IDs in a database instead of in-memory to persist across server restarts. *** ## Best Practices 1. **Use HTTPS** -- Required for production webhook endpoints 2. **Respond fast** -- Return 200 within 30 seconds; process heavy work asynchronously 3. **Handle duplicates** -- Events may be retried; use IDs for deduplication 4. **Process async** -- Do not block the response with heavy processing 5. **Log everything** -- Record incoming webhooks for debugging *** ## Testing Use Test Mode to send test events to your webhook endpoint: 1. Switch to Test Mode in the Dashboard header 2. Go to Developers --> Webhooks 3. Perform actions (create orders, complete payments) in test mode 4. Check your endpoint for incoming webhook events Webhooks fire in both Test and Live modes. Make sure your endpoint can distinguish between test and live events using the `X-Environment` context of the original action. *** ## Debugging View webhook delivery logs in the Dashboard: * Delivery status (success/failed) * HTTP response code from your endpoint * Payload sent * Timestamps and retry attempts *** ## Next Steps Step-by-step webhook integration tutorial. Full API documentation. # Checkout Flow Source: https://waffo.mintlify.app/checkout/checkout-flow How your customers complete purchases ## Checkout Overview Waffo Pancake uses a **two-step checkout flow** optimized for conversion. This design collects customer details first, then payment information, reducing abandonment and supporting accurate tax calculation. ## Checkout URLs Checkout pages use a token-based URL structure: ``` https://checkout.waffo.ai/{store-slug}/checkout/{token} ``` | Component | Description | | ------------ | ------------------------------------------------------------ | | `store-slug` | Your store's unique URL slug | | `token` | Encrypted checkout token containing product and session info | Checkout tokens are generated server-side and include product details, pricing, and security information. ## Two-Step Checkout Flow ```mermaid theme={"dark"} %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': 'transparent', 'primaryTextColor': '#7CCB02', 'primaryBorderColor': '#7CCB02', 'lineColor': '#6b7280', 'fontFamily': 'system-ui, sans-serif'}}}%% graph LR A(Product Page) --> B(Step 1: Your Details) B --> C(Step 2: Payment) C --> D(Processing) D --> E(Success/Failed) style A fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 style B fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 style C fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 style D fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 style E fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 ``` *** ## Step 1: Customer Details The first step collects information needed for tax calculation and order processing. ### Required Fields | Field | Purpose | | ------------- | ------------------------------------------------- | | Email address | Receipt, account creation, Customer Portal access | | Country | Tax jurisdiction determination | ### Conditional Fields (Based on Country) | Field | When Required | | --------------- | ------------------------------------------ | | ZIP/Postal Code | US, CA, UK, and most countries | | State/Province | US, CA, AU, IN | | City | EU countries (for VAT) | | Street Address | EU countries (full address for compliance) | ### Business Purchase Option Customers can toggle "I'm purchasing as a business" to provide: * Business name * Full billing address * Tax ID (optional, for VAT exemption) EU tax compliance requires full address for accurate VAT calculation and invoicing. *** ## Step 2: Payment The second step collects payment information. ### Payment Methods * Card number * Expiry date (MM/YY) * CVC/CVV * Cardholder name * Apple Pay (iOS, Safari) * Google Pay (Android, Chrome) * One-click with biometric auth ### Order Summary Displayed alongside payment form: | Element | Description | | ------------- | ------------------------------- | | Product name | What customer is buying | | Product image | Visual confirmation | | Subtotal | Product price | | Tax | Calculated from Step 1 location | | Total | Final amount to charge | ### Terms Agreement Customer must agree to terms before completing purchase. Links to: * Terms of Service * Privacy Policy * Merchant of Record disclosure *** ## Processing After payment submission: 1. **Card validation** - Luhn check, expiry, CVC 2. **3D Secure** - Bank verification (if required) 3. **Fraud check** - Risk assessment 4. **Authorization** - Charge to card 5. **Order creation** - Record in system Customer sees: * Animated loading indicator * "Processing your payment" message * Real-time status updates *** ## Result Pages ### Success Page On successful payment: * Order confirmation number * "Receipt sent to your email" message * Next steps or access instructions * Customer Portal link ### Failed Page On payment failure: * Clear error explanation * Suggested action * Retry button * Support contact option *** ## Subscription Checkout For subscription products, additional information displays: ### Billing Preview | Element | Example | | ----------------- | --------------------- | | Billing frequency | "Billed monthly" | | Recurring amount | "\$29.00/month" | | Next billing date | Calculated from today | ### Trial Information (if enabled) | Element | Example | | ----------------- | --------------------- | | Trial duration | "7-day free trial" | | First charge date | Date after trial ends | | Cancel anytime | Reassurance message | *** ## Multi-Language Support Checkout automatically displays in customer's browser language: | Language | Code | | -------------------- | ---- | | English | en | | Chinese (Simplified) | zh | | Japanese | ja | | Korean | ko | | German | de | | French | fr | | Spanish | es | *** ## Test Checkout Use Test Mode to try the checkout flow without real charges. ### Test Card Numbers | Card | Number | Result | | ------------------ | ------------------- | -------------- | | Visa Success | 4242 4242 4242 4242 | Success | | Mastercard Success | 5555 5555 5555 4444 | Success | | Declined | 4000 0000 0000 0002 | Declined | | 3DS Required | 4000 0027 6000 3184 | 3D Secure flow | | Insufficient Funds | 4000 0000 0000 9995 | Declined | Any future expiry date and any 3-digit CVC will work. Test mode is indicated by a banner: "Test Mode - No real charges will be made" *** ## Error Handling ### Common Payment Errors | Error | Cause | Customer Action | | ------------- | -------------------------------- | ------------------ | | Card declined | Insufficient funds or bank block | Try different card | | Invalid card | Incorrect card number | Check and re-enter | | Expired card | Card past expiration | Use valid card | | CVC mismatch | Wrong security code | Re-enter CVC | | 3DS failed | Bank verification failed | Contact bank | ### Error Display Error messages are: * Clear and actionable * Non-technical language * Include helpful next steps * Do not expose sensitive data *** ## Checkout Token Security Tokens include: * Product and pricing information * Customer session data * Expiration timestamp * Cryptographic signature Tokens cannot be modified or reused after expiration. Checkout tokens expire after 24 hours. Customers must start a new checkout session after expiration. *** ## Merchant of Record Notice At checkout footer, customers see: > "This order is processed by our online reseller & Merchant of Record, Waffo Pancake, who also handles order-related inquiries and returns." This disclosure is required for MoR compliance and helps customers understand the payment relationship. *** ## Next Steps Supported cards and wallets Brand your checkout experience # Checkout Customization Source: https://waffo.mintlify.app/checkout/customization Brand your checkout experience ## Customization Overview Make your checkout page match your brand with custom logos, colors, and themes. ## Accessing Checkout Settings 1. Go to Dashboard → Settings 2. Select "Checkout" tab 3. Customize and preview changes 4. Save to apply ## Branding Options ### Logo Upload your brand logo to appear in the checkout header. | Setting | Specification | | ---------------- | ----------------------- | | Format | PNG, JPG, SVG | | Recommended Size | 200 × 50 px | | Max File Size | 2 MB | | Background | Transparent recommended | Use a horizontal logo for best results. The logo appears in the checkout header and confirmation emails. ### Banner Image Add a banner image to enhance your checkout page. | Setting | Specification | | ---------------- | ------------- | | Format | PNG, JPG | | Recommended Size | 1200 × 300 px | | Max File Size | 5 MB | | Aspect Ratio | 4:1 | ## Theme Settings ### Color Mode * White background * Dark text * Best for most brands * Professional appearance * Dark background * Light text * Modern aesthetic * Reduces eye strain ### Custom Colors Customize the checkout color scheme: | Color Setting | Description | Default | | -------------------- | ---------------------------- | ------- | | **Accent Color** | Buttons, links, focus states | #6366F1 | | **Hover Color** | Button hover states | #4F46E5 | | **Text Color** | Primary text | #1F2937 | | **Background Color** | Page background | #FFFFFF | ### Color Picker For each color setting: 1. Click the color swatch 2. Use the color picker or enter a hex code 3. Preview changes in real-time 4. Save when satisfied Ensure sufficient contrast between text and background colors for accessibility. WCAG recommends a contrast ratio of at least 4.5:1. ## Preview Mode Before saving changes: 1. Use the preview panel on the right 2. Toggle between desktop and mobile views 3. Test with different products 4. Verify all elements are readable ## Customization Examples ### Tech Startup ``` Theme: Dark Accent: #00D4FF (Cyan) Background: #0F172A (Dark Blue) Text: #F1F5F9 (Light Gray) ``` ### E-commerce ``` Theme: Light Accent: #16A34A (Green) Background: #FFFFFF (White) Text: #111827 (Dark Gray) ``` ### Creative Agency ``` Theme: Light Accent: #8B5CF6 (Purple) Background: #FAFAFA (Off-White) Text: #374151 (Gray) ``` ## Additional Settings ### Store Information Display additional information on checkout: | Option | Description | | ------------- | ----------------------------- | | Store Name | Shown in header | | Support Email | For customer questions | | Terms Link | Link to your terms of service | | Privacy Link | Link to your privacy policy | ### Legal Links Add links to your legal pages: * Terms of Service (required) * Privacy Policy (required) * Refund Policy (optional) These appear in the checkout footer. ## Email Branding Your checkout branding extends to transactional emails: | Email Type | Branding Applied | | ---------------------- | ---------------- | | Order Confirmation | Logo, colors | | Payment Receipt | Logo, colors | | Subscription Reminders | Logo, colors | | Failed Payment | Logo, colors | ## Best Practices * Match your website's look and feel * Use the same logo as your main site * Consistent color palette builds trust * Use professional, high-quality images * Include contact information * Display security badges * Show payment method logos * Test on mobile devices * Ensure logos scale properly * Check color contrast on smaller screens * Verify touch targets are adequate * Sufficient color contrast * Readable font sizes * Alt text for images * Keyboard navigable ## Reset to Default To reset all customizations: 1. Go to Checkout Settings 2. Click "Reset to Default" 3. Confirm the action 4. Default Waffo Pancake branding will be restored Resetting to default cannot be undone. Consider saving your current settings before resetting. # Billing Questions Source: https://waffo.mintlify.app/customers/billing Understanding charges on your statement ## See "Waffo Pancake" on Your Statement? You made a purchase from a business using our platform. We're the **Merchant of Record**. Our name appears on your statement instead of the business name. *** ## Identify a Charge ### Check Your Email Look for emails from: * The business you purchased from * `receipts@waffo.ai` or `noreply@waffo.ai` Your receipt includes: * Business name * Product purchased * Amount charged * Date ### Common Reasons | Scenario | Explanation | | -------------------- | -------------------------- | | Subscription renewal | Active subscription billed | | Trial conversion | Free trial ended | | One-time purchase | Bought product or service | | Upgrade/downgrade | Plan changed | *** ## Unrecognized Charge Search inbox for receipts. Any forgotten active subscriptions? Family member use your card? Still don't recognize it? Email us. ### When Contacting Us | Information | Where to Find | | ------------- | ----------------------------- | | Charge amount | Bank statement | | Charge date | Bank statement | | Last 4 digits | Bank statement | | Your email | The one you use for purchases | Email with charge details. *** ## Duplicate Charges See the same charge twice? 1. **Wait 24-48 hours** — Banks may show pending + posted separately 2. **Check receipts** — Did you make two purchases? 3. **Contact us** — If genuine duplicate, we'll refund *** ## Subscription Billing ### When Subscriptions Bill | Interval | Billing Day | | --------- | ------------------------ | | Weekly | Same day each week | | Monthly | Same date each month | | Quarterly | Same date every 3 months | | Yearly | Same date each year | ### Price Changes Businesses must notify you: * Immediately for decreases * 30+ days for increases *** ## Failed Payments If payment fails: 1. We retry automatically over 7-14 days 2. You receive email notifications 3. Update payment method to avoid interruption Update your card. *** ## Receipts & Invoices ### Get a Receipt Receipts are sent automatically. Missing one? 1. Check spam folder 2. Search for `@waffo.ai` 3. Contact us with your email ### Download Invoice For tax or business purposes: * Customer Portal (if available) * Contact the business * Email us with purchase details *** ## Tax Charges Tax shown as separate line item. Based on: * Your location * Product type * Local regulations Questions about tax? Contact a tax professional. # For Customers Source: https://waffo.mintlify.app/customers/overview Bought something? We're here to help. ## Customer Help Center Made a purchase from a business using Waffo Pancake? Find answers here. See a charge? Understand it. Cancel, pause, or update. Request money back. Update your card. *** ## Why "Waffo Pancake" on My Statement? Waffo Pancake is a **Merchant of Record**. We process payments for many businesses. When you buy from a business using us, you may see: * "WAFFO" or "WAFFO PANCAKE" on your bank statement * Our name on receipts or invoices **This is normal.** We process payments on behalf of the business you purchased from. ### Find the Business Name Check your email for: * Order confirmation * Receipt with product details * Business name and contact info *** ## Quick Links Identify unknown charges. Stop recurring billing. Get money back. Change payment method. *** ## Contact ### Contact the Business For questions about: * The product or service * Access or delivery * Refund policies **Find their contact in your receipt email.** ### Contact Waffo Pancake For questions about: * Charges you don't recognize * Payment processing issues * Technical billing problems [support@waffo.ai](mailto:support@waffo.ai) *** ## Your Rights * Receive receipts for all purchases * Cancel subscriptions anytime * Request refunds per business policy * Access invoices for records * Update payment methods * Data privacy under applicable laws # Update Payment Source: https://waffo.mintlify.app/customers/payment-method Change your card on file ## Update Payment Method Need to update your card? Use the Customer Portal. Find link in emails from the business, or request one. Go to "Payment Methods" or "Billing". Enter: * Card number * Expiration * CVC * Billing address Make it your default payment method. Delete if no longer needed. *** ## Why Update? | Reason | Action | | -------------------- | --------------------------- | | Card expired | Add new before next billing | | Card lost/stolen | Replace immediately | | New bank | Update to new card | | Different preference | Add and set as default | *** ## Card Expiring Soon? 1. You'll receive email reminder 2. Update before next billing date 3. Avoid service interruption Card expires + payment fails = subscription may be suspended after retries. *** ## Failed Payment If payment failed: 1. Check email for notification 2. Update payment method 3. System retries automatically 4. Or contact business for manual retry ### Common Failures | Reason | Solution | | ------------------ | ---------------------------------- | | Insufficient funds | Add funds or use different card | | Card declined | Contact bank or use different card | | Incorrect details | Re-enter card info | | Expired card | Use current card | *** ## Supported Methods | Method | How | | ------------ | -------------------- | | Credit cards | Visa, Mastercard | | Debit cards | Same as credit | | Apple Pay | On supported devices | | Google Pay | On supported devices | Available methods depend on location and business settings. *** ## Security Your payment info is: * **Encrypted** in transit and at rest * **PCI compliant** * **Tokenized** — no full card storage * **Protected** from unauthorized access We never: * Share payment details with businesses * Store full card numbers * Allow unauthorized charges *** ## Multiple Cards You can have multiple cards: * Backup for failed payment recovery * Switch default anytime * Remove unused cards *** ## FAQ Still update the expiration date in portal. No. Adding card doesn't trigger charge. Only on regular billing date. Depends on business setup. Contact them. Contact the business. They can send one. Yes. Bank-level encryption. PCI compliant. *** ## Need Help? Contact business for portal link. Contact us for technical billing problems. # Refunds Source: https://waffo.mintlify.app/customers/refunds How to request your money back ## Requesting a Refund Refund policies are set by each business. Not by us. Find contact info in your receipt email. Include: * Your email * What you purchased * Why you want a refund Business reviews based on their policy. *** ## Find Business Contact Check your email for: * Order confirmation * Receipt from business * Welcome email Business name and contact should be included. *** ## Refund Policies Refund requests for one-time purchases must be submitted within **7 days** of the original payment. Each business may set additional policies within this window: | Policy | Description | | -------------- | ----------------------------------- | | Full refund | 100% refund within eligible period | | Partial refund | Refund for a portion of the payment | | No refunds | All sales final (business-specific) | Refund requests for one-time products cannot be submitted more than 7 days after payment. Check the business's refund policy before purchasing. *** ## Refund Timeline Once approved: | Step | Timeline | | -------------------- | ------------------ | | Refund initiated | Same day | | Processed by bank | 3-5 business days | | Appears on statement | 5-10 business days | Refunds appear as separate credit, not reversal of original charge. *** ## Partial Refunds Businesses may offer partial refunds for: * Prorated subscription time * Partial product use * Goodwill gestures *** ## Subscription Refunds | Scenario | Typical Policy | | -------------------- | -------------------------------- | | Within trial | Free to cancel, no refund needed | | First billing cycle | May qualify | | Ongoing subscription | Rarely refunded | **Canceling vs. Refunding:** * **Cancel** — Stops future charges, keeps current access * **Refund** — Gets money back for charges *** ## Chargebacks Business refuses legitimate refund? File chargeback with your bank. Last resort. Takes 60-90 days. May affect future purchases from that business. ### Before Filing 1. Contact business at least twice 2. Wait 5-7 business days for response 3. Document communication 4. Review their refund policy *** ## FAQ Refund decisions made by business. We process payments but don't have authority to refund without their approval. After multiple attempts: 1. Try different contact methods 2. Wait 7 business days 3. Contact us with documentation 4. Consider chargeback Contact business immediately with: * Proof of payment * Expected delivery date * Confirmation you didn't receive it Contact business with specifics. Most will work with you. Depends on business policy. Usually 14-30 days. *** ## Contact Refund requests and product issues. Can't reach business or payment issues. # Manage Subscription Source: https://waffo.mintlify.app/customers/subscriptions Cancel, pause, or update anytime ## Your Subscription. Your Control. Manage subscriptions through the **Customer Portal**. Self-service. No waiting. *** ## Access Customer Portal Check email from the business, or request one. Click link. No password needed. Secure magic link. View, update, or cancel. No portal link? Contact the business. They can send you one. *** ## Cancel Subscription ### Through Customer Portal 1. Open portal link 2. Find subscription 3. Click "Cancel" 4. Choose when: * **Immediately** — Access ends now * **At period end** — Access continues until paid period ends 5. Confirm ### By Contacting Business Can't access portal? 1. Email business directly 2. Include your account email 3. Request cancellation ### After Cancellation | Type | What Happens | | ------------- | ----------------------------------------- | | At period end | Access until paid period ends, then stops | | Immediately | Access ends now, no prorated refund | *** ## Pause Subscription Some businesses allow pausing: 1. Open Portal 2. Find subscription 3. Click "Pause" 4. Select duration 5. Confirm **During pause:** * No charges * Access may be suspended * Resume anytime *** ## Change Plan Upgrade or downgrade: 1. Open Portal 2. Click "Change Plan" 3. Select new plan 4. Review price changes 5. Confirm **Billing:** * Upgrades: Pay difference now * Downgrades: Credit next invoice *** ## View Details In Customer Portal: | Info | Description | | -------------- | ------------------------ | | Current plan | Which plan you're on | | Price | How much you pay | | Interval | Weekly, monthly, etc. | | Next billing | When you're charged next | | Payment method | Card on file | *** ## Renewal ### Automatic Renewal Subscriptions renew automatically. You'll receive: * Email reminder before renewal * Receipt after charge ### Stop Renewal Cancel before next billing date: * Current period: Access continues * Next period: No charge, access ends *** ## FAQ Refund policies set by each business. Contact them directly. Canceling stops future charges. Yes. No cancellation fees unless specified by the business. Resubscribe anytime through their website. Possible reasons: * Cancellation set for "end of period" * Multiple subscriptions * Cancellation didn't complete — contact us Contact the business. They can send a new one. *** ## Need Help? Subscription questions, refunds, product access. Payment and billing issues only. # Analytics Source: https://waffo.mintlify.app/dashboard/analytics Business insights and performance metrics ## Analytics Overview The Analytics page provides comprehensive insights into your business performance with interactive charts and key metrics. Analytics Dashboard *** ## Key Metrics ### Revenue Metrics | Metric | Description | | ----------------------- | -------------------------------------------- | | **Total Revenue** | Sum of all successful payments | | **MRR** | Monthly Recurring Revenue from subscriptions | | **ARR** | Annual Recurring Revenue (MRR × 12) | | **Average Order Value** | Average transaction amount | ### Customer Metrics | Metric | Description | | --------------------------- | --------------------------------- | | **Total Customers** | Unique paying customers | | **New Customers** | Customers acquired in period | | **Repeat Customers** | Customers with multiple purchases | | **Customer Lifetime Value** | Average revenue per customer | ### Subscription Metrics | Metric | Description | | ------------------------ | ------------------------------ | | **Active Subscriptions** | Currently active subscriptions | | **Churn Rate** | % of subscriptions canceled | | **Net MRR Growth** | MRR change over period | | **Trial Conversion** | % of trials converting to paid | *** ## Charts & Visualizations ### Revenue Chart Interactive line chart showing: * Daily/weekly/monthly revenue * Trend lines and comparisons * Period-over-period growth **Time Ranges:** * Last 7 days * Last 30 days * Last 90 days * Last 12 months * Custom range ### Transaction Volume Bar chart displaying: * Number of transactions per period * Successful vs failed breakdown * Average transaction size ### Customer Geography Visual breakdown of customers by location: * Country distribution map * Top markets by revenue * Regional growth trends See which countries generate the most revenue. Revenue breakdown by transaction currency. *** ## Date Range Selection ### Quick Filters | Filter | Period | | ------------ | ---------------- | | Today | Current day | | Last 7 Days | Previous week | | Last 30 Days | Previous month | | Last 90 Days | Previous quarter | | This Year | Year to date | ### Custom Range Select specific start and end dates for detailed analysis. ### Comparison Enable comparison mode to see: * Period-over-period changes * Percentage growth/decline * Trend indicators *** ## Metric Cards Each metric card displays: | Element | Description | | --------------- | ---------------------------------- | | **Value** | Current metric value | | **Change** | % change from previous period | | **Trend Arrow** | Up (green) or down (red) indicator | | **Sparkline** | Mini chart showing recent trend | Click on any metric card to see a detailed breakdown and drill-down analysis. *** ## Export & Reports ### Export Options | Format | Use Case | | -------- | ------------------------------------- | | **CSV** | Data analysis in spreadsheets | | **PDF** | Professional reports for stakeholders | | **JSON** | Programmatic access via API | ### Scheduled Reports Set up automated reports: * Daily summary emails * Weekly performance digest * Monthly business review Configure in **Settings → Notifications**. *** ## Filtering & Segmentation ### Filter by Product View analytics for specific products: * Individual product performance * Product comparison * Best sellers ranking ### Filter by Customer Segment Segment analytics by: * New vs returning customers * Subscription tier * Geographic region ### Filter by Payment Method Analyze by payment type: * Card payments * Apple Pay / Google Pay * Regional payment methods *** ## Understanding Your Data ### Test vs Live Mode Analytics data is separate for Test and Live modes. Ensure you're viewing the correct environment. ### Data Freshness | Data Type | Update Frequency | | ------------------ | ---------------- | | Transactions | Real-time | | Aggregated Metrics | Every 5 minutes | | Charts | Every 15 minutes | ### Timezone All analytics use UTC timezone. Timestamps are converted to your local timezone for display. *** ## Best Practices Focus on metrics that matter: * MRR for subscription health * Churn rate for retention * LTV for customer value Compare against: * Your historical performance * Industry averages * Growth targets Schedule time to review: * Daily: Transaction volume * Weekly: Revenue trends * Monthly: Full business review # Customers Source: https://waffo.mintlify.app/dashboard/customers Manage your customer database and relationships ## Customer Management The Customers page provides a complete view of everyone who has interacted with your products. Customers List ## Customer List View all your customers in a sortable, filterable table: | Column | Description | | ------------- | -------------------------------------------- | | First Seen | When the customer first appeared | | Email | Customer email address | | Country | Customer location (with flag) | | Status | Current customer status | | Subscriptions | Active subscription count | | Payments | Total payment count | | MRR | Monthly Recurring Revenue from this customer | | Revenue | Total lifetime revenue | ## Customer Statuses Has made payments but no active subscriptions. Has one or more active subscriptions. Previously had subscriptions that are now canceled. No recent activity or purchases. ## Customer Details Click on a customer row to view their full profile: ### Overview Tab * Email and name * Location * Account creation date * Total lifetime value * Current MRR ### Subscriptions Tab * All subscriptions (active and past) * Subscription status * Billing interval * Next billing date * Actions (pause, cancel) ### Payments Tab * Full payment history * Payment status * Amounts and currencies * Refund status * Associated products ### Activity Tab * Login history * Subscription changes * Payment events * Support interactions ## Filtering Customers Use filters to segment your customer base: | Filter | Options | | ---------------- | ------------------------------------- | | Status | Active, Subscribed, Churned, Inactive | | Country | Any country | | Date Range | First seen date | | Has Subscription | Yes/No | ### Search Search customers by: * Email address * Customer name * Customer ID ## Customer Metrics ### Statistics Cards | Metric | Description | | --------------- | ------------------------------- | | Total Customers | All unique customers | | Active | Customers with recent activity | | Countries | Number of different countries | | Avg. LTV | Average customer lifetime value | ### Geography Distribution A breakdown of your customers by country: * Top 5 countries displayed * Customer count per country * Revenue per region ## Customer Actions Generate a link to let customers manage their own subscriptions. Process a one-time charge for an existing customer. Cancel a customer's active subscription immediately or at period end. Issue a full or partial refund for a past payment. Download customer information for GDPR compliance or analysis. ## Customer Portal Waffo Pancake provides a self-service portal where customers can: * View their active subscriptions * Update payment methods * Download invoices * Cancel subscriptions * View payment history To give a customer access: 1. Go to customer details 2. Click "Generate Portal Link" 3. Send the secure link to the customer Portal links are time-limited for security. Generate a new link if the customer needs extended access. ## Data Export Export your customer data in CSV format: 1. Apply any desired filters 2. Click "Export" 3. Choose fields to include 4. Download the CSV file Available export fields: * Email * Name * Country * Status * Created date * Total revenue * MRR * Subscription count # Finance Source: https://waffo.mintlify.app/dashboard/finance Manage your earnings, payouts, and financial reports ## Finance Overview The Finance page is your financial command center. Track earnings, manage payouts, and download invoices and receipts. Finance Overview ## Page Layout The Finance page is organized into tabs: | Tab | Description | | ------------------ | ----------------------------------------- | | **Income** | Revenue overview and earnings breakdown | | **Payout Setup** | Configure your payout method and schedule | | **Payout History** | View past payouts and their status | *** ## Income Tab ### Earnings Summary | Metric | Description | | --------------------- | ------------------------------------- | | **Total Revenue** | All-time successful payments | | **Pending Balance** | Funds awaiting payout | | **Available Balance** | Ready for withdrawal | | **Next Payout** | Estimated next payout amount and date | ### Revenue Breakdown View revenue by: * **Time Period** — Daily, weekly, monthly * **Product** — Per-product revenue * **Currency** — Multi-currency breakdown ### Transactions A detailed list of all transactions: | Column | Description | | -------- | ------------------------------ | | Date | Transaction timestamp | | Type | Payment, refund, or fee | | Amount | Transaction amount | | Currency | Original currency | | Status | Completed, pending, or failed | | Actions | View details, download receipt | *** ## Payout Setup Tab Finance Payout Setup ### Payout Methods Configure how you receive your earnings: * Direct deposit to bank account * Supported in 50+ countries * 2-5 business days processing ### Bank Account Setup | Field | Required | Description | | -------------- | ------------------- | ----------------------- | | Account Holder | Yes | Legal name on account | | Bank Name | Yes | Financial institution | | Account Number | Yes | Bank account number | | Routing Number | Yes (US) | ABA routing number | | SWIFT/BIC | Yes (International) | International bank code | ### Payout Schedule | Schedule | Description | | ----------- | ----------------------------------- | | **Daily** | Automatic daily payouts (min \$100) | | **Weekly** | Every Monday | | **Monthly** | First of each month | | **Manual** | Request payouts manually | Minimum payout amount is \$100. Balances below this threshold accumulate until the minimum is reached. *** ## Payout History Tab ### Payout List View all past payouts: | Column | Description | | ------------ | ----------------------------- | | Date | Payout initiation date | | Amount | Payout amount | | Method | Bank transfer | | Status | Pending, completed, or failed | | Arrival Date | Expected or actual arrival | ### Payout Status Processing. Usually 1-3 business days. On the way to your account. Successfully deposited. Issue with payout. Check details. *** ## Invoices & Receipts ### Download Options Generate professional documents for your records: | Document | Purpose | | -------------------- | ----------------------------------------- | | **Invoice** | Detailed billing document with line items | | **Receipt** | Proof of payment for customers | | **Payout Statement** | Summary of payout with fees | ### PDF Generation All documents are generated as professional PDFs: * Your store branding and logo * Complete transaction details * Tax breakdown (if applicable) * Unique document numbers Download receipts to share with customers or for your own accounting records. *** ## Currency Handling ### Multi-Currency Support The Finance page handles multiple currencies: * View totals in your default currency * See original transaction currencies * Automatic conversion for aggregations ### Display Currency Choose how amounts are displayed: * **Original Currency** — Show in transaction currency * **Converted** — Show in your default currency ### Exchange Rates Exchange rates are: * Updated daily * Applied at time of transaction * Locked for payout calculations *** ## Fees & Deductions ### Fee Breakdown | Fee Type | Description | | ----------------------- | ----------------------------- | | **Platform Fee** | Waffo Pancake transaction fee | | **Payment Processing** | Card network fees | | **Payout Fee** | Per-payout transfer fee | | **Currency Conversion** | FX markup (if applicable) | All fees are automatically deducted. Net amounts shown in your balance are what you'll receive. *** ## Tax Documents ### Available Documents | Document | When Available | | ---------------------- | --------------------------- | | **1099-K** (US) | January (if thresholds met) | | **Annual Summary** | January | | **Monthly Statements** | First of each month | ### Tax Information Ensure your tax information is up to date: * Business legal name * Tax ID / EIN * Business address Update in **Settings → Business Details**. # Home Source: https://waffo.mintlify.app/dashboard/home Your business overview at a glance ## Home Page Overview The Dashboard Home page provides a comprehensive view of your business performance with key metrics, charts, and recent activity. Dashboard Home ## Statistics Cards At the top of the Home page, you'll find key performance indicators: | Metric | Description | | ------------------------ | --------------------------------------------------- | | **Total Revenue** | Sum of all successful payments | | **MRR** | Monthly Recurring Revenue from active subscriptions | | **Customers** | Total number of unique customers | | **Sales** | Number of successful one-time payments | | **Active Subscriptions** | Currently active subscription count | Statistics are calculated based on your current mode (Test or Live). Make sure you're viewing the correct mode for accurate data. ## Charts and Visualizations ### Transaction Volume Chart An interactive line chart showing: * Daily transaction counts * Revenue trends over time * Selectable date ranges (7 days, 30 days, 90 days) ### Customer Geography A visual breakdown of your customers by region: * Country distribution * Top markets * Geographic revenue concentration ## Recent Activity ### Recent Transactions A table showing your latest payments: | Column | Description | | -------- | ------------------------------------ | | Date | Transaction timestamp | | Customer | Customer email | | Amount | Payment amount with currency | | Status | Payment status (Paid, Pending, etc.) | | Product | Associated product name | ### Recent Customers Your newest customer signups with: * Customer email * Sign-up date * Country * First purchase status ## Quick Actions From the Home page, you can quickly: Add a new product to your catalog See all transactions Download reports ## Data Refresh Dashboard data updates automatically. You can also: * Pull to refresh on mobile * Click the refresh icon to force update * Data typically updates within seconds of new transactions ## Time Periods Filter your Home page data by time period: * **Today** - Current day only * **Last 7 Days** - Previous week * **Last 30 Days** - Previous month * **Last 90 Days** - Previous quarter * **Custom Range** - Select specific dates ## Currency Display If you have transactions in multiple currencies: * Main totals show in your default currency * Individual transactions show in their original currency * Exchange rates are applied for aggregations # Payments Source: https://waffo.mintlify.app/dashboard/payments Track transactions and manage refunds ## Payments Overview The Payments page shows all transactions processed through your store, including one-time purchases and subscription charges. Payments List ## Payment List View all payments in a comprehensive table: | Column | Description | | -------------- | ----------------------------------- | | Date | Transaction timestamp | | Amount Paid | Gross payment amount | | Tax Amount | Tax collected | | Status | Payment status | | Payment Method | Card type and last 4 digits | | Description | Payment description or product name | | Customer | Customer email | | Product | Associated product | ## Payment Statuses Successfully processed and funds received. Payment initiated but not yet confirmed. Full amount has been refunded. Part of the payment has been refunded. Payment was rejected by the payment processor. Customer disputed the charge with their bank. ## Filtering Payments Filter your payment list by: | Filter | Options | | ---------- | -------------------------------------------------- | | Status | All, Paid, Pending, Refunded, Declined, Chargeback | | Product | Any product in your catalog | | Date Range | Custom start and end dates | | Customer | Search by email | | Amount | Min/Max amount range | ### Search Search payments by: * Payment ID * Customer email * Product name * Last 4 digits of card ## Payment Details Click on any payment to view full details: ### Transaction Info * Payment ID * Amount and currency * Tax amount * Net amount (after fees) * Timestamp * Test/Live mode indicator ### Payment Method * Card brand (Visa, Mastercard) * Last 4 digits * Expiration date * Country of issue ### Customer Info * Email * Name (if provided) * IP address * Country ### Associated Records * Product purchased * Subscription ID (if applicable) * Invoice link ## Processing Refunds Locate the payment in the list or use search. Open the payment details and click the Refund button. * **Full Refund** - Return the entire amount * **Partial Refund** - Enter a custom amount Document why the refund is being processed. Review and confirm the refund. Refunds typically take 5-10 business days to appear on the customer's statement. Refunds cannot be reversed once processed. ### Refund Policies | Scenario | Recommendation | | -------------------- | ---------------------------------- | | Duplicate charge | Full refund | | Partial service used | Partial refund | | Service issue | Full or partial based on situation | | Fraud | Full refund + review account | ## Payment Statistics At the top of the Payments page: | Metric | Description | | ---------------- | ---------------------------- | | Total Revenue | Sum of all paid transactions | | Net Revenue | Total revenue minus refunds | | Total Refunded | Sum of all refunds issued | | Successful | Count of successful payments | | Avg. Order Value | Average payment amount | ## Payment Methods Waffo Pancake supports: Visa, Mastercard Available on iOS and Safari Available on Android and Chrome ## Chargebacks When a customer disputes a charge: 1. You'll receive a notification 2. Payment status changes to "Chargeback" 3. Funds are held pending resolution 4. You can submit evidence to fight the dispute Chargebacks carry fees and can impact your merchant reputation. Prevent them with clear product descriptions, good customer service, and recognizable billing descriptors. ## Exporting Payments Export payment data for accounting or analysis: 1. Apply desired filters 2. Click "Export" 3. Select format (CSV or PDF) 4. Download the file Export includes: * All payment details * Customer information * Tax amounts * Refund status * Timestamps # Products Source: https://waffo.mintlify.app/dashboard/products Create and manage your product catalog ## Product Management The Products page is where you manage your entire product catalog. Create one-time purchase items or subscription products. Products List ## Product List Your products are displayed in a table with: | Column | Description | | ----------- | ---------------------------------------------------------- | | Name | Product name and image thumbnail | | Price | Price with currency and billing interval | | Status | Active or Inactive | | Subscribers | Number of active subscriptions (for subscription products) | | Created | Creation date | | Actions | Edit, copy link, toggle status | ## Creating a Product Create Product Find the button in the top right of the Products page. **Required Fields:** * Product Name * Price * Currency * Pricing Type (One-Time or Subscription) * Product Description (supports Markdown) * Product Image * Tax settings For subscription products only: * Billing Interval * Trial Period (optional) Click "Create" to publish your product. ## Product Fields ### Basic Information | Field | Required | Description | | ----------- | -------- | -------------------------------------- | | Name | Yes | Display name (shown to customers) | | Description | No | Product details in Markdown format | | Image | No | Product image (recommended: 400x400px) | ### Pricing | Field | Options | Description | | ------------ | ------------------------------------------ | --------------------------------------------- | | Price | Number | The product price (in smallest currency unit) | | Currency | USD, EUR, GBP, CNY, JPY, HKD, etc. | Transaction currency | | Pricing Type | One-Time, Subscription | Payment model | | Tax Category | SaaS, Digital Goods, Software, eBook, etc. | Tax calculation rules | | Tax Behavior | Inclusive, Exclusive | Price includes or excludes tax | ### Subscription Settings Only applicable for subscription products: | Field | Options | Description | | ------------- | ---------------------------------- | --------------------------- | | Interval | Weekly, Monthly, Quarterly, Yearly | Billing frequency | | Trial Enabled | Yes/No | Offer free trial | | Trial Days | Number | Trial duration (default: 7) | ### Tax Configuration | Field | Options | Description | | ------------ | -------------------- | ------------------------------ | | Tax Category | SaaS, Digital Goods | Tax calculation rules | | Tax Behavior | Inclusive, Exclusive | Price includes or excludes tax | ## Product Status * Product is live and purchasable * Payment links work * Shown in checkout * Product is hidden * Payment links return error * Existing subscriptions continue To toggle status, use the switch in the product row or edit the product. ## Editing Products 1. Click on a product row or the edit icon 2. Modify any fields 3. Click "Save Changes" Changing the price of a subscription product only affects new subscribers. Existing subscribers keep their original price. ## Multi-Currency Pricing Products support multi-currency pricing: | Feature | Description | | ----------------------- | ------------------------------------------------------ | | **Multiple Currencies** | Set different prices for USD, EUR, GBP, CNY, JPY, etc. | | **Tax Categories** | SaaS, Digital Goods, Software, eBook, Online Course | | **Tax Behavior** | Tax inclusive or exclusive pricing | ### Price Structure ```json theme={"dark"} { "prices": { "USD": { "amount": 2900, "taxIncluded": false, "taxCategory": "saas" }, "EUR": { "amount": 2700, "taxIncluded": true, "taxCategory": "saas" } } } ``` ## Checkout Links Products use token-based checkout URLs: ``` https://checkout.waffo.ai/{store-slug}/checkout/{token} ``` **Get your link:** * Click the "Copy Link" button on any product * Or use the API to generate checkout tokens **Test vs Live:** * Toggle Test Mode in Dashboard header * Test mode generates test checkout sessions ## Best Practices * Use clear, descriptive names * Include the billing period for subscriptions (e.g., "Pro Plan - Monthly") * Avoid special characters * List key features * Use bullet points for readability * Include what customers get * Mention support or guarantees * Use high-quality images (400x400px minimum) * PNG or JPG format * Keep file size under 2MB * Consistent style across products * Research competitor pricing * Consider regional purchasing power * Offer annual discounts (typically 15-20% off) * Round prices for simplicity ## Bulk Actions Select multiple products to: * Activate/Deactivate in bulk * Export product data * Delete (with confirmation) # Subscriptions Source: https://waffo.mintlify.app/dashboard/subscriptions Manage recurring billing and subscriber relationships ## Subscription Management The Subscriptions page shows all recurring billing arrangements with your customers. Subscriptions List ## Subscription List View all subscriptions in a detailed table: | Column | Description | | ------------ | -------------------------------- | | Status | Current subscription status | | Product | Product name and image | | Customer | Subscriber email | | Amount | Subscription price with currency | | Interval | Billing frequency | | Next Billing | Next charge date | | Created | When subscription started | ## Subscription Statuses Subscription is live and billing normally. Customer is in free trial period. Payment failed, awaiting retry. Temporarily suspended, not billing. Subscription has been terminated. ## Billing Intervals | Interval | Billing Frequency | MRR Calculation | | --------- | ----------------- | --------------- | | Weekly | Every 7 days | Amount × 4.33 | | Monthly | Every month | Amount × 1 | | Quarterly | Every 3 months | Amount ÷ 3 | | Yearly | Every 12 months | Amount ÷ 12 | ## Filtering Subscriptions | Filter | Options | | -------- | -------------------------------------------- | | Status | Active, Trialing, Past Due, Paused, Canceled | | Product | Any subscription product | | Interval | Weekly, Monthly, Quarterly, Yearly | | Customer | Search by email | ## Subscription Details Click on a subscription to view: ### Overview * Subscription ID * Status and status history * Product details * Pricing and currency * Billing interval ### Billing Info * Current period start/end * Next billing date * Payment method on file * Billing history ### Customer * Customer email * Account details * Other subscriptions from same customer ### Payment History * All charges for this subscription * Successful and failed attempts * Refunds ## Managing Subscriptions ### Cancel Subscription Click on the subscription you want to cancel. Find the button in the actions menu. * **Immediately** - Ends right now * **At Period End** - Continues until current period expires Review and confirm the cancellation. Canceling at period end is recommended as it fulfills the current billing period the customer has paid for. ### Pause Subscription Temporarily pause billing: 1. Open subscription details 2. Click "Pause Subscription" 3. Optionally set a resume date 4. Confirm Paused subscriptions: * Stop generating charges * Retain customer relationship * Can be resumed anytime * Access may be revoked during pause (configurable) ### Resume Subscription For paused or canceled subscriptions: 1. Open subscription details 2. Click "Resume Subscription" 3. Choose billing start date 4. Confirm ## Subscription Metrics ### Statistics Cards | Metric | Description | | -------- | ------------------------------- | | MRR | Monthly Recurring Revenue | | Active | Count of active subscriptions | | Trialing | Count of subscriptions in trial | | Canceled | Count of canceled (this period) | | ARPU | Average Revenue Per User | ### MRR Calculation MRR is calculated from all active subscriptions: ``` MRR = Σ (Subscription Amount × Interval Factor) Where Interval Factor: - Weekly: 4.33 - Monthly: 1 - Quarterly: 0.33 - Yearly: 0.083 ``` ## Failed Payments When a subscription payment fails: 1. Status changes to "Past Due" 2. Automatic retry attempts (3 attempts over 7 days) 3. Customer notified via email 4. If all retries fail, subscription may cancel ### Dunning Emails Automatic emails sent to customers: * First failed payment notification * Retry attempt reminders * Final warning before cancellation * Cancellation confirmation ## Trial Periods For products with trials enabled: | Field | Description | | --------------- | ------------------------ | | Trial Status | Active trial indicator | | Trial Days | Total trial length | | Days Remaining | Time left in trial | | Conversion Date | When first charge occurs | Track trial conversions: * Trial → Active (converted) * Trial → Canceled (churned before conversion) ## Subscription Actions Upgrade or downgrade the subscription to a different product. Send customer a link to update their card on file. Add a coupon or manual discount to the subscription. Give the customer additional trial time. Apply account credit toward future invoices. # Analytics Source: https://waffo.mintlify.app/features/analytics Monitor store performance with charts, metrics, and flexible date ranges ## Analytics Overview The Analytics page lets you monitor your store's performance over time. It provides revenue charts, metric cards, and configurable date ranges so you can understand how your business is trending. *** ## Date Range & Granularity ### Date Range Picker Select a preset or custom date range to scope all charts and metrics on the page. | Preset | Period | | ---------- | ----------------------------------- | | **7d** | Last 7 days | | **14d** | Last 14 days | | **30d** | Last 30 days | | **90d** | Last 90 days | | **Custom** | Choose specific start and end dates | ### Granularity Control how data points are grouped in charts. | Granularity | Description | | ----------- | ------------------------ | | **Daily** | One data point per day | | **Weekly** | One data point per week | | **Monthly** | One data point per month | Your selected date range and granularity are saved automatically and persist across sessions, so the dashboard remembers your preferences. *** ## Revenue Charts The main visualization is a revenue chart that plots performance over the selected date range at the chosen granularity. Use the date range and granularity controls to adjust the view. *** ## Metric Cards The analytics page displays summary metric cards for key performance indicators such as revenue and customer counts. Each card shows the metric value for the selected period. *** ## Product Filtering You can filter analytics data by a specific product to see how individual items in your catalog are performing. This narrows charts and metrics to transactions associated with the selected product. *** ## Test vs Live Environment Analytics data is separate for Test and Live modes. Make sure you are viewing the correct environment using the mode toggle in the dashboard header. Switching between test and production mode updates all charts and metrics to reflect data from that environment only. Test mode data is never mixed with live data. *** ## Locale-Aware Formatting Numbers, currencies, and dates are formatted according to your locale setting. The dashboard supports English, Chinese, and Japanese formatting conventions. # Checkout Source: https://waffo.mintlify.app/features/checkout A two-step checkout flow optimized for conversion ## Checkout Overview Waffo Pancake uses a **two-step checkout flow** optimized for conversion. This design collects customer details first, then payment information, reducing abandonment and supporting accurate tax calculation. *** ## Checkout URLs Checkout pages use a session-based URL structure: ``` https://your-domain.com/store/{store-slug}/checkout/{sessionId} ``` | Component | Description | | ------------ | ---------------------------------------------------------------------- | | `store-slug` | Your store's unique URL slug | | `sessionId` | Checkout session identifier created when a customer initiates checkout | Checkout sessions are generated server-side and contain product, pricing, and currency information. *** ## Two-Step Flow ```mermaid theme={"dark"} %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': 'transparent', 'primaryTextColor': '#7CCB02', 'primaryBorderColor': '#7CCB02', 'lineColor': '#6b7280', 'fontFamily': 'system-ui, sans-serif'}}}%% graph LR A(Product Page) --> B(Step 1: Your Details) B --> C(Step 2: Payment) C --> D(Processing) D --> E(Success/Failed) style A fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 style B fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 style C fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 style D fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 style E fill:transparent,stroke:#7CCB02,stroke-width:2px,color:#7CCB02,rx:8,ry:8 ``` ### Step 1: Customer Details Collects information needed for tax calculation and order processing. **Required Fields:** | Field | Purpose | | ------------- | ------------------------------------------------- | | Email address | Receipt, account creation, Customer Portal access | | Country | Tax jurisdiction determination | **Conditional Fields (Based on Country):** | Field | When Shown | | --------------- | ---------------------------------------------- | | ZIP/Postal Code | Most countries (US, CA, UK, etc.) | | State/Province | US, CA, AU, IN, and other applicable countries | **Business Purchase Option:** Customers can toggle "I'm purchasing as a business" to provide: * Business name * Tax ID (for VAT/tax exemption) ### Step 2: Payment * Card number * Expiry date (MM/YY) * CVC/CVV * Cardholder name * Apple Pay (iOS, Safari) * Google Pay (Android, Chrome) * One-click with biometric auth **Order Summary** is displayed alongside the payment form with product name, image, subtotal, tax, and total. *** ## Subscription Checkout For subscription products, additional billing information displays: | Element | Example | | ----------------- | ------------------------------------------------------ | | Billing frequency | "Billed monthly" | | Recurring amount | "\$29.00/month" | | Next billing date | Calculated from today | | Trial duration | "7-day free trial" (if the product has trials enabled) | *** ## Customization Make your checkout page match your brand through the Checkout Settings in your dashboard. ### Logo Upload a custom logo displayed on the checkout page. Supported formats include PNG, JPG, and SVG. ### Theme Mode White background, dark text. Best for most brands. Dark background, light text. Modern aesthetic. Switch between Light and Dark mode presets. Each mode maintains its own set of color values. ### Color Settings | Setting | Field Name | Default (Light) | Default (Dark) | | ------------------------ | ---------------------------- | --------------- | -------------- | | **Primary Color** | `checkoutColorPrimary` | #7CCB02 | #ADFF85 | | **Background Color** | `checkoutColorBackground` | #FFFFFF | #0A1A1F | | **Card Color** | `checkoutColorCard` | #F3F4F6 | #0A1A1F | | **Text Color** | `checkoutColorText` | #111827 | #FFFFFF | | **Secondary Text Color** | `checkoutColorTextSecondary` | #8C8C8C | #8C8C8C | ### Border Radius Control the roundness of UI elements with the `checkoutBorderRadius` setting. Default is `8px`. Options range from 0px (sharp corners) to 16px (extra-large rounding). Ensure sufficient contrast between text and background colors for accessibility. WCAG recommends a contrast ratio of at least 4.5:1. ### Store Information | Option | Description | | ------------- | ---------------------------------------- | | Store Name | Shown in header | | Support Email | For customer questions | | Terms Link | Link to your terms of service (required) | | Privacy Link | Link to your privacy policy (required) | *** ## Multi-Language Support Checkout automatically displays in the customer's browser language: | Language | Code | | -------------------- | ---- | | English | en | | Chinese (Simplified) | zh | | Japanese | ja | *** ## Processing & Results After payment submission: 1. **Card validation** -- Luhn check, expiry, CVC verification 2. **3D Secure** -- Bank verification (if required by the issuing bank) 3. **Authorization** -- Charge to card 4. **Order creation** -- Record in system **Success Page:** Order confirmation number, receipt email notification, next steps, Customer Portal link. **Failed Page:** Clear error explanation, suggested action, retry button, support contact option. *** ## Error Handling | Error | Cause | Customer Action | | ------------- | -------------------------------- | ------------------ | | Card declined | Insufficient funds or bank block | Try different card | | Invalid card | Incorrect card number | Check and re-enter | | Expired card | Card past expiration | Use valid card | | CVC mismatch | Wrong security code | Re-enter CVC | | 3DS failed | Bank verification failed | Contact bank | *** ## Test Checkout Use [Test Mode](/features/test-mode) to try the checkout flow without real charges. | Card | Number | Result | | ------------ | ------------------- | -------------- | | Visa Success | 4242 4242 4242 4242 | Success | | Declined | 4000 0000 0000 0002 | Declined | | 3DS Required | 4000 0027 6000 3184 | 3D Secure flow | Test mode is indicated by a banner: "Test Mode - No real charges will be made" *** ## Merchant of Record Notice At checkout footer, customers see: > "This order is processed by our online reseller & Merchant of Record, Waffo Pancake, who also handles order-related inquiries and returns." This disclosure is required for MoR compliance and helps customers understand the payment relationship. # Customer Management Source: https://waffo.mintlify.app/features/customer-management View and track your customers from the merchant dashboard ## Customer Management The Customers page in the merchant dashboard gives you a consolidated view of every buyer who has purchased from your store. Track revenue, monitor subscriptions, and drill into individual customer details. *** ## Customer Data Each customer record contains the following fields, sourced from the backend `Customer` type: | Field | Description | | ------------------- | ---------------------------------------------------------------- | | `id` | Unique customer identifier (UUID) | | `email` | Customer email address | | `name` | Customer name | | `country` | Customer country | | `totalRevenue` | Lifetime revenue from this customer (in smallest currency units) | | `mrr` | Monthly Recurring Revenue attributed to this customer | | `subscriptionCount` | Number of subscriptions (active and past) | | `paymentCount` | Total number of payments | | `createdAt` | When the customer record was created | | `updatedAt` | When the customer record was last updated | | `storeId` | The store this customer belongs to | The backend `Customer` type does not have a `status` field. Any status labels shown in the dashboard UI (such as "Active" or "Subscribed") are derived from the customer's subscription and payment activity, not stored as a property on the customer record itself. *** ## Customer List The dashboard displays customers in a sortable, filterable table with these columns: | Column | Description | | ------------- | -------------------------------------------- | | Email | Customer email address | | Country | Customer country (displayed with flag emoji) | | Revenue | Total lifetime revenue | | MRR | Monthly Recurring Revenue | | Subscriptions | Subscription count | | Payments | Payment count | | Created | When the customer first appeared | ### Search and Filtering The customer list supports: * **Text search** -- Search by customer email or name * **Status filtering** -- Filter by derived status categories based on subscription and payment activity * **Date range filtering** -- Filter by customer creation date *** ## Customer Details Click on a customer row to view their full profile. ### Overview * Email and name * Country (with flag emoji) * Account creation date * Total lifetime revenue * Current MRR * Subscription count and payment count ### Subscriptions View all subscriptions associated with this customer: * Subscription status * Product and tier information * Billing period * Dates and amounts ### Payments View the full payment history for this customer: * Payment status * Amounts and currencies * Associated orders and products * Refund status where applicable *** ## Customer Portal Customers also have access to a self-service **Customer Portal** where they can manage their own subscriptions and view payment history. The portal is a separate feature -- see the [Customer Portal](/features/customer-portal) page for details. Key capabilities available to customers through the portal: * View subscriptions and payments * Change subscription tier (upgrade or downgrade) * Cancel subscriptions * Update billing details * Download invoices and receipts The Customer Portal uses secure email-based authentication. Buyers authenticate via a verification link sent to their email. *** ## Related Self-service portal for buyers to manage orders and subscriptions. View and manage orders and payment records. # Customer Portal Source: https://waffo.mintlify.app/features/customer-portal Self-service portal for buyers to manage orders and subscriptions ## Let Customers Help Themselves The Customer Portal gives your buyers a self-service interface to manage their purchases, view invoices, update billing details, and manage subscriptions. No support tickets required. Common requests handled automatically. Customers prefer self-service. Give it to them. *** ## What Customers Can Do ### Orders and Payments * View all past orders and payment history * Download invoices and receipts (PDF with multi-language support) * See payment status and details ### Subscriptions * View active subscriptions and billing details * See next billing date and amount * Upgrade or downgrade plans * Cancel subscriptions ### Billing Details * Update billing information (country, postal code, state) * Add business details (business name, tax ID) for invoicing * View tax information *** ## Portal Access Buyers access the Customer Portal through a secure email-based authentication flow: Buyer enters their email on the portal login page. A verification email is sent to the buyer's address. Buyer clicks the link and is authenticated with a secure session. Buyer can view and manage their orders and subscriptions. Buyer sessions have a 30-minute lifetime. The portal automatically prompts re-authentication when the session expires. *** ## Invoice and Receipt The portal includes a full invoice/receipt system: * **Multi-language support** -- Invoices render in 16 languages based on buyer preference * **PDF download** -- Buyers can download invoices as PDF files * **Billing details** -- Invoices include the buyer's billing information (country, state, postal code, business name, tax ID) * **Editable details** -- Buyers can update their billing information from the invoice page ### Invoice Data Sources Invoice data comes from the order's `billingDetail` object: | Field | Description | | -------------- | ------------------------------------------- | | `country` | Buyer's country | | `state` | State/province | | `postalCode` | Postal/ZIP code | | `businessName` | Business name (if applicable) | | `taxId` | Tax identification number (if applicable) | | `isBusiness` | Whether the purchase was made as a business | *** ## Integration ### Email Integration Include a portal link in your transactional emails: ``` Manage your subscription: https://yourstore.waffo.ai/portal ``` ### In-App Button Add a "Manage Subscription" button in your application that directs users to the portal. *** ## Subscription Management in Portal ### Cancellation Flow ``` Cancel button --> Select reason (optional) --> Confirm --> Canceled at period end ``` Cancellations take effect at the end of the current billing period. The buyer retains access until then. ### Plan Change Flow ``` Current plan --> Select new tier --> Review price changes --> Confirm ``` * **Upgrades**: Charged the prorated difference immediately * **Downgrades**: Effective at the end of the current billing period *** ## Security * Time-limited secure sessions * Email-based authentication (no passwords) * Buyers can only access their own data * PCI-compliant payment handling * All data encrypted in transit *** ## Best Practices Include clear "Manage Subscription" links in your app and transactional emails. For seamless in-app integration, generate buyer sessions server-side using the API. Track why customers cancel to improve retention. # Finance & Payouts Source: https://waffo.mintlify.app/features/finance Track income from payments and prepare for payouts ## Overview The Finance page gives you visibility into the money your store earns. It is organized into three tabs: **Income**, **Payout History**, and **Payout Setup**. At the top of the page, a balance summary shows your key financial figures at a glance. ### Balance Summary | Metric | Description | | ---------------------- | ---------------------------------------------- | | **Total Income** | Cumulative income from all successful payments | | **Incoming / Pending** | Funds from recent payments not yet settled | | **Available Balance** | Funds available for future payout | *** ## Income Tab The Income tab displays a list of your paid payments as income records. Each row represents a completed payment that contributed revenue to your store. ### Income Table | Column | Description | | ------------ | -------------------------------------------------------- | | Date | When the payment was completed | | Description | Payment details (product name, order reference) | | Gross Amount | Total amount received from the customer | | Fees | Estimated transaction fees (currently simulated at 2.9%) | | Net Income | Gross amount minus fees | The fee column currently shows a **simulated 2.9% fee** for display purposes. Actual fee structures will be finalized when the payout system is fully operational. ### Payout Setup Banner If your payout account has not been configured yet, a banner appears at the top of the Income tab prompting you to complete payout setup. Click it to navigate to the Payout Setup tab. *** ## Payout History Tab The Payout History tab is where completed payouts will appear once the payout system is live. Payout processing is not yet available. This tab currently shows an empty state. When payouts become operational, it will display columns for date, status, gross amount, fees, and net payout amount. *** ## Payout Setup Tab The Payout Setup tab guides you through a multi-step process to prepare your account for receiving payouts. This setup flow collects the information Waffo Pancake will need to send you funds once payout processing is enabled. ### Setup Steps Provide your legal business information including business name, address, and entity type. Confirm your contact email and complete identity verification (Know Your Customer). Add the bank account or payment method where you want to receive payouts. ### Verification Status Each step shows a verification status so you can track your progress: | Status | Meaning | | --------------- | -------------------------------------------- | | **Not Started** | Step has not been begun | | **In Progress** | Information submitted, awaiting verification | | **Verified** | Step completed and approved | If your business details are incomplete, the setup flow links directly to the business details settings page so you can fill in the required information. Completing payout setup now means you will be ready to receive payouts as soon as the feature becomes available. You can return to this tab at any time to check your verification progress. *** ## Current Limitations The finance system is actively being built out. Here is what is available today versus what is coming: | Feature | Status | | ------------------------------------------- | ----------- | | Income list from paid payments | Available | | Balance summary (total, pending, available) | Available | | Simulated fee display (2.9%) | Available | | Payout setup flow (3-step preparation) | Available | | Payout processing and transfers | Coming soon | | Payout history records | Coming soon | # Integrations Source: https://waffo.mintlify.app/features/integrations Connect Waffo Pancake with your applications ## Integrations Overview Waffo Pancake provides a powerful API and developer tools to integrate payments directly into your applications. *** ## API Architecture Waffo Pancake uses a **hybrid API**: * **REST (POST)** for all write operations via `/v1/actions/{domain}/{action}` * **GraphQL** for all read operations via `/v1/graphql` ``` Your Application | +-- REST POST requests --> Create/Update/Delete | +-- GraphQL queries --> Read data ``` ### Base URL ``` https://waffo-pancake-auth-service.vercel.app/v1 ``` *** ## API Keys API Keys authenticate server-to-server requests. Authentication is handled automatically by the SDK. Created for `test` environment. No real charges. Created for `prod` environment. Process real payments. ### Creating API Keys Go to **Dashboard > Developers**. Click "Generate" to create a key pair. The public key is sent to the server. Give it a descriptive nickname (e.g., "Production Server"). Choose **Test** or **Production** environment. Keys are environment-specific. Download and securely store your private key. It is only shown once. ### API Key Endpoints | Endpoint | Description | | ------------------------------------- | -------------------------- | | `POST /v1/actions/api-key/create-key` | Create a new API key | | `POST /v1/actions/api-key/delete-key` | Delete an existing API key | Never expose your private key in client-side code, version control, or public repositories. *** ## Webhooks Webhooks notify your server when events occur in real-time. ### Setting Up Go to **Dashboard > Settings > Webhooks**. Configure separate webhook URLs for each environment: * **Test webhook URL** -- receives events from test mode * **Live webhook URL** -- receives events from production mode Save your settings. Your endpoints will begin receiving all webhook events. There is no event filtering -- your webhook endpoint receives all events. Filter by event type in your server-side handler. ### Verifying Webhook Signatures A **webhook public key** is displayed on the Webhooks settings page. Use this key to verify that incoming webhook payloads were sent by Waffo Pancake and have not been tampered with. *** ## Common Endpoints ### Stores | Endpoint | Description | | ------------------------------------- | -------------------- | | `POST /v1/actions/store/create-store` | Create a store | | `POST /v1/actions/store/update-store` | Update store details | | `POST /v1/actions/store/delete-store` | Soft-delete a store | ### Products | Endpoint | Description | | ------------------------------------------------------- | -------------------------------------------------- | | `POST /v1/actions/onetime-product/create-product` | Create a one-time product | | `POST /v1/actions/onetime-product/update-product` | Update a one-time product (creates new version) | | `POST /v1/actions/onetime-product/update-status` | Activate or deactivate a one-time product | | `POST /v1/actions/onetime-product/publish-product` | Publish a one-time product across environments | | `POST /v1/actions/subscription-product/create-product` | Create a subscription product | | `POST /v1/actions/subscription-product/update-product` | Update a subscription product | | `POST /v1/actions/subscription-product/update-status` | Activate or deactivate a subscription product | | `POST /v1/actions/subscription-product/publish-product` | Publish a subscription product across environments | ### Orders | Endpoint | Description | | ---------------------------------------------------- | ------------------------------------------- | | `POST /v1/actions/onetime-order/create-order` | Create a one-time checkout session | | `POST /v1/actions/onetime-order/cancel-order` | Cancel a pending one-time order | | `POST /v1/actions/subscription-order/create-order` | Create a subscription checkout session | | `POST /v1/actions/subscription-order/cancel-order` | Cancel a subscription | | `POST /v1/actions/subscription-order/change-product` | Upgrade or downgrade a subscription product | ### Refunds | Endpoint | Description | | ---------------------------------------------- | ---------------- | | `POST /v1/actions/refund-ticket/create-ticket` | Request a refund | ### Data Queries | Endpoint | Description | | ------------------ | --------------------------------------------------------- | | `POST /v1/graphql` | Query any data (stores, products, orders, payments, etc.) | *** ## Security Best Practices Store private keys in environment variables, never in code. Regularly rotate keys, especially after team changes. Use different API keys for test and production environments. Store private keys using your platform's secret management. *** ## Next Steps Step-by-step integration guide. Complete endpoint documentation. # Notifications Source: https://waffo.mintlify.app/features/notifications Stay informed with real-time activity alerts ## Notification Center The Notification Center keeps you informed about important events in your Waffo Pancake account. Access it from the bell icon in the Dashboard header. *** ## Notification Types * New payments received * Payment failures * Refund requests * Payout notifications * New subscriptions * Cancellations * Trial expirations * Renewal failures * New customer signups * Customer updates * Portal access * Payout processed * API key events * Security alerts * Feature announcements *** ## Notification Panel ### Accessing Notifications 1. Click the bell icon in the Dashboard header 2. View unread count on the badge 3. Browse recent notifications ### Notification Content Each notification includes: | Element | Description | | ----------- | --------------------------------------------- | | **Icon** | Visual indicator of notification type | | **Title** | Brief description of the event | | **Details** | Relevant information (amount, customer, etc.) | | **Time** | When the event occurred | | **Actions** | Quick actions (view details, mark read) | *** ## Notification Page Access the full Notifications page from **Dashboard → Notifications** for: * Complete notification history * Advanced filtering * Bulk actions ### Filtering Options | Filter | Options | | -------------- | ------------------------------------------ | | **Type** | Payments, Subscriptions, Customers, System | | **Status** | Unread, Read, All | | **Date Range** | Today, This Week, This Month, Custom | ### Bulk Actions * Mark all as read * Clear old notifications * Export notification history *** ## Notification Settings Configure which notifications you receive in **Settings --> Notifications**. ### Customer Email Notifications Control which emails are sent to your customers: | Setting | Description | | ------------------------- | ------------------------------------------------------ | | Order confirmation | Email customers when they complete a one-time purchase | | Subscription confirmation | Email customers when they start a new subscription | | Subscription cycled | Email customers when their subscription renews | | Subscription canceled | Email customers when their subscription is canceled | | Subscription revoked | Email customers when their subscription is revoked | | Subscription past due | Email customers when their subscription payment fails | ### Merchant Email Notifications Control which emails you receive as a merchant: | Setting | Description | | ------------------------- | -------------------------------------------------------------- | | Order notification | Receive an email when a customer completes a one-time purchase | | Subscription notification | Receive an email when a customer starts a new subscription | *** ## Real-Time Updates Notifications appear in real-time without page refresh via the notification panel in your Dashboard. *** ## Notification Actions ### Quick Actions From the notification panel: * **View** — Go to related item (payment, customer, etc.) * **Mark Read** — Dismiss the notification * **Dismiss** — Remove from panel ### Detailed View Click on a notification to see full details: * Complete event information * Related customer data * Transaction details * Available actions *** ## Security Notifications Security notifications cannot be disabled. They alert you to important security events. Security alerts include: * New device sign-in * API key created/deleted * Unusual activity ### Recommended Actions When you receive a security alert: 1. Review the activity immediately 2. Verify it was authorized 3. If suspicious, revoke any compromised API keys and sign out of all sessions 4. Contact support if needed *** ## Best Practices Enable instant notifications for payment failures to quickly resolve issues. For high-volume stores, use daily email digests instead of instant notifications. Always investigate security notifications promptly. Keep your notification panel clean by marking items as read. *** ## Notification History Access historical notifications from the Notifications page in your Dashboard. # Orders & Payments Source: https://waffo.mintlify.app/features/orders-payments Track transactions and manage your payment lifecycle ## Overview Every purchase in Waffo Pancake creates an **order** and an associated **payment** record. Orders represent the customer's intent to buy, while payments track the actual money movement. *** ## Order Statuses Orders have different status sets depending on the product type. ### One-Time Orders | Status | Description | | ----------- | ------------------------------------ | | `pending` | Order created, awaiting payment | | `completed` | Payment succeeded, order fulfilled | | `canceled` | Order was canceled before completion | ### Subscription Orders | Status | Description | | ----------- | --------------------------------------------------------- | | `pending` | Subscription created, awaiting first payment | | `active` | Subscription is live and billing normally | | `trialing` | Customer is in a free trial period | | `past_due` | Payment failed, retrying | | `canceling` | Cancellation requested, active until period end | | `canceled` | Subscription canceled (access continues until period end) | | `expired` | Subscription expired | *** ## Payment Statuses Payment initiated, awaiting processing. Payment is being processed. Payment completed successfully. Payment failed during processing. Full refund has been processed. A partial refund has been processed. *** ## Payment List View all payments in a table with the following columns: | Column | Description | | -------------- | ---------------------------------------- | | Date | Transaction timestamp | | Amount | Payment amount in smallest currency unit | | Tax Amount | Tax collected on the transaction | | Status | Current payment status | | Payment Method | `card`, `bank_transfer`, or `wallet` | | Customer | Customer email address | | Currency | ISO 4217 currency code | ### Filtering | Filter | Options | | ---------- | -------------------------------------------------------------------------------- | | Status | `pending`, `processing`, `succeeded`, `failed`, `refunded`, `partially_refunded` | | Date Range | Custom start and end dates | *** ## Payment Details Click any payment to view its full record. ### Transaction Info | Field | Description | | ---------- | --------------------------------------------- | | Payment ID | UUID v4 identifier | | Order ID | Associated order | | Store ID | Store that received the payment | | Amount | Gross payment amount (smallest currency unit) | | Currency | ISO 4217 currency code | | Status | Current payment status | | Created At | ISO 8601 timestamp | | Updated At | ISO 8601 timestamp | ### Amount Details | Field | Description | | -------------------- | ----------------------------- | | `amount` | Total charged amount | | `taxAmount` | Tax portion of the amount | | `settlementCurrency` | Currency used for settlement | | `settlementAmount` | Amount in settlement currency | | `refundedAmount` | Total amount refunded so far | ### Billing Detail | Field | Description | | -------------- | ----------------------------------- | | `country` | Customer's billing country | | `state` | Billing state or region | | `postcode` | Billing postal code | | `isBusiness` | Whether this is a business purchase | | `businessName` | Business name (if applicable) | | `taxId` | Tax ID (if applicable) | ### Payment Method Payments record which method was used: | Method | Value | | ----------------- | --------------- | | Credit/Debit Card | `card` | | Bank Transfer | `bank_transfer` | | Digital Wallet | `wallet` | Additional method-specific details may be available in the `paymentMethodDetails` field. The structure of this field varies by payment method. *** ## Supported Payment Methods Credit and debit card payments. Direct bank-to-bank transfers. Digital wallet payments (Apple Pay, Google Pay, etc.). *** ## Refunds Refund requests are handled through a separate ticket-based workflow. Buyers submit a refund ticket specifying the payment and reason, and merchants review and approve or reject the request. For full details on the refund process, statuses, and policies, see the [Refunds](/customers/refunds) page. **Key rules:** * One-time product refunds must be requested within **7 days** of payment * Subscription cancellations take effect at the end of the current billing period * Refund tickets track their own status: `pending`, `approved`, `rejected`, `processing`, `succeeded`, `failed` *** ## API Reference ### Creating Orders Orders are created through a two-step checkout session flow: **Step 1: Create a checkout session** (API Key or Store Slug auth) ```bash One-Time Product theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/checkout/create-session \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "storeId": "store-uuid", "productId": "product-uuid", "productType": "onetime", "currency": "USD" }' ``` ```bash Subscription Product theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/checkout/create-session \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "storeId": "store-uuid", "productId": "product-uuid", "productType": "subscription", "currency": "USD" }' ``` This returns a `sessionId`, `checkoutUrl`, and `expiresAt`. The session locks the product version and price snapshot for 7 days. **Step 2: Create the order** (API Key auth) ```bash One-Time Order theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/onetime-order/create-order \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "checkoutSessionId": "session-uuid", "billingDetail": { "country": "US", "isBusiness": false, "state": "CA" } }' ``` ```bash Subscription Order theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/subscription-order/create-order \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "checkoutSessionId": "session-uuid", "billingDetail": { "country": "US", "isBusiness": false, "state": "CA" } }' ``` Both endpoints return a `checkoutUrl` that the buyer should be redirected to for payment. ### Querying Payments Use the GraphQL endpoint to query payment records: ```graphql theme={"dark"} query { payments(storeId: "store-uuid", limit: 20) { id orderId amount currency status paymentMethod amountDetails { amount taxAmount settlementCurrency settlementAmount refundedAmount } billingDetail { country state postcode isBusiness businessName taxId } createdAt } } ``` All amounts are in the smallest currency unit. For example, `2900` in USD means \$29.00. For zero-decimal currencies like JPY, `4500` means 4500 yen. # Products Source: https://waffo.mintlify.app/features/products One-time or recurring. Your revenue, your rules. ## Products = Revenue Products are what you sell. One-time payment or subscription. We handle the rest. *** ## Two Types Customer pays once. Done. * Digital downloads * Lifetime licenses * Templates, courses, assets Customer pays on schedule. * SaaS plans * Memberships * Service retainers *** ## Create a Product Dashboard --> Products --> **Create Product** ```json theme={"dark"} { "storeId": "your-store-uuid", "name": "Pro Plan", "prices": { "USD": { "amount": 2900, "taxIncluded": false, "taxCategory": "saas" } } } ``` **Done.** You get a checkout URL. Share it anywhere. *** ## Product Fields ### Required | Field | What It Is | | ------------ | ----------------------------------- | | Name | What customers see | | Price | How much you charge (smallest unit) | | Currency | USD, EUR, GBP, CNY, JPY, HKD, etc. | | Type | One-time or Subscription | | Tax Category | SaaS, Digital Goods, Software, etc. | ### Optional | Field | Default | Purpose | | ----------- | ------- | ---------------------------- | | Description | — | Markdown. Sell your product. | | Image | — | 400x400px recommended | | Success URL | — | Redirect after purchase | | Metadata | — | Custom key-value data | *** ## Multi-Currency Pricing Set different prices for different currencies: ```json theme={"dark"} { "USD": { "amount": 2900, "taxIncluded": false, "taxCategory": "saas" }, "EUR": { "amount": 2700, "taxIncluded": true, "taxCategory": "saas" }, "JPY": { "amount": 4500, "taxIncluded": true, "taxCategory": "saas" } } ``` Amounts are in smallest currency unit. 2900 USD = \$29.00. 4500 JPY = ¥4500. *** ## Billing Intervals | Interval | When | Best For | | --------- | --------------- | ------------------- | | Weekly | Every 7 days | High-usage products | | Monthly | Every month | Standard SaaS | | Quarterly | Every 3 months | B2B software | | Yearly | Every 12 months | Committed customers | Annual plans with 15-20% discount = lower churn + better cash flow. *** ## Checkout Links Checkout URLs are generated by creating a checkout session via the API: ```bash theme={"dark"} POST /v1/actions/checkout/create-session ``` The resulting checkout URL follows this structure: ``` /store/{store-slug}/checkout/{sessionId} ``` **Share it anywhere:** * Website button * Twitter bio * Email signature * Discord server **Generating Checkout URLs:** * Dashboard: Click "Copy Link" on any product * API: Create a checkout session with the product ID **Test vs Live:** * Toggle Test Mode in Dashboard header * Test mode generates test checkout sessions *** ## Product Status Live. Customers can buy. Hidden. Existing subscriptions continue. *** ## Updating Products Products use **immutable versioning**: Updates create new versions. Existing subscriptions keep their original version. | Field | Impact | | ---------------- | ---------------------------- | | Name/Description | Creates new version | | Image | Creates new version | | Price | New purchases only | | Interval | Cannot change after creation | ### Environment Sync Sync product versions between test and production: ```bash theme={"dark"} POST /v1/actions/onetime-product/merge-product { "id": "product-id", "fromEnvironment": "test", "toEnvironment": "prod" } ``` *** ## Product Tiers (Subscriptions) For subscription products, tiers are built-in: ```json theme={"dark"} { "tiers": [ { "tierKey": "starter", "tierName": "Starter", "prices": { "USD": { "amount": 900, "taxIncluded": false, "taxCategory": "saas" } }, "features": ["5 projects", "Basic support"] }, { "tierKey": "pro", "tierName": "Pro", "prices": { "USD": { "amount": 2900, "taxIncluded": false, "taxCategory": "saas" } }, "features": ["Unlimited projects", "Priority support"] } ] } ``` **Tier Management:** * Customers can upgrade/downgrade via Customer Portal * Upgrade: Charged difference immediately * Downgrade: Effective at period end *** ## Best Practices Include billing period: * "Pro Plan - Monthly" * "Pro Plan - Annual (Save 20%)" * Round numbers ($29, not $28.73) * Annual discount (15-20%) * Research competitors * 400x400px minimum * PNG or JPG * Under 2MB # Refunds Source: https://waffo.mintlify.app/features/refunds Manage refund tickets, process full or partial refunds, and track refund status ## Overview Waffo Pancake uses a **refund ticket** system. Buyers request refunds through the API or Customer Portal, and each request creates a ticket that moves through a defined lifecycle. Merchants review and resolve tickets from the dashboard. *** ## Business Rules These rules are enforced by the API and cannot be overridden. * **One-time products** are eligible for refund within **7 days** of payment. * **Subscriptions** do not use the refund ticket system. Cancellation takes effect at the end of the current billing period. * **Partial refunds** are supported by providing a custom `amount` (in smallest currency units) when creating a ticket. *** ## Refund Ticket Statuses Every refund ticket moves through the following lifecycle: Refund requested, awaiting review. Refund approved by the merchant. Refund request denied. Refund is being processed by the payment provider. Refund completed successfully. Refund processing failed. *** ## Creating a Refund Ticket Refund tickets are created by calling the API with API Key authentication. ### Endpoint ``` POST /v1/actions/refund-ticket/create-ticket ``` **Authentication:** API Key ### Request Body The ID of the payment to refund (UUID v4). A description of why the refund is being requested. Amount to refund in smallest currency units (e.g., cents). Omit for a full refund. ### Response The unique ID of the created refund ticket. Initial status of the ticket. Always `pending` on creation. The refund amount in smallest currency units. ### Example ```bash cURL theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/refund-ticket/create-ticket \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "paymentId": "550e8400-e29b-41d4-a716-446655440000", "reason": "Product not as described", "amount": 1500 }' ``` ```typescript SDK theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); const { ticketId, status, requestedAmount } = await client.refunds.createTicket({ paymentId: "550e8400-e29b-41d4-a716-446655440000", reason: "Product not as described", amount: 1500, }); ``` *** ## Querying Refund Tickets Use GraphQL to retrieve refund ticket data. ```graphql theme={"dark"} query { refundTickets(storeId: "STORE_ID") { id paymentId storeId customerId reason status requestedAmount approvedAmount currency createdAt updatedAt resolvedAt } } ``` | Field | Type | Description | | ----------------- | ------- | ------------------------------------------- | | `id` | string | Refund ticket ID | | `paymentId` | string | Associated payment ID | | `storeId` | string | Store that owns the payment | | `customerId` | string | Buyer who requested the refund | | `reason` | string | Reason provided by the buyer | | `status` | string | Current ticket status | | `requestedAmount` | integer | Amount the buyer requested | | `approvedAmount` | integer | Amount approved (may differ from requested) | | `currency` | string | ISO 4217 currency code | | `createdAt` | string | ISO 8601 timestamp | | `updatedAt` | string | ISO 8601 timestamp | | `resolvedAt` | string | ISO 8601 timestamp (null if unresolved) | *** ## Webhook Notifications You can configure webhooks to receive notifications when refund ticket events occur. See the [Webhooks guide](/integrate/webhooks) for setup instructions. *** ## Reducing Refund Requests Accurate descriptions reduce "not as expected" refund requests. Let customers try before buying to reduce post-purchase regret. Address issues quickly before they become refund requests. Use a clear billing descriptor so customers recognize charges. # Subscriptions Source: https://waffo.mintlify.app/features/subscriptions Recurring revenue on autopilot ## Recurring Revenue. Automated. Customers subscribe. We handle billing cycles, failed payments, and lifecycle management. You focus on your product. *** ## How It Works ``` Customer subscribes → Billing cycle → Auto-charge → Repeat ``` Failed payment? The subscription enters `past_due` status until the payment situation is resolved. *** ## Subscription States | Status | Description | | ---------- | ----------------------------------- | | `pending` | Awaiting first payment | | `active` | Live and billing normally | | `trialing` | In free trial period | | `past_due` | Payment failed, awaiting resolution | | `canceled` | Will not renew after current period | | `paused` | Billing paused temporarily | *** ## Billing Intervals | Interval | Frequency | Best For | | --------- | --------------- | -------------------- | | Weekly | Every 7 days | Usage-heavy products | | Monthly | Every month | Standard SaaS | | Quarterly | Every 3 months | B2B software | | Yearly | Every 12 months | Committed customers | *** ## Failed Payments When a payment fails, the subscription transitions to `past_due` status. The customer is notified via email to update their payment method. *** ## Managing Subscriptions ### Cancel Cancellation is always effective at the end of the current billing period. The customer retains access until the paid period ends. ```bash theme={"dark"} POST /v1/actions/subscription-order/cancel-order { "orderId": "550e8400-e29b-41d4-a716-446655440000" } ``` Response includes `currentPeriodEnd` so you know when access expires. There is no immediate cancellation option. Customers always retain access through the end of their paid period. ### Upgrade/Downgrade | Scenario | Behavior | | ------------------- | ----------------------------------------------------- | | Upgrade mid-cycle | Takes effect immediately | | Downgrade mid-cycle | Takes effect at the end of the current billing period | ```bash theme={"dark"} POST /v1/actions/subscription-order/change-tier { "orderId": "550e8400-e29b-41d4-a716-446655440000", "newTierVersionId": "tier-version-uuid" } ``` *** ## Metrics ### MRR (Monthly Recurring Revenue) ``` Weekly subscription: $10 × 4.33 = $43.30 MRR Monthly subscription: $29 × 1 = $29 MRR Annual subscription: $290 ÷ 12 = $24.17 MRR ``` ### Key Metrics | Metric | What It Tells You | | ------ | ------------------------- | | MRR | Monthly recurring revenue | | Churn | % subscriptions canceled | | LTV | Customer lifetime value | | ARPU | Average revenue per user | *** ## Webhooks Subscribe to subscription lifecycle events via webhooks. Configure webhook endpoints in **Settings --> Webhooks**. Specific webhook event names are not listed here as they may change. Refer to the webhook configuration in your Dashboard for the current list of available events. Webhook payloads use standard Waffo Pancake conventions: * IDs are UUID v4 format * Amounts in smallest currency units * Timestamps in ISO 8601 UTC * Billing frequency uses the `billingPeriod` field (e.g., `monthly`, `yearly`) *** ## Customer Portal Let customers manage their own subscriptions: * View details * Update payment method * Change plans * Cancel * Download invoices Self-service subscription management. *** ## Best Practices 15-20% off yearly = lower churn + better cash flow. Failed payment ≠ instant cancellation. Give time to update card. Trial ending. Upcoming charge. No surprises. # Test Mode Source: https://waffo.mintlify.app/features/test-mode Break things. Risk-free. ## Test Everything. Break Nothing. Build and test your entire integration without real transactions. No real charges. No real payouts. Just safe experimentation. No real money moves. Everything works like Live Mode. *** ## Test vs Live | | Test Mode | Live Mode | | ------------ | ---------------- | ---------------- | | Transactions | Simulated | Real charges | | Money | Fake | Real funds | | Data | Isolated | Production | | Webhooks | Fully functional | Fully functional | | API Behavior | Identical | Identical | **Switch modes:** Dashboard header toggle or `X-Environment` header in API calls. | Header Value | Mode | | --------------------- | --------- | | `X-Environment: test` | Test Mode | | `X-Environment: prod` | Live Mode | Always verify you're in the correct mode before sharing payment links. *** ## API Keys by Environment API Keys are created for a specific environment (test or production). When creating an API key in the Dashboard, you select which environment the key belongs to. | Environment | Purpose | | ----------- | ----------------------- | | Test | Development and testing | | Production | Real payments | API Keys use key pair authentication, not prefixed secret keys. See [Authentication](/api-reference/authentication) for details. *** ## Test Cards ### Successful Payments | Card | Brand | | --------------------- | ---------- | | `4242 4242 4242 4242` | Visa | | `5555 5555 5555 4444` | Mastercard | | `3782 822463 10005` | Amex | ### Declined Payments | Card | Error | | --------------------- | ------------------ | | `4000 0000 0000 0002` | Declined | | `4000 0000 0000 9995` | Insufficient funds | | `4000 0000 0000 0069` | Expired card | ### 3D Secure | Card | Behavior | | --------------------- | ----------------------- | | `4000 0027 6000 3184` | Requires authentication | | `4000 0000 0000 3220` | Authentication fails | Any future expiry date. Any 3-digit CVC. *** ## Test Payment Methods ### Digital Wallets Test Mode shows simulated UI: * **Apple Pay** -- Safari/iOS * **Google Pay** -- Chrome/Android *** ## Test Webhooks Webhooks fire normally in Test Mode. To test your webhook endpoints: 1. Register your webhook endpoint in Dashboard --> Developers 2. Switch to Test Mode 3. Perform actions that trigger events (create orders, complete payments) 4. Your endpoint receives webhook events just like in Live Mode *** ## Test Subscriptions Test the full lifecycle: 1. **Create** -- Subscribe via test checkout 2. **Bill** -- Billing occurs on schedule (use short intervals for faster testing) 3. **Update** -- Change plans via the Customer Portal or API 4. **Cancel** -- Test cancellation flow 5. **Expire** -- Verify expired subscription behavior *** ## Test Data ### Isolation Test data is completely separate: * Test products don't appear in Live Mode * Test customers are separate * Test transactions don't affect live reports ### Environment Sync When ready to go live, sync your products from test to production: ```bash theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/onetime-product/publish-product \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY_TOKEN" \ -d '{ "id": "product-uuid" }' ``` The publish-product endpoint is a one-way operation from test to production. It does not require an `X-Environment` header. *** ## Going Live Checklist Before accepting real payments: * [ ] Complete end-to-end testing in test mode * [ ] Test edge cases (declined cards, failures) * [ ] Verify webhook handling * [ ] Test checkout on mobile devices * [ ] Connect bank account (Finance --> Payout Setup) * [ ] Complete business details (Settings --> Business Details) * [ ] Review product pricing * [ ] Sync products from test to production using publish-product Full going-live checklist. # Guide Source: https://waffo.mintlify.app/guides/introduction Step-by-step guides for common business scenarios, from product setup to daily operations ## Find the Right Guide for Your Business Whether you're selling digital products, running a SaaS subscription, or managing day-to-day operations, these guides walk you through the entire process — from setting up in the Dashboard to going live. *** ## Business Scenarios Courses, templates, ebooks, software licenses. Set up one-time purchases and start selling in minutes. Monthly/yearly plans with trials and cancellation handling. Manage recurring revenue with ease. Billing for AI products and API services. Subscription tiers with token quotas, dynamic pricing, and metering tools. *** ## Operations Get notified when payments succeed, subscriptions renew, or refunds are processed. Configure notifications in Dashboard. Handle refund requests, set refund policies, and track refund status from your Dashboard. *** ## Quick Decision Guide | I want to... | Guide | | --------------------------------------- | -------------------------------------------------- | | Sell a course, ebook, or template | [Sell Digital Products](/guides/one-time-payments) | | Launch a SaaS with monthly/yearly plans | [Run SaaS Subscriptions](/guides/subscriptions) | | Bill for AI products or API usage | [AI Product Billing](/guides/usage-based) | | Get notified on payment events | [Set Up Webhooks](/guides/webhooks) | | Handle customer refund requests | [Manage Refunds](/guides/refunds) | *** ## Before You Start Make sure you have: 1. **A Waffo Pancake account** — [Sign up here](https://dashboard.waffo.ai) 2. **A store created** — You'll be guided through this during onboarding 3. **Test mode enabled** — All guides use test mode by default, so you can safely experiment You can do everything from the Dashboard without writing any code. When you're ready for deeper integration, check the [API Reference](/api-reference/introduction). *** ## No-Code vs Code ### No-Code (Recommended to start) 1. Create products in Dashboard 2. Copy the checkout link 3. Share anywhere — your website, email, social media **Best for:** Quick launches, validating ideas, non-technical merchants. ### Code Integration 1. Create checkout sessions via API 2. Handle webhooks for automated fulfillment 3. Build custom flows **Best for:** Custom experiences, automated delivery, advanced tracking. All guides start with the no-code approach. Code integration is introduced where it adds value, with links to the API Reference for details. # Sell Digital Products Source: https://waffo.mintlify.app/guides/one-time-payments Set up one-time purchases for courses, templates, ebooks, and software licenses ## Who Is This For? This guide is for merchants who sell digital products with a single payment — no recurring billing. Common examples include: | Product Type | Examples | | ----------------- | ---------------------------------------------- | | Digital Downloads | Ebooks, templates, design assets, stock photos | | Online Courses | Video courses, tutorials, workshops | | Software Licenses | Desktop apps, plugins, browser extensions | | Digital Services | One-time consultations, audits, reports | *** ## Step 1: Create Your Product In your Dashboard, navigate to **Products** from the sidebar. Products list page Click the **Create Product** button in the top right corner. Select **One-Time** as the product type. Create one-time product form * **Name**: Your product name * **Price**: Set the price and currency * **Description**: What the customer gets * **Image**: Upload a product image (optional but recommended) You can set prices in multiple currencies. Waffo Pancake will display the right currency based on the customer's location. Click **Save** to create the product. The product starts in **test mode** — only visible to test checkouts. When you're ready to sell, switch the product status to **Active** in the product detail page. *** ## Step 2: Share Your Checkout Link Once your product is created, you'll get a checkout link that you can share anywhere. ### Get the Link On the product detail page, copy the checkout link: ``` https://checkout.waffo.ai/your-store/my-product ``` ### Where to Share * **Your website** — Add a "Buy Now" button linking to the checkout URL * **Email campaigns** — Include the link in newsletters or launch emails * **Social media** — Share directly on Twitter, Instagram, or other platforms * **Landing pages** — Embed the link in your marketing pages This is all you need to start selling. No code required. Customers click the link, pay, and receive a confirmation email automatically. *** ## Step 3: Track Orders After customers purchase, you can track everything from the Dashboard. ### Orders Page Navigate to **Payments** in the sidebar to see all completed orders. Payments list page Each order shows: * Customer email * Amount paid * Payment method * Order status * Date and time ### Email Notifications By default, both you and the customer receive email notifications on purchase. You can customize notification settings in **Settings → Notifications**. *** ## Step 4: Manage Your Products ### Update Product Details You can update the product name, description, price, or image at any time from the product detail page. When you update a product, Waffo Pancake creates a new version. Existing customers who already purchased are not affected. ### Publish to Production Products you create in test mode need to be published before real customers can purchase them: 1. Go to the product detail page 2. Click **Publish to Production** 3. The product is now live and available for real payments *** ## Business Scenarios The following are example scenarios. Adjust them to match your actual business. ### Scenario 1: Selling an Online Course 1. **Create product**: Enter your course name and set a price of \$49 (example) 2. **Share link**: Add the checkout link to your course landing page 3. **Customer purchases**: They pay and receive an order confirmation email 4. **Deliver content**: Use webhooks to automatically grant course access, or manually send access details ### Scenario 2: Selling Design Templates 1. **Create product**: Upload your template bundle with preview images 2. **Set pricing tiers**: Create separate products for different bundles (e.g., Basic $19, Pro $49, Complete \$99) (example) 3. **Share links**: Each product has its own checkout link 4. **Delivery**: Configure webhooks to send download links after purchase ### Scenario 3: Software Licenses 1. **Create product**: Set up your software as a one-time purchase 2. **Customer purchases**: Payment is processed automatically 3. **Generate license**: Use webhooks to trigger license key generation in your system 4. **Deliver**: Customer receives their license key via email *** ## Going Further: Code Integration For automated delivery or custom checkout flows, you can integrate with the Waffo Pancake API. ### When You Need Code * **Automated delivery**: Send download links or license keys automatically after payment * **Custom tracking**: Pass metadata (user ID, campaign source) to track conversions * **Dynamic pricing**: Create checkout sessions with custom amounts ### How It Works ``` Customer clicks "Buy" → Checkout Session → Payment → Webhook → Your server delivers the product ``` For API details, see the [API Reference](/api-reference/introduction). *** ## Testing Before Launch Use test mode to verify your entire flow before accepting real payments. Toggle the **Test/Production** switch in the top navigation bar of your Dashboard. Open your checkout link and complete a purchase using a test card: | Scenario | Card Number | | ----------------------- | --------------------- | | Successful payment | `4242 4242 4242 4242` | | Declined | `4000 0000 0000 0002` | | Requires authentication | `4000 0025 0000 3155` | Check that the test order appears in your **Payments** page and that notification emails were sent. *** ## Launch Checklist Before going live: * [ ] Product created with correct name, description, and price * [ ] Checkout link tested in test mode * [ ] Order confirmation email looks good * [ ] Product published to production * [ ] Checkout link shared on your website / social media *** ## Next Steps Automate delivery by receiving payment notifications Handle refund requests from customers # Manage Refunds Source: https://waffo.mintlify.app/guides/refunds Handle refund requests, set refund policies, and track refund status ## What You'll Learn How to manage the refund process from your Dashboard: * Review and process refund requests * Understand refund types and policies * Track refund status * Handle subscription cancellations with refunds *** ## Refund Types | Type | Description | When to Use | | ------------------ | -------------------------------- | ----------------------------------------------- | | **Full Refund** | Refund the entire payment amount | Customer dissatisfied, product not as described | | **Partial Refund** | Refund part of the payment | Partial service delivered, goodwill gesture | *** ## Step 1: Review Refund Requests Customers can submit refund requests through the Customer Portal. These appear in your Dashboard. Navigate to **Payments** in the sidebar to see all payments, including those with refund requests. Payments page with refund requests Click on a payment to see the refund request details: * Customer's reason for the refund * Requested amount * Request date * Payment details (amount, date, product) *** ## Step 2: Process Refunds ### Approve or Reject For each refund request, you can: * **Approve**: The refund is processed and the customer is notified * **Reject**: The request is declined with an optional note to the customer Refund approval dialog ### What Happens After Approval 1. The refund amount is deducted from your balance 2. The customer receives a refund confirmation email 3. Funds are returned to the customer's original payment method 4. The payment status updates to reflect the refund Refunds are permanent. Once approved, they cannot be reversed. Review each request carefully before approving. *** ## Step 3: Track Refund Status Refund tickets go through these statuses: | Status | Meaning | | ------------ | ---------------------------------------------------- | | `pending` | Customer submitted request, awaiting your review | | `processing` | Refund approved, being processed by payment provider | | `succeeded` | Refund completed, funds returned to customer | | `rejected` | Request rejected by you | | `failed` | Refund failed during processing (rare) | You can filter and track all refunds in the **Payments** section of your Dashboard. *** ## Refund Policies ### Setting Expectations We recommend establishing clear refund policies and communicating them to customers: | Policy Element | Recommendation | | ---------------- | ------------------------------------------ | | **Time window** | 7–30 days after purchase | | **Conditions** | Product not as described, technical issues | | **Exclusions** | Consumed services, customized products | | **Process time** | 5–10 business days for funds to appear | Display your refund policy clearly on your checkout page and product pages. Clear policies reduce disputes and build customer trust. *** ## Subscription Refunds ### When a Subscriber Requests a Refund For subscription products, consider these options: 1. **Refund + Cancel**: Refund the current period and cancel the subscription 2. **Refund only**: Refund the current period but keep the subscription active 3. **Cancel only**: Cancel the subscription without a refund (customer keeps access until period ends) ### Recommended Approach For most cases, **refund + cancel** is the cleanest approach. The customer gets their money back, and the subscription is terminated. *** ## Business Scenarios ### Scenario 1: Digital Product Refund **Customer says:** "The course didn't cover what was advertised." **Recommended action:** 1. Review the refund request in Dashboard 2. If within your refund window (e.g., 7 days), approve the full refund 3. Customer receives confirmation and funds are returned ### Scenario 2: Subscription First-Month Refund **Customer says:** "I didn't realize I'd be charged after the trial." **Recommended action:** 1. Approve the refund for the first payment 2. Cancel the subscription 3. Consider improving trial-to-paid communication ### Scenario 3: Partial Refund for Service Issue **Customer says:** "The service was down for a week." **Recommended action:** 1. Calculate the proportional refund (e.g., 25% for 1 week of a month) 2. Issue a partial refund 3. Optionally extend the current period as a goodwill gesture *** ## Going Further: Code Integration ### Webhooks for Refunds If you use webhooks, you can automate post-refund actions: | Event | Automated Action | | ------------------ | ------------------------------------------ | | `payment.refunded` | Revoke product access, update database | | Refund approved | Send internal notification to support team | ### API Refunds For programmatic refund processing, see the [API Reference — Refunds](/api-reference/endpoints/refunds). *** ## Best Practices 1. **Respond quickly**: Review refund requests within 24–48 hours 2. **Be fair**: When in doubt, lean toward the customer's side 3. **Keep records**: Document the reason for each refund decision 4. **Learn from patterns**: If many refunds cite the same reason, fix the underlying issue 5. **Communicate clearly**: Always explain refund decisions to customers *** ## Checklist * [ ] Refund policy established and communicated * [ ] Customer Portal enabled for self-service refund requests * [ ] Refund review process in place for your team * [ ] Webhook events configured for refund notifications (if using code integration) * [ ] Refund policy displayed on checkout/product pages *** ## Next Steps Automate post-refund actions Set up products with clear refund expectations # Run SaaS Subscriptions Source: https://waffo.mintlify.app/guides/subscriptions Set up recurring billing with monthly/yearly plans, trials, and cancellation handling ## Who Is This For? This guide is for merchants who sell subscription-based services or products with recurring billing. Common examples include: | Business Type | Examples | | ----------------- | ---------------------------------------------------- | | SaaS Products | Project management tools, CRM, analytics platforms | | Content Platforms | Online learning, premium newsletters, media access | | Digital Services | Cloud hosting, API access, design tools | | Membership | Community access, premium support, exclusive content | *** ## Subscription Lifecycle Before setting up, it helps to understand how subscriptions flow: ``` Trial → Active → (Renew each period) → Canceled → Expired ↑ ↓ └───── Reactivate ────┘ ``` | Status | What It Means | | ----------- | --------------------------------------------------------- | | `trialing` | Customer is in a free trial period | | `active` | Paying customer, subscription is active | | `past_due` | Payment failed, Waffo is retrying automatically | | `canceling` | Customer canceled, but still has access until period ends | | `canceled` | Subscription has fully ended | *** ## Step 1: Create Subscription Products You'll typically create multiple products for different pricing tiers (e.g., Free, Pro, Enterprise). In your Dashboard, navigate to **Products** from the sidebar. Products list page Click **Create Product** and select **Subscription** as the product type. Create subscription product form * **Name**: Your plan name (e.g., "Basic Plan", "Pro Plan") * **Billing Period**: Choose monthly, quarterly, or yearly * **Price**: Set the recurring price * **Description**: What's included in this plan Create separate products for each billing period. For example, create both a monthly and yearly version of the same plan. Click **Save**. The product starts in test mode. Activate it when ready. *** ## Step 2: Organize Plans with Product Groups If you have multiple tiers (Free, Pro, Enterprise), use **Product Groups** to organize them. Go to **Products** and create a new product group (e.g., "Pricing Plans"). Select the subscription products that belong together. This helps manage pricing tiers as a unit. * **Shared Trial**: If enabled, a customer who used a trial on one plan can't get another trial on a different plan in the same group. Product groups are optional but recommended if you offer multiple pricing tiers. They prevent trial abuse and simplify management. *** ## Step 3: Share and Start Selling Just like one-time products, subscription products get a checkout link. ### Share the Checkout Link Copy the checkout link from the product detail page: ``` https://checkout.waffo.ai/your-store/my-product ``` ### Build a Pricing Page Create a pricing page on your website that links to each plan's checkout URL: > Prices below are examples only. Set them based on your actual business. | Plan | Price | Checkout Link | | ---------- | ---------- | ------------------------------------------------------ | | Basic | \$9/month | `https://checkout.waffo.ai/your-store/basic-plan` | | Pro | \$29/month | `https://checkout.waffo.ai/your-store/pro-plan` | | Enterprise | \$99/month | `https://checkout.waffo.ai/your-store/enterprise-plan` | *** ## Step 4: Monitor Subscriptions ### Subscriptions Dashboard Navigate to **Subscriptions** in the sidebar to see all active, trialing, and canceled subscriptions. Subscriptions list page Each subscription shows: * Customer email * Current plan * Status (active, trialing, past\_due, etc.) * Current period start and end dates * Next billing date ### Subscription Detail Click on any subscription to view details: * Payment history * Plan changes * Cancellation details (if applicable) *** ## Step 5: Handle Cancellations When a customer cancels, the subscription enters a **canceling** state. The customer keeps access until the current billing period ends, then it becomes **canceled**. ### What Happens Automatically * Customer receives a cancellation confirmation email * You receive a notification * Access continues until the period ends * No further charges are made ### View Cancellations in Dashboard Filter subscriptions by **Canceling** or **Canceled** status to see who has left. *** ## Business Scenarios The following are example scenarios. Adjust them to match your actual business. ### Scenario 1: SaaS with Monthly and Yearly Plans 1. **Create products**: Create both monthly and yearly versions of the same plan 2. **Group them**: Create a product group to link them together 3. **Pricing page**: Link each option on your website 4. **Monitor**: Track MRR and churn in the Analytics page ### Scenario 2: Content Platform with Free Trial 1. **Create product**: Set up your subscription plan and price 2. **Enable trial**: Set a 14-day free trial period 3. **Share link**: Customer signs up and starts trial immediately 4. **After trial**: Automatically converts to paid subscription, or expires if they don't add payment ### Scenario 3: API Service with Tiered Plans 1. **Create products**: Create a subscription product for each tier with different API call quotas and prices 2. **Group them**: Create a product group with shared trial 3. **Integrate webhooks**: Grant appropriate API limits based on which plan the customer subscribes to *** ## Going Further: Code Integration ### When You Need Code * **Access control**: Check subscription status in your app to gate features * **Automated provisioning**: Use webhooks to automatically create accounts or adjust limits * **Custom cancellation flows**: Build in-app cancellation with feedback collection ### Key Webhook Events | Event | When It Fires | | ------------------------ | --------------------------- | | `subscription.activated` | New subscription started | | `subscription.updated` | Plan changed or renewed | | `subscription.canceled` | Subscription fully ended | | `order.completed` | Recurring payment processed | | `subscription.past_due` | Payment attempt failed | For webhook setup, see the [Webhooks guide](/guides/webhooks). For API details, see the [API Reference](/api-reference/introduction). *** ## Testing Toggle to test mode in your Dashboard. Use `4242 4242 4242 4242` to simulate a successful subscription. Verify the subscription appears in your Subscriptions page with the correct plan and status. Cancel the test subscription and verify it transitions to canceling → canceled. *** ## Launch Checklist * [ ] Subscription products created for each plan/tier * [ ] Product group set up (if multiple tiers) * [ ] Pricing page links to correct checkout URLs * [ ] Test subscription flow works end-to-end * [ ] Cancellation flow tested * [ ] Notification emails look correct * [ ] Products published to production *** ## Next Steps Automate access control with subscription event notifications Combine subscriptions with metered usage # AI Product Billing Source: https://waffo.mintlify.app/guides/usage-based Set up flexible billing for AI products and API services ## Who Is This For? This guide is for developers building AI products, API services, or any usage-based business. Common examples: | Business Type | Examples | | ------------------ | --------------------------------------------------------- | | AI API Services | LLM API proxies, image generation, speech recognition | | AI SaaS | AI writing assistants, AI code completion, AI translation | | AI Agent Platforms | Automated workflows, data analysis agents | | API Services | Payment processing, messaging, data queries | *** ## How Billing Works with Waffo Pancake Waffo Pancake does not provide built-in usage metering, but you can implement flexible AI product billing through these approaches: ### Approach 1: Subscription Tiers with Token/Request Quotas Create subscription products at different tiers, each with a different token or request quota. > Prices below are examples only. Set them based on your actual business and costs. | Plan | Monthly | Token Quota | Best For | | ----------- | ----------- | ----------- | --------------------- | | **Starter** | \$9/month | 100K tokens | Individual developers | | **Pro** | \$49/month | 1M tokens | Small teams | | **Scale** | \$199/month | 10M tokens | Enterprise | ### Approach 2: Dynamic Pricing via Checkout Session Pass dynamic pricing through `priceSnapshot` when creating a checkout session to charge based on actual usage. ```typescript theme={"dark"} const session = await client.checkout.createSession({ storeId: "store_id", productId: "usage-product-id", productType: "onetime", currency: "USD", // replace with your currency priceSnapshot: { amount: calculatedAmount, // dynamically calculated based on usage taxIncluded: false, taxCategory: "saas", }, }); ``` ### Approach 3: External Metering Tools Use dedicated metering tools to track usage, combined with Waffo Pancake for billing. *** ## Recommended Metering Tools AI model proxy and usage tracking supporting 100+ LLM providers. Unified interface for OpenAI, Anthropic, Gemini, and more with built-in usage analytics. Open-source usage metering platform designed for AI and API products. Real-time tracking of token consumption, API calls, and custom metrics. *** ## Business Scenarios The following are example scenarios. Adjust them to match your actual business. ### Scenario 1: AI API Service (Token-Based Billing) **Setup:** 1. Create tiered subscription products (Starter / Pro / Scale) 2. Each tier includes a token quota 3. Track token consumption using LiteLLM or your own system 4. Prompt users to upgrade when approaching their quota **Dashboard workflow:** * Monitor active subscriptions in the **Subscriptions** page * Track revenue per tier in **Analytics** * View customer details to understand usage patterns ### Scenario 2: AI SaaS (Subscription + Token Allowance) **Setup:** 1. Create subscription products with token allowances 2. Store allowance info in product metadata 3. When users exceed their allowance, create overage charges via `priceSnapshot` 4. Use webhooks to automate renewal and quota resets **Dashboard workflow:** * Monitor subscriptions and one-time orders * Track subscription revenue vs overage revenue in **Analytics** ### Scenario 3: AI Agent Platform (Per-Task/Per-Call Billing) **Setup:** 1. Create a base subscription product with a set number of agent calls 2. Log each agent execution upon completion 3. For usage beyond the included calls, create one-time orders with dynamic pricing 4. Use OpenMeter to track call counts and costs **Dashboard workflow:** * View per-customer revenue in **Payments** * Track agent call growth trends *** ## Key Webhook Events | Event | Action | | ------------------------ | --------------------------------------------------- | | `subscription.activated` | Set initial token/request quota | | `subscription.updated` | Adjust quota to match new plan | | `subscription.canceled` | Revoke API access or downgrade to free tier | | `subscription.past_due` | Reduce quota or throttle API calls | | `order.completed` | Grant additional token allowance (overage purchase) | For API details, see the [API Reference](/api-reference/introduction). *** ## Testing Set up your tiered subscription products in test mode. Use `4242 4242 4242 4242` to subscribe to each tier. Test your usage tracking and quota enforcement logic. Verify the dynamic pricing and overage billing flow. *** ## Launch Checklist * [ ] Subscription products created for each tier * [ ] Pricing and quotas clearly documented * [ ] Usage tracking/metering tool integrated * [ ] Quota enforcement working correctly * [ ] Upgrade/downgrade flows tested * [ ] Overage billing flow verified * [ ] Products published to production *** ## Next Steps Learn more about subscription management Automate quota management with webhooks # Set Up Webhooks Source: https://waffo.mintlify.app/guides/webhooks Get notified when payments succeed, subscriptions renew, or refunds are processed ## 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: Configure Webhook URL in Dashboard In your Dashboard, navigate to **Settings → Webhooks**. Webhook settings page 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. Click **Save** to activate webhook notifications. *** ## Step 2: Understand Event Types Waffo Pancake sends these webhook events: ### Payment Events | Event | When It Fires | Common Action | | ------------------- | ------------------------------ | ----------------------------- | | `payment.succeeded` | Payment completed successfully | Deliver product, grant access | | `payment.failed` | Payment attempt failed | Notify customer, retry | | `payment.refunded` | Refund processed | Revoke access, update records | ### Subscription Events | Event | When It Fires | Common Action | | ----------------------- | ------------------------ | -------------------------- | | `subscription.created` | New subscription started | Create account, set limits | | `subscription.updated` | Plan changed or renewed | Update access level | | `subscription.canceled` | Subscription fully ended | Revoke access | | `subscription.expired` | Subscription expired | Clean up resources | *** ## 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: | Attempt | Delay | | --------- | ---------- | | 1st retry | 5 minutes | | 2nd retry | 30 minutes | | 3rd retry | 2 hours | | 4th retry | 8 hours | | 5th retry | 24 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](/api-reference/webhooks). *** ## Testing Webhooks In Dashboard → Settings → Webhooks, enter your test server URL. Use test mode to create a purchase. This triggers webhook events to your test URL. Check your server logs to confirm the webhook was received and processed correctly. For local development, use tools like [ngrok](https://ngrok.com) to expose your local server to the internet so Waffo Pancake can reach it. *** ## 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 Handle refund requests and track refund status Detailed webhook payload format and code examples # Introduction Source: https://waffo.mintlify.app/index Accept payments globally — we handle taxes, compliance, and payouts so you don't have to. ## Turn Your Software into a Business You built something people want. Now you need to get paid — globally, compliantly, without the headache. **Waffo Pancake handles everything between your product and your bank account:** payments, taxes, compliance, and payouts worldwide. Accept Visa and Mastercard. Plus Apple Pay & Google Pay for faster checkout. Get paid directly to your bank account. We're your Merchant of Record. **Early Adopter Offer:** Process your first \$2,000 for free. Lock in the lowest MoR rates. *** ## What's Blocking Your Revenue? You want to ship, not fight compliance. Here's what we solve for you: Traditional MoR services require you to register a legal entity first — that takes weeks and thousands of dollars. **Waffo Pancake's Solution:** We act as your Merchant of Record. You get paid directly to your bank account without needing an LLC. Subscription management, tax calculation, dunning emails, failed payment retries... that's months of engineering work. **Waffo Pancake's Solution:** Complete infrastructure out of the box — subscriptions, one-time payments, all handled. The US has 10,000+ tax jurisdictions, the EU has 27 countries each with VAT rules, plus constantly changing regulations... **Waffo Pancake's Solution:** We're the legal seller. Tax calculation, collection, and reporting are handled automatically. Complex checkout forms, no Apple Pay/Google Pay, no multi-language support — every step loses customers. **Waffo Pancake's Solution:** Optimized two-step checkout flow, Apple Pay & Google Pay support, built-in 7 languages. *** ## How Waffo Pancake Helps You Taxes, compliance, risk — all handled by us. You focus on your product. Visa, Mastercard, plus Apple Pay and Google Pay. One-time or subscription — your business model, your choice. Weekly, monthly, quarterly, or annual billing. Two-step checkout flow, 7 languages supported, mobile-first design. Revenue, customers, subscription metrics — no SQL needed, everything at a glance. Refunds, customer portal, subscription management — all in one dashboard. *** ## Who Is This For? No company? No problem. Get paid directly to your bank account. We handle all compliance. Subscriptions, trials, seat-based billing, usage metering — complete solution designed for SaaS. AI-friendly integration via SDK, MCP Skill, and CLI — ship payments with natural language prompts. *** ## Start Getting Paid in 5 Minutes Sign up at [dashboard.waffo.ai](https://dashboard.waffo.ai). No credit card required. Create a product and set pricing. Done in 2 minutes. Get your checkout link and share it with customers. Funds go directly to your bank account. Set up your first payment in 5 minutes. Safely test the complete flow before going live. *** ## Built for Developers Install the official TypeScript SDK and start accepting payments in a few lines: ```bash theme={"dark"} npm install @waffo/pancake-ts ``` ```typescript theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); // Create a checkout session — redirect buyer to checkoutUrl const session = await client.checkout.createSession({ storeId: "store_xxx", productId: "prod_xxx", productType: "onetime", currency: "USD", }); // => session.checkoutUrl ``` Or call the REST API directly: ```bash theme={"dark"} curl -X POST https://waffo-pancake-auth-service.vercel.app/v1/actions/checkout/create-session \ -H "Content-Type: application/json" \ -H "X-Store-Slug: your-store-slug" \ -H "X-Environment: test" \ -d '{ "productId": "your-product-uuid", "productType": "onetime", "currency": "USD" }' ``` Official SDK with built-in signing and webhook verification. REST + GraphQL API with full endpoint documentation. Real-time event notifications. Seamless backend integration. *** ## Start Your Global Revenue Journey Don't let complex compliance slow down your product momentum. First \$2,000 fee-free. Lock in early adopter pricing. # Waffo Pancake Skill Source: https://waffo.mintlify.app/integrate/sdk-skill Complete reference for the @waffo/pancake-ts SDK — covers store setup, products, checkout, webhooks, subscriptions, and GraphQL queries Open the raw Skill file and copy the full content to your clipboard. Download the Skill file to add to your AI coding agent or IDE. *** The `@waffo/pancake-ts` SDK is a server-side TypeScript client for the Waffo Pancake payment API. It handles request signing, checkout session creation, webhook verification, and GraphQL queries. ## Gotchas — Read This First These are the mistakes that break integrations. Read before writing any code. | Gotcha | Why It Breaks | Fix | | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | | Reading webhook body as JSON | `request.json()` re-serializes the body, changing whitespace. Signature verification compares against the **original raw bytes**. | Always use `request.text()` (App Router / Hono) or `express.raw()` (Express). | | Using localtunnel for webhooks | localtunnel strips custom HTTP headers. `X-Waffo-Signature` never reaches your handler. | Use `cloudflared tunnel --url http://localhost:3000` instead. | | Forgetting `.publish()` | Products are created in `test` environment by default. Production checkout sessions for unpublished products will fail silently. | Call `client.onetimeProducts.publish({ id })` or `client.subscriptionProducts.publish({ id })` before going live. | | Accessing `result` instead of `result.data` in GraphQL | The GraphQL client returns `{ data: T \| null, errors?: [...] }`. Fields are nested under `.data`. | Always destructure: `const stores = result.data?.stores ?? []`. | | Passing dollar amounts instead of cents | All amounts use **smallest currency unit**. `$29.00` = `2900`, `¥1000` = `1000` (JPY has no decimal). | Double-check: if creating a \$9.99 product, pass `999` not `9.99`. | | Using `$id: ID!` in GraphQL variables | Backend uses `$id: String!`, not `$id: ID!`. Using the wrong type silently returns `null`. | Always declare ID variables as `String!`. | | `productIds` in group update is full replacement | Calling `subscriptionProductGroups.update({ productIds: [...] })` replaces the entire list — it does not append. | Always pass the complete desired list, not just new additions. | *** ## Use Cases Waffo Pancake is a merchant-of-record payment platform. The SDK fits projects that need: * **SaaS subscription billing** — monthly/yearly plans with upgrade/downgrade (e.g., Free/Pro/Team tiers) * **Digital product sales** — one-time purchases for e-books, templates, courses, licenses * **Per-usage payments** — charge per download, API call, or generated report * **Hybrid models** — subscriptions + one-time purchases combined * **Multi-currency pricing** — per-currency prices with automatic tax handling | Project Type | Payment Model | Products to Create | | ----------------------------- | ------------------------------- | -------------------------------------------------------------------------- | | AI Skills marketplace | Per-download + Pro subscription | 1 one-time (\$0.99/download) + 2 subscriptions (monthly/yearly) | | Online course platform | One-time per course | 1 one-time per course ($29–$199) | | SaaS (Starter/Pro/Enterprise) | Subscription tiers | 3 subscriptions + 1 product group for plan switching | | Template shop | One-time per template | 1 one-time per template, or 1 shared product with `priceSnapshot` override | | API credits | Credit packs + subscription | 1 one-time per pack + subscription for monthly quota | *** ## Installation & Setup ```bash theme={"dark"} npm install @waffo/pancake-ts ``` Server-side only. Node.js 18+. Zero dependencies. ```typescript theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); ``` Two env vars are required — provided at signup: ``` WAFFO_MERCHANT_ID= WAFFO_PRIVATE_KEY= ``` ### PEM Key Handling **Escaped newlines** (simplest): ``` WAFFO_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEv...\n-----END PRIVATE KEY-----" ``` **Base64** (recommended for CI/CD): ```bash theme={"dark"} cat private.pem | base64 | tr -d '\n' ``` ```typescript theme={"dark"} const privateKey = Buffer.from(process.env.WAFFO_PRIVATE_KEY_BASE64!, "base64").toString("utf-8"); ``` **File path** (local dev): ```typescript theme={"dark"} import { readFileSync } from "fs"; const privateKey = readFileSync("./keys/private.pem", "utf-8"); ``` *** ## Quick Start: Create from Scratch ```typescript theme={"dark"} // 1. Create a store const { store } = await client.stores.create({ name: "My SaaS" }); // 2. Create products const { product: monthly } = await client.subscriptionProducts.create({ storeId: store.id, name: "Pro Monthly", billingPeriod: "monthly", prices: { USD: { amount: 999, taxIncluded: true, taxCategory: "saas" } }, }); const { product: yearly } = await client.subscriptionProducts.create({ storeId: store.id, name: "Pro Yearly", billingPeriod: "yearly", prices: { USD: { amount: 9900, taxIncluded: true, taxCategory: "saas" } }, }); // 3. Create a checkout session const session = await client.checkout.createSession({ storeId: store.id, productId: monthly.id, productType: "subscription", currency: "USD", }); // Redirect customer to session.checkoutUrl ``` Save the Store ID and Product IDs to env vars for future use. ## Quick Start: Use Existing Products If products already exist in the Dashboard, copy their IDs and go straight to checkout: ```typescript theme={"dark"} const session = await client.checkout.createSession({ productId: process.env.WAFFO_PRO_MONTHLY_PRODUCT_ID!, productType: "subscription", currency: "USD", buyerEmail: "customer@example.com", successUrl: "https://myapp.com/welcome", }); // Redirect customer to session.checkoutUrl ``` *** ## API Reference ### Stores ```typescript theme={"dark"} // Create const { store } = await client.stores.create({ name: "My Store" }); // Update (partial — only provided fields change) const { store } = await client.stores.update({ id: "store_id", name: "New Name", supportEmail: "help@example.com", website: "https://example.com", }); // Soft-delete const { store } = await client.stores.delete({ id: "store_id" }); ``` ### One-Time Products ```typescript theme={"dark"} const { product } = await client.onetimeProducts.create({ storeId: "store_id", name: "E-Book", description: "A great e-book", prices: { USD: { amount: 2900, taxIncluded: false, taxCategory: "digital_goods" }, EUR: { amount: 2700, taxIncluded: true, taxCategory: "digital_goods" }, }, successUrl: "https://example.com/thanks", metadata: { sku: "EB-001" }, }); // Update (creates new immutable version) const { product } = await client.onetimeProducts.update({ id: "product_id", name: "E-Book v2", prices: { USD: { amount: 3900, taxIncluded: false, taxCategory: "digital_goods" } }, }); // Publish test → production (required before going live) const { product } = await client.onetimeProducts.publish({ id: "product_id" }); // Activate / deactivate const { product } = await client.onetimeProducts.updateStatus({ id: "product_id", status: "inactive", // or "active" }); ``` **taxCategory options:** `digital_goods` | `saas` | `software` | `ebook` | `online_course` | `consulting` | `professional_service` ### Subscription Products ```typescript theme={"dark"} const { product } = await client.subscriptionProducts.create({ storeId: "store_id", name: "Pro Monthly", billingPeriod: "monthly", // "weekly" | "monthly" | "quarterly" | "yearly" prices: { USD: { amount: 999, taxIncluded: true, taxCategory: "saas" } }, }); // update, publish, updateStatus — same pattern as one-time products ``` ### Subscription Product Groups Groups enable shared trials and plan switching between subscription products. ```typescript theme={"dark"} const { group } = await client.subscriptionProductGroups.create({ storeId: "store_id", name: "Pro Plans", rules: { sharedTrial: true }, productIds: ["monthly_product_id", "yearly_product_id"], }); // Update (productIds is FULL REPLACEMENT, not append) await client.subscriptionProductGroups.update({ id: "group_id", productIds: ["monthly_id", "quarterly_id", "yearly_id"], }); // Publish to production await client.subscriptionProductGroups.publish({ id: "group_id" }); // Delete (physical delete, not soft-delete) await client.subscriptionProductGroups.delete({ id: "group_id" }); ``` ### Checkout Sessions ```typescript theme={"dark"} const session = await client.checkout.createSession({ storeId: "store_id", // optional if productId is from an existing store productId: "product_id", productType: "onetime", // "onetime" | "subscription" currency: "USD", buyerEmail: "buyer@example.com", // optional, pre-fills email successUrl: "https://example.com/thanks", // redirect after payment metadata: { orderId: "internal-123" }, // custom key-value pairs // Optional overrides: priceSnapshot: { amount: 1999, taxIncluded: true, taxCategory: "saas" }, billingDetail: { country: "US", isBusiness: false }, expiresInSeconds: 3600, // default: 7 days }); // session.checkoutUrl — redirect customer here // session.sessionId — for tracking // session.expiresAt — ISO 8601 expiry ``` ### Cancel Subscription ```typescript theme={"dark"} const { orderId, status } = await client.orders.cancelSubscription({ orderId: "order_id", }); // status: "canceled" (was pending) or "canceling" (active → ends at period end) ``` ### GraphQL Queries Read-only. Use `String!` for ID variables (not `ID!`). ```typescript theme={"dark"} const result = await client.graphql.query<{ stores: Array<{ id: string; name: string; status: string }>; }>({ query: `query { stores { id name status } }`, }); const stores = result.data?.stores ?? []; // With variables — note String!, not ID! const result = await client.graphql.query<{ onetimeProduct: { id: string; name: string; prices: unknown }; }>({ query: `query ($id: String!) { onetimeProduct(id: $id) { id name prices } }`, variables: { id: "product_id" }, }); const product = result.data?.onetimeProduct; ``` *** ## Webhook Verification The SDK embeds public keys for both environments. Verification is one function call. ### Next.js App Router ```typescript theme={"dark"} import { verifyWebhook } from "@waffo/pancake-ts"; export async function POST(request: Request) { const body = await request.text(); // MUST be raw text, not .json() const sig = request.headers.get("x-waffo-signature"); try { const event = verifyWebhook(body, sig); // event.eventType, event.data, event.storeId, event.mode return new Response("OK"); } catch { return new Response("Invalid signature", { status: 401 }); } } ``` ### Express ```typescript theme={"dark"} import express from "express"; import { verifyWebhook } from "@waffo/pancake-ts"; // MUST use express.raw(), not express.json() app.post("/webhooks", express.raw({ type: "application/json" }), (req, res) => { try { const event = verifyWebhook( req.body.toString("utf-8"), req.headers["x-waffo-signature"] as string, ); res.status(200).send("OK"); } catch { res.status(401).send("Invalid signature"); } }); ``` ### Hono ```typescript theme={"dark"} import { verifyWebhook } from "@waffo/pancake-ts"; app.post("/webhooks", async (c) => { const body = await c.req.text(); // raw text const sig = c.req.header("x-waffo-signature"); try { const event = verifyWebhook(body, sig); return c.text("OK"); } catch { return c.text("Invalid signature", 401); } }); ``` ### Verification Options ```typescript theme={"dark"} // Explicit environment (skip auto-detection) const event = verifyWebhook(body, sig, { environment: "prod" }); // Custom replay tolerance (default: 5 minutes) const event = verifyWebhook(body, sig, { toleranceMs: 600000 }); // Disable replay protection (not recommended in production) const event = verifyWebhook(body, sig, { toleranceMs: 0 }); ``` ### Event Types | Event | Trigger | | -------------------------------- | ------------------------------------------ | | `order.completed` | One-time payment succeeded | | `subscription.activated` | First subscription payment succeeded | | `subscription.payment_succeeded` | Renewal payment succeeded | | `subscription.canceling` | Cancel initiated (active until period end) | | `subscription.uncanceled` | Cancellation withdrawn | | `subscription.updated` | Plan changed (upgrade/downgrade) | | `subscription.canceled` | Subscription fully terminated | | `subscription.past_due` | Renewal payment failed | | `refund.succeeded` | Refund completed | | `refund.failed` | Refund failed | ### Event Shape ```typescript theme={"dark"} interface WebhookEvent { id: string; // Delivery ID (use for idempotent dedup) timestamp: string; // ISO 8601 UTC eventType: string; // e.g. "order.completed" eventId: string; // Business event ID (payment/order ID) storeId: string; mode: "test" | "prod"; data: { orderId: string; buyerEmail: string; currency: string; amount: number; // smallest currency unit taxAmount: number; productName: string; }; } ``` ### Configuring Webhook URLs ```typescript theme={"dark"} await client.stores.update({ id: "store_id", webhookSettings: { testWebhookUrl: "https://your-domain.com/api/webhooks", prodWebhookUrl: "https://your-domain.com/api/webhooks", testEvents: [ "order.completed", "subscription.activated", "subscription.canceled", "subscription.past_due", ], prodEvents: [ "order.completed", "subscription.activated", "subscription.canceled", "subscription.past_due", ], }, }); ``` *** ## Error Handling ```typescript theme={"dark"} import { WaffoPancakeError } from "@waffo/pancake-ts"; try { await client.stores.create({ name: "My Store" }); } catch (err) { if (err instanceof WaffoPancakeError) { console.log(err.status); // HTTP status code console.log(err.errors); // Array of { message, layer } console.log(err.errors[0].layer); // "store" | "product" | "order" | ... } } ``` Errors are ordered by call stack depth: `errors[0]` is the root cause (deepest layer), `errors[n]` is the outermost caller. *** ## Development Tips 1. **Webhook tunneling** — use `cloudflared`, not localtunnel (see Gotchas). ```bash theme={"dark"} brew install cloudflare/cloudflare/cloudflared cloudflared tunnel --url http://localhost:3000 ``` 2. **Idempotency is automatic** — the SDK generates deterministic keys from `merchantId + path + body`. Retries are safe. 3. **Test → Prod workflow** — products default to test. Use `.publish()` to promote. Webhook events include `mode: "test" | "prod"` so your handler can distinguish. *** ## Quick Start Checklist 1. `npm install @waffo/pancake-ts` 2. Set `WAFFO_MERCHANT_ID` and `WAFFO_PRIVATE_KEY` env vars 3. Initialize `new WaffoPancake({ merchantId, privateKey })` 4. Create or reference a store 5. Create or reference product(s) 6. Create checkout: `client.checkout.createSession(...)` → redirect to `checkoutUrl` 7. Handle webhooks: `verifyWebhook(rawBody, sig)` — **must use `request.text()`** 8. Configure webhook URL: `client.stores.update({ webhookSettings: ... })` # SDKs Source: https://waffo.mintlify.app/integrate/sdks Client libraries and framework integrations ## SDKs & Libraries Waffo Pancake provides an official TypeScript SDK and direct API access. *** ## TypeScript SDK Official TypeScript SDK on npm ### Installation ```bash theme={"dark"} npm install @waffo/pancake-ts ``` ### Features * Zero runtime dependencies, ESM + CJS, Node >= 20 * Automatic request signing with deterministic idempotency keys * Full TypeScript type definitions (15 enums, 40+ interfaces) * Webhook verification with embedded public keys (test/prod) ### Quick Start ```typescript theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); // Create a store const { store } = await client.stores.create({ name: "My Store" }); // Create a one-time product const { product } = await client.onetimeProducts.create({ storeId: store.id, name: "E-Book: TypeScript Handbook", prices: { USD: { amount: 2900, taxIncluded: false, taxCategory: "digital_goods" }, }, }); // Create a checkout session const session = await client.checkout.createSession({ storeId: store.id, productId: product.id, productType: "onetime", currency: "USD", }); // => redirect buyer to session.checkoutUrl ``` ### Configuration | Parameter | Type | Required | Description | | ------------ | -------------- | -------- | ------------------------------------------------------- | | `merchantId` | `string` | Yes | Your Merchant ID | | `privateKey` | `string` | Yes | RSA private key (PEM, base64, or raw — auto-normalized) | | `baseUrl` | `string` | No | API base URL (default: production) | | `fetch` | `typeof fetch` | No | Custom fetch implementation | ### Available Resources | Namespace | Methods | Description | | ---------------------------------- | -------------------------------------------------- | ------------------------------- | | `client.stores` | `create()` `update()` `delete()` | Store management | | `client.onetimeProducts` | `create()` `update()` `publish()` `updateStatus()` | One-time product CRUD | | `client.subscriptionProducts` | `create()` `update()` `publish()` `updateStatus()` | Subscription product CRUD | | `client.subscriptionProductGroups` | `create()` `update()` `delete()` `publish()` | Product groups for shared trial | | `client.orders` | `cancelSubscription()` | Order management | | `client.checkout` | `createSession()` | Create checkout sessions | | `client.graphql` | `query()` | Typed GraphQL queries | ### Checkout Integration ```typescript theme={"dark"} import { WaffoPancake, CheckoutSessionProductType } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); // Create checkout session const session = await client.checkout.createSession({ storeId: "store_xxx", productId: "prod_xxx", productType: CheckoutSessionProductType.Onetime, currency: "USD", buyerEmail: "customer@example.com", successUrl: "https://example.com/thank-you", }); // Step 3: Open checkout in new tab (recommended) // Frontend: window.open(session.checkoutUrl, "_blank", "noopener,noreferrer"); ``` ### Webhook Verification ```typescript theme={"dark"} import { verifyWebhook, WebhookEventType } from "@waffo/pancake-ts"; // Express (use raw body — parsed JSON breaks signature verification) app.post("/webhooks", express.raw({ type: "application/json" }), (req, res) => { try { const event = verifyWebhook( req.body.toString("utf-8"), req.headers["x-waffo-signature"] as string, ); res.status(200).send("OK"); switch (event.eventType) { case WebhookEventType.OrderCompleted: // handle order completion break; case WebhookEventType.SubscriptionActivated: // handle subscription activation break; } } catch { res.status(401).send("Invalid signature"); } }); // Next.js App Router export async function POST(request: Request) { const body = await request.text(); const sig = request.headers.get("x-waffo-signature"); try { const event = verifyWebhook(body, sig); // handle event ... return new Response("OK"); } catch { return new Response("Invalid signature", { status: 401 }); } } ``` ### Error Handling ```typescript theme={"dark"} import { WaffoPancakeError } from "@waffo/pancake-ts"; try { await client.stores.create({ name: "" }); } catch (err) { if (err instanceof WaffoPancakeError) { console.log(err.status); // 400 console.log(err.errors); // [{ message: "...", layer: "store" }, ...] } } ``` *** ## Direct API Access You can also use the REST and GraphQL API directly. API Key authentication is handled automatically by the SDK -- no manual header setup is needed. ```typescript theme={"dark"} // Create a product const { product } = await client.onetimeProducts.create({ storeId: "your-store-uuid", name: "My Product", prices: { USD: { amount: 2900, taxIncluded: false, taxCategory: "saas" }, }, }); // Query data via GraphQL const data = await client.graphql.query<{ stores: Array<{ id: string; name: string; status: string }> }>( `{ stores { id name status } }` ); ``` *** ## SDK Roadmap | Language | Status | | ------------------------ | ---------------------------------------------------------------------------------- | | **Node.js / TypeScript** | Available — [`@waffo/pancake-ts`](https://www.npmjs.com/package/@waffo/pancake-ts) | | **Python** | Planned | | **Go** | Planned | | **PHP** | Planned | *** ## Framework Guides Build with Next.js and Server Actions. Create checkout flows programmatically. Implement recurring billing. Receive real-time event notifications. *** ## API Reference For complete endpoint documentation: Full REST and GraphQL API documentation. # Account Reviews Source: https://waffo.mintlify.app/mor/account-reviews Business verification and payout setup for Waffo Pancake merchants ## Why Verification Is Required As a Merchant of Record, Waffo Pancake processes payments and handles tax obligations on your behalf. To comply with financial regulations and ensure accurate invoicing, we collect basic business information from every merchant before enabling payouts. This protects both you and your customers by ensuring: * **Tax compliance** -- Correct tax reporting and remittance for your transactions * **Accurate invoices** -- Customer invoices display your verified business details * **Payout eligibility** -- Funds can only be disbursed to verified accounts *** ## Payout Setup Flow Before you can receive payouts, you need to complete a 3-step setup process. You can find this in your store's **Finance** page under the **Payout Setup** tab. Fill out your business information in **Settings > Business Details**. This includes your business name, type, address, contact information, and tax ID. Once submitted, your details are reviewed. Verify your contact email address via a 6-digit code. This step also covers identity verification (KYC) requirements. Connect a payout account to receive funds. Available options include Alipay and bank transfer. Each step must be completed in order. You can track your progress via the step indicator on the Payout Setup tab. *** ## Business Details The business details form collects the following information: | Field | Description | | ----------------- | -------------------------------------------------------------------------- | | **Business Name** | Your official registered business name | | **Business Type** | The legal structure of your business (e.g., sole proprietor, company, LLC) | | **Contact Email** | A business email for payout-related communications | | **Contact Phone** | A phone number for account contact | | **Address** | Your business street address | | **City** | City of your business address | | **Country** | Country where your business is registered | | **Postal Code** | Postal or ZIP code | | **Tax ID** | Your tax identification number (e.g., EIN, VAT number) | Your business details appear on customer invoices and are used for tax calculations. Use your official registered information. After submitting your business details, they will be reviewed. You can check the review status from the Payout Setup tab -- it will show as either pending review or approved. *** ## Payout Methods Once your business details are approved and your email is verified, you can connect a payout method. Receive payouts directly to your Alipay account. Direct deposit to your bank account. You can change your payout method at any time from the Payout Setup tab after setup is complete. *** ## Frequently Asked Questions Review typically takes 1-3 business days after submission. You will see the status update on your Payout Setup tab. Yes. Navigate to **Settings > Business Details** to view or update your information. Note that changes may require re-review. You can still create products and accept payments, but payouts will not be disbursed until all three setup steps are complete. # Fees Source: https://waffo.mintlify.app/mor/fees 4.5% + $0.5 (limited offer). No hidden costs. Ever. ## Simple Pricing **Limited offer** — No monthly fees. No setup costs. No hidden charges. **Standard rate** — No monthly fees. No setup costs. No hidden charges. *** ## What's Included Everything: | Feature | Included | | ---------------------------- | -------- | | Payment processing | Yes | | Global tax compliance | Yes | | Tax calculation & collection | Yes | | Tax remittance | Yes | | All major card networks | Yes | | Dashboard | Yes | | Customer Portal | Yes | | Webhooks & API | Yes | | Multi-currency | Yes | | Fraud protection | Yes | | Chargeback handling | Yes | *** ## Fee Calculation | Component | Limited Offer | Standard | | ---------- | ------------- | -------- | | Percentage | 4.5% | 5% | | Fixed | \$0.50 | \$0.50 | **Example (limited offer rate):** ``` Sale: $100 Fee: $100 × 4.5% + $0.50 = $5.00 You receive: $95.00 ``` **Example (standard rate):** ``` Sale: $100 Fee: $100 × 5% + $0.50 = $5.50 You receive: $94.50 ``` *** ## No Hidden Fees | Fee Type | Cost | | ---------------------- | -------- | | Monthly fee | \$0 | | Setup fee | \$0 | | API access | \$0 | | Webhooks | \$0 | | Currency conversion | Included | | Failed payment retries | \$0 | | Customer portal | \$0 | | Support | \$0 | *** ## vs Alternatives ### vs Other MoRs | Provider | Transaction Fee | Monthly | | ----------------- | ----------------------------- | ------- | | **Waffo Pancake** | 4.5% + \$0.50 (limited offer) | \$0 | | Paddle | 5% + \$0.50 | \$0 | | Gumroad | 10% | \$0 | | FastSpring | 5.9% + \$0.95 | \$0 | | Lemon Squeezy | 5% + \$0.50 | \$0 | ### vs DIY | Approach | Transaction | Tax Compliance | | --------------------- | -------------------- | ----------------- | | **Waffo Pancake** | 4.5% (limited offer) | Included | | Stripe + Accountant | 2.9% | \$2,000-10,000/mo | | Stripe + Tax Software | 2.9% | \$200-500/mo | DIY doesn't include your time managing compliance. That's 10-20+ hours/month. *** ## How It Works ``` Customer pays $100 ↓ Fee deducted: $5.00 (4.5% + $0.50, limited offer) ↓ Your balance: $95.00 ↓ Payout to your account ``` Fees deducted automatically. No invoices to pay. *** ## Refunds | Scenario | Fee | | -------------- | ----------------------------- | | Full refund | Fee not returned | | Partial refund | Proportional fee not returned | We've already incurred costs processing the original payment. *** ## Chargebacks | Event | Cost | | ------------------- | ------------------ | | Chargeback received | \$15 dispute fee | | Chargeback won | \$15 refunded | | Chargeback lost | Transaction + \$15 | *** ## Currency Conversion | Conversion | Rate | | ---------- | ---------------- | | Standard | Market rate | | Fee | Included in 4.5% | No additional conversion fees. *** ## Volume Discounts | Monthly Volume | | | -------------- | ------------------ | | \$10,000+ | Contact sales | | \$50,000+ | Custom rates | | \$100,000+ | Enterprise pricing | Processing \$10,000+/month? Let's talk. *** ## Early Adopter Offer Process your first $2,000 with zero fees. Lock in the limited offer rate of 4.5% + $0.50. *** ## FAQ No. Pay only when you make sales. No. Only charge on success. Retries are free. Same fees. No extra subscription management charges. Yes. The 4.5% (limited offer) covers it. No. All payment methods: same 4.5% + \$0.50 fee (limited offer). # Prohibited & Restricted Products Source: https://waffo.mintlify.app/mor/prohibited-products Categories that require additional review or are not permitted on Waffo Pancake. As a Merchant of Record, Waffo Pancake is responsible for every transaction processed through our platform. To maintain compliance with payment networks, financial regulations, and applicable laws, certain product and service categories are either restricted (accepted only under specific conditions) or prohibited entirely. Selling prohibited products will result in immediate account suspension and potential fund withholding. If you are unsure whether your product qualifies, contact support before listing. *** ## Restricted Categories These categories are accepted on Waffo Pancake, but require additional review and must meet specific conditions before you can begin selling. Contact our team to discuss your use case. | Category | Conditions & Notes | | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | **Skill Games** | Must be skill-based with no element of chance; prizes must be disclosed clearly; age verification required where applicable | | **Streaming Services** | Content must not include unauthorized copyrighted material; must comply with digital rights management obligations | | **AIGC (AI-Generated Content)** | Content must not infringe third-party IP; must include clear disclosure that content is AI-generated | | **Online Educational Platforms** | Credentials and qualifications claimed must be accurate; refund policies must be clearly stated | | **Luxury Items** | Authenticity must be verifiable; products must be accompanied by proper provenance documentation | | **Food Products** | Must comply with applicable food safety regulations in all markets sold; proper labeling required | | **Alcohol** | Must meet local licensing and age verification requirements in each jurisdiction; delivery restrictions apply | | **In-Game Virtual Items** | Must not facilitate unauthorized secondary markets; must comply with game publisher terms | | **VPN / VPS Services** | Must not be marketed for bypassing legal restrictions; acceptable use policies must be published | | **IPTV** | Only licensed content distribution is permitted; unauthorized rebroadcasting of copyrighted channels is prohibited | | **Subscription Services** | Cancellation terms must be clearly disclosed; auto-renewal must have explicit customer consent | | **Corrective Contact Lenses** | Valid prescription requirement must be enforced; must comply with medical device regulations in each market | | **Computer Software Stores** | All software sold must be properly licensed; no cracked, pirated, or key-reselling operations | | **Tele-Medicine** | Practitioners must be licensed in the jurisdictions they serve; cannot replace emergency medical services | | **Digital Games (Vietnam)** | Must hold valid licensing approval from Vietnamese authorities; subject to additional review for Vietnam sales | Approval for a restricted category does not guarantee ongoing eligibility. Waffo Pancake reserves the right to reassess accounts if business practices change or regulatory requirements are updated. *** ## Prohibited Categories The following categories are not permitted on Waffo Pancake under any circumstances. Products or services that are illegal, facilitate illegal activity, or promote harm: * Controlled substances, narcotics, and drug paraphernalia * Counterfeit identity documents, fake IDs, or fraudulent credentials * Telecommunications manipulation equipment (e.g., SIM cloners, call spoofing services) * Content that promotes, glorifies, or incites violence or hatred * Human trafficking or any services facilitating the exploitation of persons * Tobacco products and electronic cigarettes * Prescription drugs sold without a valid prescription process * Charities, political organizations, and religious organizations (payment collection via MoR is not appropriate for these entities) * Debt collection services Products or services that violate intellectual property rights: * Unauthorized distribution of copyrighted media (films, music, books, software) * Counterfeit goods — replicas or imitations misrepresenting brand or origin * Illegal imports or exports of goods prohibited from cross-border trade Products or services designed to deceive buyers or exploit participants: * Pyramid schemes, multi-level marketing structured around recruitment fees * Get-rich-quick schemes, guaranteed investment returns, or unrealistic income claims * Predatory lending products with deceptive terms * Services that sell or artificially inflate social media engagement (fake likes, followers, views, or reviews) * Pornographic or sexually explicit content of any kind * Prostitution, escort services, or any form of commercial sexual services * Firearms, handguns, rifles, and related accessories * Ammunition and explosive materials * Toxic, hazardous, radioactive, or biological materials * Any items regulated under arms control or export control laws * Online casinos, poker, and all other forms of gambling * Sports betting, sports forecasting competitions with cash prizes * Lotteries and sweepstakes where purchase is required for entry * Unregulated or unlicensed cryptocurrency exchanges * Initial Coin Offerings (ICOs) that do not meet applicable securities regulations * NFT marketplaces or projects where the primary use is speculative trading The following behaviors violate our platform policies and will result in immediate termination: * Creating accounts under a false identity or impersonating another individual or business * Processing payments on behalf of an undisclosed third-party merchant * Structuring transactions to avoid chargebacks, fraud detection, or reporting thresholds * Distributing malware, ransomware, spyware, or any malicious software through the platform *** ## Questions & Compliance This list is not exhaustive. Waffo Pancake may restrict additional categories based on evolving regulations, payment network requirements, or risk assessments. For the complete and legally binding terms, refer to the [Waffo Terms of Service](https://waffo.com/terms). Unsure if your product qualifies? Reach out before listing. Learn about our merchant verification process. # Supported Countries Source: https://waffo.mintlify.app/mor/supported-countries 173 countries. 135 currencies. 430+ payment methods. ## Sell Globally. Automatically. 173 countries. 135 currencies. 430+ payment methods. *** ## Customer Countries ### Americas | Country | Tax | Payment Methods | | ------------- | --------- | ---------------------------- | | United States | Sales Tax | Cards, Apple Pay, Google Pay | | Canada | GST/HST | Cards, Apple Pay, Google Pay | | Mexico | IVA | Cards, OXXO | | Brazil | ICMS | Cards, PIX, Boleto | | Argentina | IVA | Cards, Local methods | ### Europe | Country | Tax | Payment Methods | | -------------- | ------- | ----------------------------- | | United Kingdom | VAT 20% | Cards, Apple Pay, Google Pay | | Germany | VAT 19% | Cards, SEPA, Giropay | | France | VAT 20% | Cards, SEPA, Cartes Bancaires | | Netherlands | VAT 21% | Cards, iDEAL, SEPA | | Poland | VAT 23% | Cards, BLIK, P24 | | Sweden | VAT 25% | Cards, Swish | | + All EU | VAT | Multiple local methods | ### Asia Pacific | Country | Tax | Payment Methods | | ----------- | ------- | ---------------------------- | | China | VAT | Alipay, WeChat Pay | | Japan | JCT | Cards, Konbini | | Australia | GST 10% | Cards, Apple Pay, Google Pay | | South Korea | VAT | Cards, KakaoPay | | Singapore | GST | Cards, PayNow | | India | GST | Cards, UPI | | Hong Kong | None | Cards, Alipay HK | ### Middle East & Africa | Country | Tax | Payment Methods | | ------------ | --- | --------------- | | UAE | VAT | Cards | | Saudi Arabia | VAT | Cards, MADA | | Israel | VAT | Cards | | South Africa | VAT | Cards, EFT | *** ## Payment Methods ### Global | Method | Coverage | | --------------- | ------------- | | Visa/Mastercard | Worldwide | | Apple Pay | 60+ countries | | Google Pay | 40+ countries | ### Regional | Method | Country | | ------ | ------- | | PIX | Brazil | | Boleto | Brazil | | OXXO | Mexico | | Method | Country | | ---------- | ----------- | | SEPA | EU/EEA | | iDEAL | Netherlands | | Bancontact | Belgium | | Giropay | Germany | | BLIK | Poland | | Swish | Sweden | | Method | Country | | ---------- | --------- | | Alipay | China | | WeChat Pay | China | | Konbini | Japan | | PayNow | Singapore | | UPI | India | *** ## Receive Payouts Fast transfers via Alipay * United States * United Kingdom * EU countries (SEPA) * Canada, Australia * Hong Kong, Singapore, Japan * * 100+ more countries ### Payout Currencies | Currency | Bank Transfer | | -------- | ------------- | | USD | Yes | | EUR | Yes | | JPY | Yes | | GBP | Yes | | HKD | Yes | *** ## Tax Compliance by Region ### United States * Sales tax in 45+ states * Nexus management * Automatic rate updates ### European Union * VAT registered * One-Stop Shop (OSS) * Digital services rules ### United Kingdom * UK VAT registered * Post-Brexit compliance ### Rest of World * Local compliance where required * Automatic threshold monitoring *** ## Unsupported Countries Due to international sanctions and compliance requirements, Waffo Pancake cannot process payments involving the following countries: | Code | Country | | ---- | -------------------------------- | | AFG | Afghanistan | | BDI | Burundi | | BLR | Belarus | | CAF | Central African Republic | | COD | Democratic Republic of the Congo | | CUB | Cuba | | GNB | Guinea-Bissau | | HTI | Haiti | | IRN | Iran | | IRQ | Iraq | | LBN | Lebanon | | LBY | Libya | | MLI | Mali | | MMR | Myanmar | | NIC | Nicaragua | | PRK | North Korea | | RUS | Russia | | SDN | Sudan | | SOM | Somalia | | SSD | South Sudan | | SYR | Syria | | UKR | Ukraine | | YEM | Yemen | | ZWE | Zimbabwe | Transactions involving these countries — whether the buyer or merchant is located there — will be blocked. This list is subject to change based on evolving sanctions and compliance requirements. *** ## Need a Country? Need somewhere we don't support yet? Let us know. # What is MoR? Source: https://waffo.mintlify.app/mor/what-is-mor We're the seller. You focus on building. ## Merchant of Record = We Handle Everything A **Merchant of Record (MoR)** is the legal entity that sells to your customers. When you use Waffo Pancake, we become your MoR. Legally, we sell to your customers. Revenue goes to you. Minus fees. *** ## How It Works ``` Customer pays → Waffo Pancake → We handle taxes → You receive payout ↓ We're the legal seller We issue invoices We remit taxes ``` *** ## Without MoR vs With MoR ### Without MoR (DIY) **You're responsible for:** * Registering for taxes in every country * Calculating correct tax rates * Filing tax returns everywhere * Staying compliant with changing regulations * Handling audits and disputes ### With MoR (Waffo Pancake) **We handle:** * Global tax registration * Tax calculation and collection * Tax remittance * Regulatory updates * Audits and disputes **You focus on:** Building your product. *** ## Global Tax Complexity | Country | Tax | Rate | Complexity | | --------- | --------- | ------ | ----------------------------- | | USA | Sales Tax | 0-10%+ | 10,000+ jurisdictions | | EU | VAT | 17-27% | 27 countries, different rules | | UK | VAT | 20% | Post-Brexit rules | | Canada | GST/HST | 5-15% | Federal + provincial | | Australia | GST | 10% | Digital services rules | Without an MoR, you'd need to register, track, file, and manage compliance in every jurisdiction you sell to. *** ## Real Cost Comparison | Approach | Monthly Cost | Time | | -------------------- | ---------------- | ---------------- | | DIY Global Tax | \$2,000-15,000+ | 20+ hours/month | | Hire Tax Consultants | \$2,000-10,000 | 5-10 hours/month | | **Waffo Pancake** | Included in fees | 0 hours | *** ## What We Handle Real-time calculation based on: * Customer location * Product type * Local tax rules * Exemptions and thresholds Correct tax at checkout: * Inclusive or exclusive pricing * Multi-currency * Real-time rate updates We pay to authorities: * On-time filing * Correct jurisdictions * Proper documentation * All major card networks + digital wallets * Chargebacks and disputes * Refunds * Currency conversion *** ## MoR vs Payment Processor | Feature | Payment Processor | MoR | | ------------------ | ----------------- | --- | | Processes payments | Yes | Yes | | Tax calculation | No | Yes | | Tax collection | No | Yes | | Tax remittance | No | Yes | | Legal seller | You | MoR | | Tax liability | You | MoR | Using just Stripe? You're still responsible for all tax obligations. With us, we handle everything. *** ## Benefits ### Solo Founders Traditional MoRs require a legal entity. We don't. Get paid directly to your personal bank account. ### Startups Don't spend engineering time on billing. Ship features instead. ### Growing Companies Expand to new markets instantly. We're already compliant in 173 countries. *** ## FAQ Customers see your brand on checkout. Invoices show us as legal seller (required for tax compliance), but feature your branding prominently. No. MoR model requires us to process payments. This is how we legally handle your tax obligations. 173 countries. See the full list. Full list of countries where you can sell. # Onboarding Source: https://waffo.mintlify.app/onboarding Complete guide to setting up your Waffo Pancake account ## Onboarding Flow The onboarding process guides you through setting up your merchant account in three simple steps. Create your account with Google, GitHub, or Magic Link Set up your first store with basic information Create your first product with pricing Get your checkout link ready to share Start managing your business Onboarding Flow ## Step 1: Create Your Account Access the sign-in page at: ``` https://dashboard.waffo.ai/merchant/auth/signin ``` ### Authentication Methods **Fastest option** - Sign in with your existing Google account in one click. **For developers** - Sign in with your GitHub account. **Passwordless** - Enter your email and receive a secure login link. ### Magic Link Process 1. Enter your email address on the sign-in page 2. Check your inbox for the login email 3. Click the magic link to authenticate 4. You'll be securely logged in Magic links expire after 15 minutes for security. If your link expires, simply request a new one. ### OAuth Callback After OAuth authentication: * You'll be redirected to `/merchant/auth/callback/{provider}` * Session is established automatically * New users proceed to onboarding ## Step 2: Create Your Store After authentication, you'll be prompted to create your first store. ### Store Information | Field | Required | Description | | ---------------- | -------- | -------------------------------------------- | | Store Name | Yes | Your business or brand name | | Store URL | Auto | Generated from store name (e.g., `my-store`) | | Default Currency | Yes | Primary currency for transactions | | Country | Yes | Your business location | ### Multi-Store Support Waffo Pancake supports multiple stores per account. You can: * Separate different product lines * Manage multiple brands * Keep test and production stores separate You can create additional stores later from the Dashboard settings. ## Step 3: Add Your First Product Create your first product to start accepting payments. Create Product Form ### Product Fields | Field | Required | Description | | ------------ | -------- | ------------------------------------------------ | | Product Name | Yes | Display name for your product | | Description | No | Detailed product description (supports Markdown) | | Image | No | Product image for checkout page | | Price | Yes | Product price amount | | Currency | Yes | USD, EUR, GBP, CNY, or HKD | | Pricing Type | Yes | One-time or Subscription | ### Pricing Types Single purchase products like: * Digital downloads * Lifetime licenses * Physical goods Customer is charged once at checkout. Recurring billing products like: * SaaS subscriptions * Membership plans * Service retainers **Billing Intervals:** * Weekly * Monthly * Quarterly * Yearly **Trial Period (Optional):** * Enable free trial * Set trial duration (default: 7 days) ### Tax Configuration | Setting | Options | Description | | ------------ | -------------------- | -------------------------------- | | Tax Category | SaaS, Digital Goods | Determines tax calculation rules | | Tax Behavior | Inclusive, Exclusive | Whether price includes tax | ## Success Page After creating your first product, you'll see a success page with: * **Checkout Link** - Your product's shareable checkout URL * **Copy Button** - Quick copy to clipboard * **Test Checkout** - Preview your checkout flow * **Next Steps** - Suggested actions to complete setup ## Welcome to Your Dashboard Dashboard Home Clicking "Go to Dashboard" takes you to `/merchant/dashboard/{storeId}/home` with: * **Quick Stats** - Revenue, customers, and subscription metrics * **Recent Activity** - Latest transactions and customer signups * **Getting Started Checklist** - Next steps to optimize your store * **Revenue Charts** - Visual performance overview Learn about all features and how to use them effectively. ## Troubleshooting * Check your spam/junk folder * Verify you entered the correct email * Try requesting a new link * Contact support if issues persist * Ensure pop-ups are allowed for dashboard.waffo.ai * Try a different browser * Clear browser cache and cookies * Check if the OAuth provider is experiencing issues * Store names must be unique * Try a different store name * Store slug is auto-generated from name * Check for special characters * Check the error message displayed * Try signing in again * Clear cookies for waffo.ai domains * Contact support with the error details *** ## URL Reference | Page | URL | | ------------------- | ----------------------------------------------- | | Sign In | `/merchant/auth/signin` | | Verify Request | `/merchant/auth/verify-request` | | Magic Link Callback | `/merchant/auth/magic-link/callback` | | OAuth Callback | `/merchant/auth/callback/{provider}` | | Onboarding | `/merchant/onboarding` | | Create Product | `/merchant/onboarding/{storeId}/create-product` | | Success | `/merchant/onboarding/{storeId}/success` | | Dashboard | `/merchant/dashboard/{storeId}/home` | # Quickstart Source: https://waffo.mintlify.app/quickstart Ship your first payment in 5 minutes Pick your AI tool, paste the command, and Waffo Pancake SDK integration starts automatically. Run in your terminal: ```bash theme={"dark"} claude "Integrate Waffo Pancake payments into my web application. Use the Waffo Pancake Skill and the official TypeScript SDK: npm install @waffo/pancake-ts. Read https://docs.waffo.ai/llms-full.txt for the full API reference. Setup: 1) Install SDK and create a WaffoPancake client with WAFFO_MERCHANT_ID and WAFFO_PRIVATE_KEY 2) Create a checkout endpoint using client.checkout.createSession({ storeId, productId, productType: 'onetime', currency: 'USD' }) — redirect user to session.checkoutUrl 3) Create a webhook handler using verifyWebhook(rawBody, signature) from the SDK to verify x-waffo-signature header 4) Handle events: order.completed, subscription.activated, subscription.canceled — return 200 OK immediately. Test card: 4242 4242 4242 4242 (any future expiry, any CVC)" ``` Run in your terminal: ```bash theme={"dark"} codex "Integrate Waffo Pancake payments into my web application. Use the Waffo Pancake Skill and the official TypeScript SDK: npm install @waffo/pancake-ts. Read https://docs.waffo.ai/llms-full.txt for the full API reference. Setup: 1) Install SDK and create a WaffoPancake client with WAFFO_MERCHANT_ID and WAFFO_PRIVATE_KEY 2) Create a checkout endpoint using client.checkout.createSession({ storeId, productId, productType: 'onetime', currency: 'USD' }) — redirect user to session.checkoutUrl 3) Create a webhook handler using verifyWebhook(rawBody, signature) from the SDK to verify x-waffo-signature header 4) Handle events: order.completed, subscription.activated, subscription.canceled — return 200 OK immediately. Test card: 4242 4242 4242 4242 (any future expiry, any CVC)" ``` Open Cursor, press Cmd+K (or Ctrl+K), then paste: ```text theme={"dark"} Integrate Waffo Pancake payments into my web application. Use the Waffo Pancake Skill and the official TypeScript SDK: npm install @waffo/pancake-ts Read https://docs.waffo.ai/llms-full.txt for the full API reference. Setup: 1. Install SDK and create a WaffoPancake client with WAFFO_MERCHANT_ID and WAFFO_PRIVATE_KEY 2. Create a checkout endpoint using client.checkout.createSession({ storeId, productId, productType: "onetime", currency: "USD" }) — redirect user to session.checkoutUrl 3. Create a webhook handler using verifyWebhook(rawBody, signature) from the SDK to verify x-waffo-signature header 4. Handle events: order.completed, subscription.activated, subscription.canceled — return 200 OK immediately Test card: 4242 4242 4242 4242 (any future expiry, any CVC) ``` These AI prompts are based on the official [Waffo Pancake Skill](/integrate/sdk-skill). You can also download the Skill file and add it directly to your AI coding assistant. *** ## Ship Revenue in 5 Minutes No credit card required. No LLC needed. Just sign up and start selling. Get Started Steps *** ## 1. Create Account ``` https://dashboard.waffo.ai/merchant/auth/signin ``` Three options: * **Google OAuth** — One click. Done. * **GitHub OAuth** — For developers. Quick and easy. * **Magic Link** — Email. Click link. In. *** ## 2. Create Store First login triggers store setup: | Field | What It Does | | ---------- | ------------------------ | | Store Name | Your brand name | | Currency | Default for new products | | Country | Your business location | No business registration required. Solo founders welcome. *** ## 3. Add Product Dashboard → Products → **Create Product** Create Product Form ```json theme={"dark"} { "name": "Pro Plan", "prices": { "USD": { "amount": 2900, "taxIncluded": false, "taxCategory": "saas" } } } ``` For subscriptions, also set `billingPeriod` (`weekly`, `monthly`, `quarterly`, `yearly`) and define `tiers`. **One-time or subscription.** Your choice. For subscriptions: * Pick billing period * Add multiple tiers (optional) * Enable free trial (optional) * Set trial days *** ## 4. Get Your Purchase Link Product created? You get a permanent purchase link: ``` https://checkout.waffo.ai/{store-slug}/{product-slug} ``` Share it. Embed it. Tweet it. Done. This link is permanent — it never expires and stays valid even when you update the product. Just click "Copy Link" in the Dashboard. *** ## 5. Get Paid Customer pays → We handle taxes → You receive payout. Funds go directly to your bank account. No intermediary. No delays. Finance Payout Setup *** ## Test vs Live * No real charges * Safe to experiment * Separate test data * Real payments * Real payouts * Toggle when ready **Switch in Dashboard header.** Toggle via `X-Environment` header in API. Always test first. *** ## Test Cards | Card | Result | | --------------------- | --------- | | `4242 4242 4242 4242` | Success | | `4000 0000 0000 0002` | Declined | | `4000 0027 6000 3184` | 3D Secure | Any future expiry. Any CVC. *** ## Going Live Checklist Before flipping to Live Mode: * [ ] Test checkout flow end-to-end * [ ] Verify webhook endpoints (if using) * [ ] Add bank account for payouts (Finance → Payout Setup) * [ ] Complete business details (Settings → Business Details) * [ ] Review product pricing * [ ] Sync products from test to production *** ## What's Next? Pricing models. Trials. Intervals. Recurring billing. Dunning. Lifecycle. Your brand. Your colors. Our infra. API keys. Webhooks. Your backend. *** ## Need Help? Community support. Fast answers. # Developers Source: https://waffo.mintlify.app/settings/developers API keys and developer tools ## Developer Settings The Developers page provides tools for integrating Waffo Pancake with your applications. ## API Keys ### Overview API keys authenticate server-to-server requests to the Waffo Pancake API. * Created for `test` environment * Use for development * No real charges * Separate from production data * Created for `prod` environment * Use for production * Process real payments * Keep private key secure ### Key Types | Key Type | Use Case | Description | | ----------- | ---------------- | ----------------------------------- | | **API Key** | Server-side only | Signed requests for full API access | ### API Key Authentication API Key authentication is handled automatically by the SDK. Install `@waffo/pancake-ts`, provide your Merchant ID and private key, and the SDK will handle request signing automatically. ```typescript theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); ``` Never expose your private key in client-side code, version control, or public repositories. ### Creating API Keys Go to Dashboard --> Developers --> API Keys The API Key Generator opens. Click "Generate" to create a key pair. * Public key is sent to the server * Private key stays with you Give it a descriptive nickname (e.g., "Production Server"). Choose **Test** or **Production** environment. **Critical:** Download and securely store your private key. Your private key is only shown once. Store it securely -- you will need it for API authentication. ### Managing Keys | Action | Description | | ------ | -------------------------------------------- | | View | See key nickname, creation date, environment | | Delete | Permanently remove the key | ## Webhooks ### What Are Webhooks? Webhooks notify your server when events occur in Waffo Pancake. ### Available Events | Event | Trigger | | -------------------------------- | ----------------------------------- | | `order.completed` | Order completed | | `subscription.activated` | Subscription activated | | `subscription.payment_succeeded` | Subscription payment succeeded | | `subscription.updated` | Subscription updated | | `subscription.canceling` | Subscription cancellation scheduled | | `subscription.canceled` | Subscription ended | | `subscription.uncanceled` | Subscription cancellation reversed | | `subscription.past_due` | Subscription payment past due | | `refund.succeeded` | Refund processed successfully | | `refund.failed` | Refund processing failed | ### Setting Up Webhooks Enter your webhook URL (must be HTTPS). Choose which events to receive. Save your webhook endpoint. ### Webhook Payload Example ```json theme={"dark"} { "event": "order.completed", "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "orderId": "660e8400-e29b-41d4-a716-446655440001", "amount": 2900, "currency": "USD", "status": "completed", "createdAt": "2026-01-15T10:30:00.000Z" } } ``` All IDs are UUID v4 format. Amounts are in the smallest currency unit. Timestamps are ISO 8601 UTC. ### Webhook Best Practices Return 2xx status within 30 seconds. Process heavy work asynchronously. Events may be sent multiple times. Use event IDs for deduplication. Failed webhooks retry up to 5 times with increasing delays (5min, 30min, 2h, 24h). Check webhook delivery logs in the Dashboard for failures. ## API Documentation ### Base URL ``` https://waffo-pancake-auth-service.vercel.app/v1 ``` ### Architecture Waffo Pancake uses a hybrid API: * **REST (POST)** for all write operations via `/v1/actions/...` * **GraphQL** for all read operations via `/v1/graphql` ### Authentication Example **API Key (Server-to-Server) using SDK:** ```typescript theme={"dark"} import { WaffoPancake } from "@waffo/pancake-ts"; const client = new WaffoPancake({ merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY!, }); const { store } = await client.stores.create({ name: "My Store" }); ``` ### Common Endpoints | Endpoint | Method | Description | | ------------------------------------------------- | ------ | ---------------------------- | | `/v1/actions/onetime-product/create-product` | POST | Create one-time product | | `/v1/actions/subscription-product/create-product` | POST | Create subscription product | | `/v1/actions/onetime-order/create-order` | POST | Create checkout session | | `/v1/actions/subscription-order/create-order` | POST | Create subscription checkout | | `/v1/graphql` | POST | Query data (GraphQL) | Complete endpoint documentation with request/response examples. ## Security Best Practices Store private keys in environment variables, never in code. Regularly rotate keys, especially after team changes. Use different API keys for test and production environments. Store private keys using your platform's secret management. ## Testing ### Test Mode Use test mode for development: * All endpoints work identically * No real charges processed * Test card numbers available * Full webhook testing ### Test Cards | Card Number | Behavior | | --------------------- | ------------------ | | `4242 4242 4242 4242` | Success | | `4000 0000 0000 0002` | Declined | | `4000 0000 0000 9995` | Insufficient funds | ## Logs and Debugging ### Webhook Logs Track webhook deliveries: * Event type * Delivery status (success/failed) * HTTP response from your endpoint * Retry attempts and timestamps # Store Settings Source: https://waffo.mintlify.app/settings/store-settings Configure your store preferences ## Store Settings Overview Manage your store's basic configuration, preferences, and operational settings. Store Settings ## Accessing Store Settings 1. Click your store name in the Dashboard header 2. Select "Settings" from the dropdown 3. Or navigate via sidebar → Settings ## General Settings ### Store Information | Setting | Description | | ------------- | --------------------------------------- | | Store Name | Your business name (shown to customers) | | Store URL | Unique identifier in URLs | | Description | Brief description of your store | | Support Email | Where customers can reach you | | Website URL | Your main website link | ### Default Currency Set the default currency for new products: | Currency | Code | Symbol | | ---------------- | ---- | ------ | | US Dollar | USD | \$ | | Euro | EUR | € | | British Pound | GBP | £ | | Chinese Yuan | CNY | ¥ | | Hong Kong Dollar | HKD | HK\$ | Changing the default currency only affects new products. Existing products keep their original currency. ### Timezone Select your business timezone for: * Dashboard date displays * Report generation * Scheduled emails * Billing calculations ## Mode Settings ### Test Mode Control your test environment: | Option | Description | | -------------------- | ----------------------------- | | Test Mode Toggle | Switch between test and live | | Test Data Visibility | Show/hide test transactions | | Test Notifications | Enable test mode email alerts | ### Going Live Checklist Before switching to Live mode, ensure: * [ ] Business details completed * [ ] Bank account verified * [ ] Tax settings configured * [ ] At least one active product * [ ] Checkout branding set up * [ ] Webhook endpoints configured (if using) ## Notification Settings ### Email Notifications Configure which emails you receive: | Notification | Description | Default | | --------------------- | --------------------------------- | ------- | | New Payment | Alert for each successful payment | On | | Failed Payment | Alert when payment fails | On | | New Subscription | When customer subscribes | On | | Subscription Canceled | When subscription ends | On | | Chargeback Alert | Immediate dispute notification | On | | Weekly Summary | Weekly business summary | On | ### Notification Channels * **Email** - Sent to account email * **Dashboard** - In-app notification center ## Team Settings ### Invite Team Members Add colleagues to help manage your store: Find in Settings → Team Provide their email address Choose appropriate permissions They'll receive an email to join ### Team Roles | Role | Permissions | | ---------- | ------------------------------------------------- | | **Owner** | Full access, including billing and store deletion | | **Admin** | Update store settings, manage products and orders | | **Member** | Read-only access to store data | ## Danger Zone Actions in this section are irreversible. Proceed with caution. ### Delete Store Permanently delete your store: * All products removed * All customer data deleted * Payment history archived * Cannot be undone ### Transfer Ownership Transfer store to another user: 1. Enter new owner's email 2. They must accept the transfer 3. Your access is removed after transfer ## Multi-Store Management ### Creating Additional Stores 1. Click store selector in header 2. Select "Create New Store" 3. Follow onboarding for new store 4. Switch between stores via selector You can create up to 20 stores per merchant account. ### Store Use Cases | Scenario | Recommendation | | ------------------------------ | --------------- | | Different brands | Separate stores | | Different regions | Separate stores | | Test vs Production | Separate stores | | Different products, same brand | Single store | ## Settings Export Export your store settings for backup: 1. Go to Settings → Export 2. Select data types 3. Download JSON/CSV file Exportable data: * Store configuration * Product catalog * Customer list * Transaction history