Skip to main content

Payment Flows

PayChain supports several payment and treasury flows. Choose the simplest flow that matches the business outcome. Most merchants should start with fixed amount invoices, then add payout routing, dynamic recipients, or programmatic withdrawals only when the workflow needs it.
Important note: Invoice state is the source of truth for customer payment fulfillment. Balances and transactions are useful for reconciliation, but they should not replace verified invoice status.

Flow overview

FlowBest forKey API surfaceFund movement
Fixed amount invoiceCheckout, one-off payment links, SaaS invoices, order paymentsCustomers, invoices, webhooksCustomer pays invoice. Merchant later withdraws or settles.
Auto-detected paymentRepeat payer addresses, fintech deposits, wallet-style fundingCustomer addresses, auto-generated invoices, webhooksPayChain detects qualifying deposits and creates invoice records.
Payout route invoiceRepeated split patterns, marketplace seller splits, revenue shareInvoice with payoutRouteIdPayChain creates payout withdrawals after full settlement.
Dynamic payout recipientsOn/off-ramp orders, one-time marketplace receiversInvoice with payoutRecipientsPayChain creates payout withdrawals to invoice-specific recipients after full settlement.
Programmatic withdrawalTreasury payout automation, off-platform settlementWithdrawal quote and createBackend creates a withdrawal using a payout API key.
Key separation note: Standard API keys are for collection, invoices, reads, balances, transactions, networks, tokens, and webhooks. Programmatic fund movement requires a payout API key.
Plan note: Payout API withdrawals are plan-priced. Free plan businesses have no included payout API quota, so programmatic withdrawals can still be created with a payout API key, but the Free payout API fee applies from the first withdrawal.

Fixed amount invoice

Use this when the customer should pay a known amount for an order, subscription, invoice, top-up, or checkout session.

What happens

  1. Your backend creates or finds a customer.
  2. Your backend creates an invoice with amount, token, chain, and network.
  3. The customer pays the invoice address.
  4. PayChain detects and confirms settlement.
  5. PayChain sends an invoice webhook.
  6. Your backend verifies the webhook and fetches the invoice.
  7. Your system fulfills the order.

SDK example

const invoice = await paychain.invoices.create(
  {
    amount: '100.00',
    token: 'USDC',
    chain: 'evm',
    networkId: 'base-mainnet',
    customerId: 'customer_123',
    metadata: {
      orderId: 'order_123'
    }
  },
  { idempotencyKey: 'order_123_invoice' }
);

REST equivalent

curl -X POST "$PAYCHAIN_API_URL/businesses/$PAYCHAIN_BUSINESS_ID/invoices" \
  -H "x-api-key: $PAYCHAIN_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: order_123_invoice" \
  -d '{
    "amount": "100.00",
    "token": "USDC",
    "chain": "evm",
    "networkId": "base-mainnet",
    "customerId": "customer_123",
    "metadata": {
      "orderId": "order_123"
    }
  }'
Best first flow: Fixed amount invoices are the cleanest first integration because the customer, amount, asset, network, webhook, and fulfillment state are explicit.

Auto-detected payment

Use this when repeat users deposit to a reusable customer address and you do not want to pre-create every invoice.

What happens

  1. The customer has a reusable PayChain deposit address.
  2. A supported transfer arrives on that address.
  3. PayChain applies strict asset matching, dust protection, and internal-transfer exclusions.
  4. PayChain creates an auto-generated invoice record for a qualifying deposit.
  5. PayChain sends the normal invoice webhook.
Dust protection note: Auto-detected deposits below configured thresholds, non-positive observations, sponsored-gas activity, and internal operational wallet transfers should not become customer revenue.

Use cases

  • Fintech wallet funding.
  • Recurring customer deposit addresses.
  • Gaming deposits.
  • On/off-ramp user funding.

API surfaces

  • Create or fetch customer.
  • Read customer deposit addresses where available.
  • Listen for invoice.* webhooks.
  • Fetch the canonical invoice after webhook verification.
REST note: Auto-detection is usually configured around customer deposit addresses and backend webhooks. The important REST action is not creating every invoice manually; it is reconciling the auto-generated invoice PayChain creates after a qualifying deposit.

Payout route invoice

Use this when the same split pattern repeats across many invoices, such as marketplace seller splits or partner revenue share.

What happens

  1. An operator creates and approves a payout route template in the dashboard.
  2. Your backend creates an invoice with payoutRouteId.
  3. The customer fully pays or overpays the invoice.
  4. PayChain calculates net business amount after fees.
  5. PayChain creates one withdrawal per route recipient.
  6. Each recipient leg counts as one payout API withdrawal for quota and fee purposes.

SDK example

await paychain.invoices.create(
  {
    amount: '250.00',
    token: 'USDC',
    chain: 'evm',
    networkId: 'base-mainnet',
    payoutRouteId: 'route_marketplace_seller_split'
  },
  { idempotencyKey: 'order_456_invoice' }
);

REST equivalent

curl -X POST "$PAYCHAIN_API_URL/businesses/$PAYCHAIN_BUSINESS_ID/invoices" \
  -H "x-api-key: $PAYCHAIN_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: order_456_invoice" \
  -d '{
    "amount": "250.00",
    "token": "USDC",
    "chain": "evm",
    "networkId": "base-mainnet",
    "payoutRouteId": "route_marketplace_seller_split"
  }'
