> ## Documentation Index
> Fetch the complete documentation index at: https://requestnetwork-feat-tron-sponsored-tx-doc.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Batch payouts (EVM)

> Pay many recipients in one signed transaction. Marketplaces paying vendors, agencies paying contractors, refund campaigns, payroll-adjacent flows.

## What you'll build

A workflow for paying many recipients at once with a single payer signature — 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.

<Warning>
  **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`](/api-features/payouts) or [`POST /v2/secure-payments/payouts`](/api-reference/secure-payments#post-v2secure-paymentspayouts).
</Warning>

## Two modes

| Mode                                | Endpoint                                                                                | What you get back                                                                     |
| ----------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| **Hosted Batch Link** (recommended) | [`POST /v2/secure-payments`](/api-reference/secure-payments) with multiple `requests[]` | A `pay.request.network` URL the payer opens, signs once, and pays everyone            |
| **Direct Execution** (advanced)     | [`POST /v2/payouts/batch`](/api-features/payouts#batch-payout)                          | Approval 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.

<Tip>
  **Bundling payouts across chains or on Tron?** [Multicall payouts](/api-features/payouts#multicall-payouts) combine multiple existing payout links into one link with cross-chain (Li.Fi) routing or Tron batch execution — a separate mechanism from the same-network batch endpoints below. See the [Secure Payments reference](/api-reference/secure-payments#post-v2secure-paymentsmulticall-payouts).
</Tip>

## Prerequisites

Same as the [Quickstart](/use-cases/quickstart) — you need a Client ID. Webhooks are optional but recommended so you get notified when each leg of the batch settles.

## Mode 1 — Hosted Batch Link (Recommended & Safer Approach)

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:

```typescript theme={null}
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.

```typescript theme={null}
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.

```typescript theme={null}
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

<Note>
  The hosted Secure Payment Page and Dashboard execute through the payer's connected wallet (including an automatic [smart account](/api-features/secure-payment-pages#smart-account-payments) on supported EVM chains), so you cannot connect an existing Gnosis Safe multisig directly in the UI.

  To pay from a Safe multisig, use the API: request Safe-ready calldata and track settlement with the [Safe multisig payments](/api-features/safe-multisig-payments) flow, executing the transaction on your own Safe. For broader corporate treasury and operational wallet infrastructure, Request Network is also compatible with WalletConnect-based vault providers such as Utila, DFNS, or Fireblocks.
</Note>

## Real-world examples

### Marketplace seller payouts

```typescript theme={null}
// 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

```typescript theme={null}
// 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

```typescript theme={null}
// 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](/use-cases/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

## Related

<CardGroup cols={2}>
  <Card title="Payouts feature reference" href="/api-features/payouts" icon="paper-plane">
    Single, batch, and recurring payout endpoints.
  </Card>

  <Card title="Webhook reconciliation" href="/use-cases/webhook-reconciliation" icon="webhook">
    Wire batch confirmations into your accounting / DB.
  </Card>
</CardGroup>
