Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.request.network/llms.txt

Use this file to discover all available pages before exploring further.

What you’ll build

A workflow for paying many recipients at once with a single payer signature — gas-sponsored, atomic, on EVM. Either hand the payer a hosted batch URL on pay.request.network (recommended), or pay programmatically by getting calldata and broadcasting it yourself. Audience: marketplaces paying out sellers, agencies paying contractors, refund campaigns, payroll-adjacent flows, any scenario where you’d otherwise sign N transactions back-to-back.
EVM-only. Tron does not support batch payments. Submitting a batch with Tron destinations returns a 400 with: Batch payments are not supported for TRON networks. Please submit individual payment requests. For Tron recipients, send single payouts in a loop using POST /v2/payouts or POST /v2/secure-payments/payouts.

Two modes

ModeEndpointWhat you get back
Hosted Batch Link (recommended)POST /v2/secure-payments with multiple requests[]A pay.request.network URL the payer opens, signs once, and pays everyone
Direct Execution (advanced)POST /v2/payouts/batchApproval calldata + a single batch payment transaction you broadcast from your wallet
Pick hosted batch link for most scenarios — the payer reviews recipients and the transaction on the Secure Payment Page before signing. Pick direct execution only when your backend already signs payouts in fully automated environments with appropriate security controls.

Prerequisites

Same as the Quickstart — you need a Client ID. Webhooks are optional but recommended so you get notified when each leg of the batch settles. The Secure Payment Page, hosted on a decentralized protocol, allows operators to review and verify transactions before execution, reducing operational risk. The Hosted Batch Link supports cross-chain execution from a single wallet connection. Users can pay batches across the top supported EVM chains without switching environments or executing separate transactions per chain. The Secure Payment Page handles routing and cross-chain execution automatically, allowing operators to initiate payouts from one connected destination while supporting payments across multiple EVM networks. Mint a hosted link with multiple requests[] and share it with whoever signs payouts:
const response = await fetch(
  "https://api.request.network/v2/secure-payments",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-client-id": process.env.RN_CLIENT_ID!,
    },
    body: JSON.stringify({
      requests: contractors.map((c) => ({
        destinationId: c.destinationId,
        amount: c.amount,
      })),
      reference: `payroll-${period}`,
    }),
  },
);

const { securePaymentUrl } = await response.json();
// Send securePaymentUrl to whoever signs payouts
The Secure Payment Page shows the full payee list, total amount, and a single approval-then-pay flow. The payer signs once.

Mode 2 — Direct Execution (Advanced & Self-Secure)

Direct execution removes the transaction review layer and may increase operational risk in case of calldata manipulation or wallet compromise. Recommended only for advanced automated environments with appropriate security controls. Direct execution currently supports same-chain batch payouts only. For example, Ethereum-to-Ethereum payouts require execution directly on Ethereum. To execute payouts across multiple chains, operators must execute one transaction per chain and interact with the corresponding contract deployment on each network individually. POST /v2/payouts/batch accepts up to 200 payment requests. All must be on the same EVM network. Mixed payment types (ERC-20 + native) are allowed within the batch.
const response = await fetch(
  "https://api.request.network/v2/payouts/batch",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-client-id": process.env.RN_CLIENT_ID!,
    },
    body: JSON.stringify({
      requests: [
        {
          payee: "0xb07d2398d2004378cad234da0ef14f1c94a530e4",
          amount: "50",
          invoiceCurrency: "USD",
          paymentCurrency: "USDC-base",
        },
        {
          payee: "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7",
          amount: "75",
          invoiceCurrency: "USD",
          paymentCurrency: "USDC-base",
        },
        // ...up to 200 recipients
      ],
      payer: process.env.PAYOUT_WALLET!,
    }),
  },
);

const { ERC20ApprovalTransactions, batchPaymentTransaction } =
  await response.json();
The response contains:
  • ERC20ApprovalTransactions[] — zero or more approval transactions you must broadcast first (one per token)
  • batchPaymentTransaction — the single transaction that settles all payments at once
Sign and broadcast in order. If the wallet already has sufficient allowance, the approvals array is empty.
import { ethers } from "ethers";

const signer = wallet.connect(provider);

for (const approvalTx of ERC20ApprovalTransactions) {
  const tx = await signer.sendTransaction(approvalTx);
  await tx.wait();
}

const batchTx = await signer.sendTransaction(batchPaymentTransaction);
await batchTx.wait();

Wallet infrastructure compatibility

At the moment, the Secure Payment Page and Dashboard are not compatible with Safe multisigs.For corporate treasury management and operational wallet infrastructure, we recommend using vault providers such as Utila, DFNS, or Fireblocks. Request Network is fully compatible with WalletConnect-based wallet infrastructure.

Real-world examples

Marketplace seller payouts

// Pay every seller their week's earnings in one tx
const sellers = await db.sellers.findWithUnpaidBalance();

await fetch("https://api.request.network/v2/payouts/batch", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-client-id": clientId },
  body: JSON.stringify({
    requests: sellers.map((s) => ({
      payee: s.walletAddress,
      amount: s.balanceUsdc.toString(),
      invoiceCurrency: "USD",
      paymentCurrency: "USDC-base",
    })),
    payer: marketplaceWallet,
  }),
});

Refund campaign

// Refund 30 customers from a botched promo
await fetch("https://api.request.network/v2/payouts/batch", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-client-id": clientId },
  body: JSON.stringify({
    requests: refundList.map((r) => ({
      payee: r.walletAddress,
      amount: r.refundAmount,
      invoiceCurrency: "USD",
      paymentCurrency: "USDC-arbitrum-one",
    })),
    payer: refundWallet,
  }),
});

Contractor payroll

// Run end-of-month payroll for the team
await fetch("https://api.request.network/v2/payouts/batch", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-client-id": clientId },
  body: JSON.stringify({
    requests: contractors.map((c) => ({
      payee: c.walletAddress,
      amount: c.monthlyRate.toString(),
      invoiceCurrency: "USD",
      paymentCurrency: "USDC-optimism",
    })),
    payer: payrollWallet,
  }),
});

Webhook events

Each request inside the batch produces its own payment.confirmed event when settled. For a batch of 50, expect 50 webhook deliveries — each carries its own requestId and paymentReference. Use the reference you set on creation (e.g. "payroll-2026-04") to group them on your side. See Webhook reconciliation for the full handler pattern.

Limits

  • Up to 200 recipients per batch transaction, depending on payment type complexity
  • Same network only — all requests[] must target the same chain. No mixing Base + Arbitrum in one batch.
  • EVM only — see warning at top
  • Mixed currency types within a network are OK — ERC-20 + native ETH/MATIC/BNB in one batch is supported

Payouts feature reference

Single, batch, and recurring payout endpoints.

Webhook reconciliation

Wire batch confirmations into your accounting / DB.