Routing note: Payout routing triggers only after full settlement. It should not run for tolerated underpayments, failed invoices, or wrong-asset payments.

Dynamic payout recipients

Use this when the receiver changes on each invoice, such as on-ramp, off-ramp, or marketplace orders with one-time sellers.

What happens

  1. Your trusted backend validates the receiver and order.
  2. Your backend creates an invoice with payoutRecipients.
  3. The customer fully pays or overpays the invoice.
  4. PayChain splits the net amount by percentage.
  5. PayChain creates payout withdrawals after settlement.

SDK example

await paychain.invoices.create(
  {
    amount: '500.00',
    token: 'USDC',
    chain: 'evm',
    networkId: 'base-mainnet',
    payoutRecipients: [
      {
        label: 'Receiver',
        destinationAddress: '0x0000000000000000000000000000000000000000',
        percentage: 98
      },
      {
        label: 'Operator fee',
        destinationAddress: '0x0000000000000000000000000000000000000000',
        percentage: 2
      }
    ]
  },
  { idempotencyKey: 'order_789_invoice' }
);

REST equivalent

curl -X POST "$PAYCHAIN_API_URL/businesses/$PAYCHAIN_BUSINESS_ID/invoices" \
  -H "x-api-key: $PAYCHAIN_PAYOUT_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: order_789_invoice" \
  -d '{
    "amount": "500.00",
    "token": "USDC",
    "chain": "evm",
    "networkId": "base-mainnet",
    "payoutRecipients": [
      {
        "label": "Receiver",
        "destinationAddress": "0x0000000000000000000000000000000000000000",
        "shareBps": 9800
      },
      {
        "label": "Operator fee",
        "destinationAddress": "0x0000000000000000000000000000000000000000",
        "shareBps": 200
      }
    ]
  }'
Security note: Do not trust payout destinations submitted directly by a browser or mobile app. Validate receivers, order status, limits, and fraud rules in your backend before creating the invoice.

Programmatic withdrawal

Use this when your backend needs to move business treasury funds after your own business logic approves the payout.
Free plan behavior: Free plan includes 0 payout API withdrawals as free quota, not as a withdrawal ban. A Free plan payout API key can create programmatic withdrawals when policy and balance checks pass, and the Free payout API fee is deducted from the requested amount.

What happens

  1. Your backend calculates the payout.
  2. Your backend requests a withdrawal quote.
  3. Your backend creates the withdrawal with a payout API key.
  4. PayChain queues the withdrawal and checks withdrawable treasury capacity.
  5. If recent invoice funds are still sweeping into treasury, PayChain can hold the withdrawal in pending_funds until those sweepable funds are available.
  6. PayChain processes the withdrawal through the normal lifecycle.
  7. PayChain sends withdrawal webhooks.

SDK example

const quote = await paychain.withdrawals.quote({
  token: 'USDC',
  chain: 'evm',
  networkId: 'base-mainnet',
  amount: '100.00',
  destinationAddress: '0x0000000000000000000000000000000000000000'
});

const withdrawal = await paychain.withdrawals.create(
  {
    quoteId: quote.id,
    clientReference: 'payout_123'
  },
  { idempotencyKey: 'payout_123' }
);

REST equivalent

curl -X POST "$PAYCHAIN_API_URL/businesses/$PAYCHAIN_BUSINESS_ID/withdrawals/quote" \
  -H "x-api-key: $PAYCHAIN_PAYOUT_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: payout_123_quote" \
  -d '{
    "token": "USDC",
    "chain": "evm",
    "networkId": "base-mainnet",
    "amount": "100.00",
    "destinationAddress": "0x0000000000000000000000000000000000000000"
  }'

curl -X POST "$PAYCHAIN_API_URL/businesses/$PAYCHAIN_BUSINESS_ID/withdrawals" \
  -H "x-api-key: $PAYCHAIN_PAYOUT_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: payout_123" \
  -d '{
    "quoteId": "quote_123",
    "clientReference": "payout_123"
  }'
Gas credit note: If PayChain sponsors network cost for a withdrawal, the operation can consume included or prepaid gas credits. If credits are insufficient, the withdrawal may become gas-blocked until top-up.
Immediate payout note: For webhook-driven payouts, create withdrawals with idempotency keys and then follow withdrawal state. A valid withdrawal may be accepted as pending_funds while PayChain finishes sweeping newly settled invoice funds. A true over-withdrawal or non-sweepable legacy source balance can still be rejected.

Which flow should I choose?

If you need…Choose
A customer pays a known amountFixed amount invoice
Repeat payer deposits without pre-created invoicesAuto-detected payment
Same split template across many invoicesPayout route invoice
One-time receiver per invoiceDynamic payout recipients
Backend-controlled treasury movementProgrammatic withdrawal

Common mistakes

  • Using auto-detection when the payment amount and order should be exact.
  • Using dynamic payout recipients without server-side receiver validation.
  • Treating a payout route as active before the invoice is fully settled.
  • Using a standard API key for programmatic withdrawals.
  • Fulfillment based only on transaction history instead of canonical invoice state.
  • Retrying payout or withdrawal creation without an idempotency key.
  • Treating totalHeld or recovery-required balance as immediately withdrawable. Use the withdrawal quote or amounts.total for withdrawable capacity.