Merchant docs

Design your Pulze integration before approval: payment links, recurring mandates, multi-token checkout, credit top-ups, agent billing, webhooks, SDK, and MCP.

Builder access is open. You can use all documentation and prepare your integration now. API keys and payment execution unlock after Pulze verifies the merchant; no credential or customer charge is available from documentation access alone.

Payment links

Create a link from the dashboard. Your customer opens it, connects a wallet, signs once, and Pulze records the payment or subscription against your merchant account.

Unified crypto payments

Customers can pay using bits of crypto left across supported wallets/tokens. The system routes them programmatically into one payment and settles to your preferred stablecoin.

Recurring payments

The customer signs the subscription approval once. When the billing period is due, Pulze can execute the authorized pull without asking the customer for a second approval.

Club memberships

Sports clubs, creators, alumni groups, professional associations, gaming communities, charities and other member organizations can configure recurring dues and member benefits. Your server can create a hosted checkout link automatically through the merchant API.

API keys and SDK

Build against the typed SDK interfaces for server-side subscriptions, invoices, reporting, webhooks, and checkout. Generate credentials after account approval.

MCP and agent billing

Connect approved AI agents to bounded usage reporting and saved-mandate charging. Human review modes, merchant limits, audit logs, and kill switches remain in the payment path.

Credits and usage businesses

Let customers enter a top-up amount once, save a mandate, and add credits later without repeating wallet setup. Usage businesses can meter first and bill within approved caps.

Webhooks and reconciliation

Consume signed lifecycle events for payments, subscriptions, refunds, disputes, payouts, and credit notes. Treat transaction confirmation as the source of payment truth.

