# A Developer’s Guide to Batch Payouts Using Request Network

Batch payouts are a common requirement in payroll systems, treasury tools, creator payouts, and automated on-chain settlement pipelines. Instead of sending multiple independent ERC-20 transfers which is slow, expensive, Request Network provides a **single API call** that returns:

* ERC-20 **approval transactions** (if needed)
    
* a **batch payment transaction** containing pre-encoded calldata
    
* all the metadata required to execute the batch atomically on-chain
    

---

## Prerequisites

Before writing code, make sure you have:

* **Node.js** (&gt;= 18 recommended)
    
* A funded **Sepolia wallet** holding FAU tokens (Token Address: `0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C`)
    
* Environment Variables:
    
    * `PRIVATE_KEY`: Payer’s Private Key
        
    * `API_KEY`: Request API Key
        

---

## Getting Your Request Network API Key

Request Network exposes its batch payout API behind an authenticated HTTP interface. To get your API key:

1. Visit: [**https://portal.request.network**](https://portal.request.network/?utm_source=chatgpt.com)
    
2. Create an account / log in
    
3. Create a new “API Key”
    
4. Copy the generated **API Key**
    
5. Store it securely (e.g., `.env` file)
    

```plaintext
API_KEY=your-request-network-api-key
PRIVATE_KEY=your-sepolia-private-key
```

Your API key is required for the `x-api-key` header in all API calls.

---

## Creating a Batch Payout

### Setup Provider + Wallet

To interact with Sepolia and later broadcast the approval and batch payment transactions, we first initilize a provider and wallet. The `JsonRpcProvider` connects your code to an Ethereum Sepolia RPC endpoint. Using your `PRIVATE_KEY`, we instantiate an Ethers.js `Wallet` that will sign and pay for all on-chain operations. The derived `payerAddress` is the account that Request Network will treat as the payer for the batch.

```typescript
const provider = new providers.JsonRpcProvider(
  "https://ethereum-sepolia-rpc.publicnode.com"
);
const payerWallet = new Wallet(process.env.PRIVATE_KEY as string, provider);

const payerAddress = payerWallet.address;
```

---

### **Prepare the Batch Requests**

Next we define a simple list of payout entries, each containing a recipient address and an amount. These entries represent the individual payments you want to include in the batch.

Later, each item is converted into the format the Request Network API expects, where both the invoice currency and the payment currency are set to `FAU-sepolia`. This means the payout will be settled entirely in FAU tokens on the Sepolia network.

```typescript
const requests = [
  { address: "0x00A2895816e64F152FF81c8A931DC1bd9F5c3ce3", amount: "10" },
  { address: "0xc0d86456F6f2930b892f3DAD007CDBE32c081FE6", amount: "10" },
  { address: "0xe269688F24e1C7487f649fC3dCD99A4Bf15bDaA1", amount: "10" },
];
```

---

### **Create the Batch Payout Request**

Next we sends a `POST` request to [`https://api.request.network/v2/payouts/batch`](https://api.request.network/v2/payouts/batch). Along with your API key in the header, the body includes the list of payout entries and the Ethereum address of the payer.

Request Network validates the batch, calculates total spending, and prepares all the on-chain steps required to settle this batch. This single API call returns everything you need to perform the payout on-chain without writing your own smart contract logic.

```typescript
const response = await fetch("https://api.request.network/v2/payouts/batch", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": process.env.API_KEY as string,
  },
  body: JSON.stringify({
    requests: requests.map((r) => ({
      payee: r.address,
      amount: r.amount,
      invoiceCurrency: "FAU-sepolia",
      paymentCurrency: "FAU-sepolia",
    })),
    payer: payerAddress,
  }),
});
```

---

### **Understanding the API Response**

The response contains two important elements:

1. `ERC20ApprovalTransactions`
    
2. `batchPaymentTransaction`
    

The approval transactions are optional and are only returned when your wallet does not have enough ERC-20 allowance set for Request Network’s batch contract. Each approval transaction is already encoded and ready to be broadcast.

The `batchPaymentTransaction` contains the calldata and contract address needed to process all payouts in one atomic on-chain operation. Essentially, the API produces all transaction objects for you, so your code only needs to sign and send them.

```typescript
const { batchPaymentTransaction, ERC20ApprovalTransactions } =
  await response.json();
```

---

### **Sending Required ERC-20 Approvals**

If approvals are required, the script loops through each approval transaction and broadcasts it directly through the payer’s wallet. These approval transactions use the standard ERC-20 `approve()` function to authorize Request Network’s batch contract to move FAU tokens on your behalf. Once an approval is confirmed, the allowance is updated on-chain, enabling the final batch payment to succeed.

```typescript
if (ERC20ApprovalTransactions.length > 0) {
  for (const tx of ERC20ApprovalTransactions) {
    const res = await payerWallet.sendTransaction(tx);
    await res.wait();
    console.log(res.hash);
  }
}
```

---

### **Executing the Batch Payment Transaction**

After any necessary approvals are completed, the script sends the main batch payment transaction. This transaction performs all payouts in one go, distributing FAU to each recipient based on the request list.

Once the transaction confirms, all recipients receive their payouts, and you get a single transaction hash representing the complete batch settlement.

```typescript
const res = await payerWallet.sendTransaction(batchPaymentTransaction);
await res.wait();

console.log(res.hash);
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1764522368030/02845bba-9663-444a-8395-a5ebbf88f776.png align="center")

## Full Code

```typescript
import type { TransactionRequest } from "@ethersproject/abstract-provider";
import { providers, Wallet } from "ethers";

const provider = new providers.JsonRpcProvider(
	"https://ethereum-sepolia-rpc.publicnode.com",
);
const payerWallet = new Wallet(process.env.PRIVATE_KEY as string, provider);

const payerAddress = payerWallet.address;

const requests: { address: string; amount: string }[] = [
	{
		address: "0x00A2895816e64F152FF81c8A931DC1bd9F5c3ce3",
		amount: "10",
	},
	{
		address: "0xc0d86456F6f2930b892f3DAD007CDBE32c081FE6",
		amount: "10",
	},
	{
		address: "0xe269688F24e1C7487f649fC3dCD99A4Bf15bDaA1",
		amount: "10",
	},
];

const response = await fetch("https://api.request.network/v2/payouts/batch", {
	method: "POST",
	headers: {
		"Content-Type": "application/json",
		"x-api-key": process.env.API_KEY as string,
	},
	body: JSON.stringify({
		requests: [
			...requests.map((r) => ({
				payee: r.address,
				amount: r.amount,
				invoiceCurrency: "FAU-sepolia",
				paymentCurrency: "FAU-sepolia",
			})),
		],
		payer: payerAddress,
	}),
});

const { batchPaymentTransaction, ERC20ApprovalTransactions } =
	(await response.json()) as {
		batchPaymentTransaction: TransactionRequest;
		ERC20ApprovalTransactions: TransactionRequest[];
	};

if (ERC20ApprovalTransactions.length > 0) {
	console.log(
		"Sending ERC20 approval transactions...",
		ERC20ApprovalTransactions.length,
	);
	for (const tx of ERC20ApprovalTransactions) {
		const res = await payerWallet.sendTransaction(tx);
		await res.wait();
		console.log(res.hash);
	}
}

const res = await payerWallet.sendTransaction(batchPaymentTransaction);
await res.wait();

console.log(res.hash);
```

---

## Conclusion

Batch payouts don’t need custom smart contracts or complicated encoding logic. By relying on Request Network’s batch payout API, you can automate multi-recipient payments with a single API call and one final on-chain transaction.

The API handles request creation, calldata generation, allowance validation, and transaction preparation, your code simply forwards the returned transaction objects.

With the code above, you now have a fully working end-to-end implementation. From fetching payout instructions to executing the final settlement on-chain, your system can now perform seamless mass payouts with minimal moving parts.

Happy shipping!