Choose your integration

  • No-code commerce: create and share payment or subscription links.
  • SaaS and memberships: schedule recurring charges under one customer mandate.
  • Usage and compute: report metered usage, review it, then charge within caps.
  • Wallet credits: let customers choose an amount and repeat top-ups later.
  • Marketplaces and families: coordinate split invoices and recurring shares.
  • Agentic commerce: give an agent a narrowly scoped key with human controls.
  • Club membership flow

    1. Choose a membership type, dues, billing interval, settlement destination and accepted customer routes.
    2. Optionally configure claimable per-cycle rewards and an existing club asset for display.
    3. Create links in the dashboard, or have your server create them when a member selects a plan.
    4. Member connects wallet and signs the dues authorization.
    5. Pulze tracks the subscription and rewards after each confirmed paid cycle.
    6. Members request reward claims in the Pulze portal; the club sends and verifies the transfer.

    Asset details can describe an existing token or NFT, but do not mint, transfer, or grant membership rights. Rewards are tracked by Pulze and claimed by members; the club currently sends those tokens from its own wallet.

    Create a club checkout from your website

    Call Pulze from your server when a member chooses a plan. Return the hosted URL to your site and redirect the member there. Store the link ID against your own signup/order key so your server can reuse it after a retry. Never expose your merchant API key to the browser.

    const response = await fetch(
      `https://api.pulze.guru/api/v1/merchants/${process.env.PULZE_MERCHANT_ID}/payment-links`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': process.env.PULZE_API_KEY,
        },
        body: JSON.stringify({
          amount: '10000000', // $10.00, USD 6 decimals
          chain: 'base', // settlement network. Omit token to settle in the chain's USDC
          period: 2592000, // monthly
          title: 'Supporter membership',
          customerEmail: member.email,
          metadata: {
            vertical: 'club-membership',
            membership: {
              clubType: 'sports',
              membershipName: 'Supporter',
              benefits: ['Member status while active'],
              memberAgreement: 'Your membership terms…',
              rewards: { enabled: false },
            },
            fanAsset: { enabled: false, delivery: 'manual' },
          },
        }),
      },
    );
    if (!response.ok) throw new Error('Could not prepare checkout');
    const { url, id } = await response.json();
    await saveLinkForSignup(member.signupId, id); // merchant-owned idempotency
    return { checkoutUrl: url };

    The hosted checkout is served by Pulze at the returned URL. This API call creates a payment link; your website controls its signup UX, retries, redirect, and membership records.

    Connect repeat top-ups to your app

    For credits or compute usage, start a short-lived checkout handoff from your server using your app's session ID. Pulze returns a one-use PKCE result after the customer selects a wallet and approves the reusable permission. Your app can then save that wallet and use the existing repeat top-up flow.

    1. Create a handoff for your variable credit top-up link with integrationSessionId, codeChallenge and state.
    2. Open checkoutUrl. Verify Pulze origin, popup source and state before forwarding the one-time code to your server.
    3. Exchange the code server-side with the saved verifier, then store the returned credential securely.
    const handoff = await pulze.topUps.createCheckoutHandoff(
      merchantId,
      topUpPaymentLinkId,
      { integrationSessionId, codeChallenge, state },
    );
    return { checkoutUrl: handoff.checkoutUrl };
    
    const saved = await pulze.topUps.exchangeCheckoutHandoff(merchantId, {
      authorizationCode,
      codeVerifier, // load only from your server-side session store
    });
    // Keep saved.customerTopUpAuthorization encrypted on your server.

    The result is bound to your merchant, link, app session, checkout-selected wallet and active Pulze permission. It works only for customer-requested top-ups; it does not authorize merchant-triggered off-cycle charges. See the Pulze SDK README for complete setup and repeat-charge examples. A top-up link must have no fixed amount: creation is refused if it has one.

    Every way to create an invoice

    Amounts are USD6 integer strings ($10.00 is "10000000"). chain is where you are paid; token is the settlement token's contract address (omit it for the default). An invoice is paid only after Pulze confirms the payment, never when an API call returns.

    1. One-time invoice: POST /merchants/{id}/payment-links with amount, title, optional customerEmail, expiresAt, maxUses and taxBehavior. Send the returned url to the customer.
    2. Subscription or trial: the same call with period (seconds), optional maxCycles (0 = until cancelled) and trialDays. A period needs a fixed amount.
    3. Credit top-up: no amount, metadata { billingIntentType: 'credit_top_up', variableAmount: true }. Customer limits default to $1 minimum, $1,000 per deposit, $2,500 per day. A fixed amount is refused.
    4. Metered usage link: metadata.billingIntentType 'metered_usage' with a positive initial amount; optional customer caps in metadata.authorization (maxAmountPerChargeUsd6, dailyCapUsd6).
    5. Split invoice: POST /merchants/{id}/payment-links/split with 2 to 12 shares. One single-use link per payer; read progress at GET /payment-links/split/{groupId}.
    6. Club membership: a recurring link with metadata.vertical 'club-membership' (see club token configuration below).
    7. Products and customer bills (dashboard session): create a product, assign it to a customer, email the checkout link, or charge a saved permission.
    8. Quick charge or off-cycle: bill and charge a customer who already saved a permission. Run the read-only preflight first; the settlement network must be inside their signed scope.
    9. Agent charge: POST /agent/customers/{payer}/charge with an agent-scoped key. requestId is required and makes retries safe.
    10. Signed subscription: pulze.subscriptions.create after the payer signs the EIP-712 subscription once.

    Customer coins are chosen with sourceRouteMode and acceptedRoutes ({ "8453": ["USDC", "USDT"] }), separately from where you are paid. Each coin must be an executable route on its chain, and more accepted coins mean more wallet prompts for a plain wallet. API keys authenticate payment-link routes; product, customer-bill and quick-charge routes need a merchant session. Full reference: docs/INTEGRATION-INVOICES-AND-CLUB-TOKENS.md.

    Club token configuration

    A club link tracks dues and earned rewards. Pulze does not mint, transfer or fund tokens; the club sends rewards from its own wallet. Three token settings are separate: dues settlement (chain and token), the coins members pay with (acceptedRoutes), and the two club-token fields below.

    1. Reward token (membership.rewards): ERC-20 only. Needs chainId, tokenAddress, tokenDecimals (must equal the on-chain decimals), amountPerCycle in raw token units and a trigger of EVERY_PAYMENT or FIRST_PAYMENT. Requires a recurring club-membership link.
    2. Rewards are earned only by a confirmed recurring payment with no dispute or refund. FIRST_PAYMENT pays once per member per link and is not repeated on re-subscribe. Earned rewards stay earned if the member cancels.
    3. Display asset (fanAsset): an existing ERC-20, ERC-721 or ERC-1155 shown to members. Needs address and a network (defaults to the settlement chain); ERC-20 decimals are verified. It does not deliver the asset.
    4. Verify first: POST /merchants/{id}/payment-links/club-token-metadata with chainId, address and type returns the verified symbol and decimals, or a 400. Available networks: GET /payment-links/route-capabilities, linkSetup.assetChains.
    5. Claims: members request earned rewards in the Pulze portal. You list requests, send the tokens from your wallet, then fulfill with the transfer hash; Pulze checks the exact ERC-20 transfer. Or decline; the member keeps the rewards.
    6. The reward and display tokens may live on a different network than your settlement chain, on any network Pulze can read.
    metadata: {
      vertical: 'club-membership',
      membership: {
        clubType: 'sports',
        membershipName: 'Supporter',
        rewards: {
          enabled: true,
          trigger: 'FIRST_PAYMENT',      // or 'EVERY_PAYMENT'
          chainId: 8453,
          tokenAddress: '0x...',         // ERC-20 on that network
          tokenDecimals: 18,             // must match the contract
          amountPerCycle: '5000000000000000000', // raw units: 5 tokens at 18 decimals
        },
      },
      fanAsset: { enabled: true, type: 'ERC721', chainId: 8453, address: '0x...', delivery: 'manual' },
    }

    Quick API

    Prepare this server-side integration now. Add the issued key only after verification.

    import { PulzeClient } from '@pulze/sdk';
    
    const pulze = new PulzeClient({
      baseUrl: 'https://api.pulze.guru/api/v1',
      apiKey: process.env.PULZE_API_KEY
    });
    
    await pulze.subscriptions.create({
      sub,
      signature,
      email: 'customer@example.com',
      chain: 'base'
    });

    TypeScript SDK

    Use the typed client from your server. Keep issued credentials out of browsers, repositories, logs, prompts, and client bundles.

    npm install @pulze/sdk ethers
    
    const pulze = new PulzeClient({
      baseUrl: 'https://api.pulze.guru/api/v1',
      apiKey: process.env.PULZE_API_KEY
    });

    MCP discovery

    Run the MCP server without a key to inspect public payment links and route quotes. Authenticated agent tools unlock only after verification and scoped-key issuance.

    PULZE_API_URL=https://api.pulze.guru \
    node packages/mcp/src/server.mjs
    
    # Add PULZE_MCP_API_KEY only after approval.

    API authentication and schema

    Store the issued key as PULZE_API_KEY on your server and send it in X-API-Key. It is not a Bearer token. Interactive dashboard sessions use Bearer authentication separately.

    POST /api/v1/merchants/{merchantId}/payment-links
    X-API-Key: pk_live_...
    Content-Type: application/json
    
    {
      "amount": "100000000",
      "title": "Monthly plan",
      "period": 2592000,
      "maxCycles": 0,
      "trialDays": 0,
      "customerEmail": "customer@example.com",
      "taxBehavior": "EXCLUSIVE"
    }

    Amount uses six-decimal smallest units: $100.00 is 100000000. Omit period for one-time checkout. A positive period creates recurring billing; zero max cycles means the subscription remains active until cancelled.

    # Python
    from decimal import Decimal
    import requests
    
    usd6 = str(int(Decimal("100.00") * 1_000_000))
    response = requests.post(
        f"https://api.pulze.guru/api/v1/merchants/{merchant_id}/payment-links",
        headers={"X-API-Key": PULZE_API_KEY},
        json={"amount": usd6, "title": "Monthly plan", "period": 2592000},
        timeout=20,
    )
    response.raise_for_status()

    Signed webhook contract

    Register an HTTPS endpoint in merchant Settings. Pulze shows its signing secret once, supports test delivery and replay, and retries failed deliveries with backoff.

    Pulze-Event: payment.confirmed
    Pulze-Delivery: delivery_id
    Pulze-Timestamp: 1780000000
    Pulze-Signature-Version: v1
    Pulze-Signature: v1=<hex hmac sha256>
    
    signature = HMAC_SHA256(
      PULZE_WEBHOOK_SECRET,
      Pulze-Timestamp + "." + rawRequestBody
    )
    
    {
      "id": "delivery_id",
      "type": "payment.confirmed",
      "createdAt": "ISO-8601 timestamp",
      "data": { "paymentId": "...", "status": "CONFIRMED", "txHash": "0x..." }
    }

    Verify against the untouched raw request body before parsing JSON. Reject stale timestamps and deduplicate by the outer delivery id. Core events are payment.confirmed, invoice.funding_confirmed, invoice.action_required, subscription.created, subscription.action_required, dispute.opened, dispute.resolved, refund.approved, refund.completed, and refund.failed.

  • payment.confirmed: paymentId, paymentLinkId, optional fundingSessionId, subscriptionId, payer address/email, chain, tokens, gross/subtotal/tax/fee/net amounts, status, txHash, payment type.
  • invoice.funding_confirmed: paymentLinkId, fundingSessionId, payer, reserve target, completed source-step count. This confirms reserve funding only; the invoice remains unpaid until payment.confirmed.
  • invoice.action_required: paymentLinkId, fundingSessionId, payer, target, failed source/network steps, reason, and transaction references. The customer must resolve the stated issue before invoice payment.
  • subscription.created: subscriptionId, paymentLinkId, payer address/email, chain, token, amount per cycle, period, max/executed cycles, total paid, status, next payment date.
  • subscription.action_required: subscriptionId, paymentLinkId when available, payer, charge network, reason, required customer/operator action, resume path, and paymentStatus=NOT_PAID. This is a recovery notice, never a payment confirmation.
  • dispute events: disputeId, paymentId, status/outcome, frozen amount, reason, and whether a refund is required.
  • refund events: refund/payment/dispute ids where applicable, amount, token, chain, status, txHash, and failure reason.
  • Builder-to-launch checklist

    1. Complete merchant signup and payout wallet.
    2. Choose the API, SDK, MCP, or no-code integration pattern.
    3. Map payment, refund, dispute, and payout webhook handling.
    4. Complete Pulze account verification.
    5. Generate credentials and run the controlled integration test.
    6. Enable customer payments only after the launch review passes.