<!-- ZenPays documentation · https://docs.zenpays.com/docs/rest-api/endpoints/payouts/batch-payout-upload -->

# Upload Batch Payout

Upload multiple payouts in a single API call using a CSV or Excel file. Use [Batch Payout Template](/docs/rest-api/endpoints/payouts/batch-payout-template) to get the correct column headers and field definitions before building your file.

<EndpointHeader verb="POST" path="/payment/api/v1/batch-payouts/upload" />

## Request

### Headers

<ParamTable
  label="Header"
  rows={[
    { name: "Authorization", required: true, desc: "`Bearer {api_key}`" },
    { name: "X-Signature", required: true, desc: "HMAC-SHA256 signature" },
    { name: "X-Timestamp", required: true, desc: "ISO 8601 timestamp" },
    { name: "X-Secret-Salt", required: true, desc: "Secret salt for HMAC validation" },
    { name: "X-Merchant-Id", required: true, desc: "Your merchant ID" },
    { name: "X-Request-Id", desc: "Idempotency key for the request" },
    { name: "Content-Type", required: true, desc: "`multipart/form-data`" },
  ]}
/>

### Body Parameters

<ParamTable
  rows={[
    { name: "file", type: "File", required: true, desc: "CSV or Excel file (max 5MB). Accepted: `.csv`, `.xlsx`, `.xls`" },
    { name: "webhookUrl", type: "string", desc: "URL for batch status webhooks" },
  ]}
/>

## Response

### Success (200 OK)

```json
{
  "success": true,
  "data": {
    "batch_id": "batch_1774867295648_06f4074d",
    "total_payouts": 5,
    "total_amount": 50000,
    "currency": "INR",
    "estimated_fees": 125,
    "status": "validated",
    "message": "Batch payout uploaded and validated successfully",
    "preview_data": [
      {
        "row_number": 1,
        "customer_email": "rajesh@example.com",
        "beneficiary_name": "Rajesh Kumar",
        "amount": 10000,
        "currency": "INR",
        "payout_type": "IMPS",
        "beneficiary_account": "1234567890"
      }
    ],
    "validation_errors": []
  }
}
```

### Response Fields

<ParamTable
  rows={[
    { name: "batch_id", type: "string", desc: "Unique identifier for the batch" },
    { name: "total_payouts", type: "number", desc: "Number of payout rows parsed" },
    { name: "total_amount", type: "number", desc: "Sum of all payout amounts" },
    { name: "currency", type: "string", desc: "Currency code from the file" },
    { name: "estimated_fees", type: "number", desc: "Estimated processing fees" },
    { name: "status", type: "string", desc: "Batch status after upload (`validated`)" },
    { name: "message", type: "string", desc: "Human-readable status message" },
    { name: "preview_data", type: "array", desc: "Preview of the first rows in the batch" },
    { name: "validation_errors", type: "array", desc: "Per-row validation errors (empty when all rows pass)" },
  ]}
/>

:::note
After upload, the batch is in `validated` status. You must call [Confirm Batch Payout](/docs/rest-api/endpoints/payouts/confirm-batch-payout) to start processing.
:::

### Error Responses

<ErrorTable
  rows={[
    { code: "MISSING_FILE", status: "400", message: "No file uploaded" },
    { code: "BATCH_UPLOAD_FAILED", status: "400", message: "File parsing or validation failed" },
    { code: "UNAUTHORIZED", status: "401", message: "Invalid API key" },
  ]}
/>

<CodeRail>

## Examples

<Tabs groupId="language">
  <TabItem value="curl" label="cURL" default>

```bash
curl -X POST "https://api.zenpays.com/payment/api/v1/batch-payouts/upload" \
  -H "Authorization: Bearer zp_test_xxxxx" \
  -H "X-Timestamp: 2024-01-15T10:30:00.000Z" \
  -H "X-Signature: a1b2c3d4e5f6..." \
  -H "X-Secret-Salt: your_secret_salt" \
  -H "X-Merchant-Id: ZP_FIN_xxxxx" \
  -H "X-Request-Id: req_unique_id" \
  -F "file=@batch-payouts.csv" \
  -F "webhookUrl=https://your-server.com/webhooks/batch-payout"
```

  </TabItem>
  <TabItem value="sdk" label="SDK (Recommended)">

```typescript
const result = await zenpays.payouts.uploadBatch({
  filePath: './batch-payouts.csv',
  webhookUrl: 'https://your-server.com/webhooks/batch-payout',
});

console.log(`Batch ID: ${result.batch_id}`);
console.log(`Total payouts: ${result.total_payouts}`);
console.log(`Total amount: ${result.total_amount} ${result.currency}`);
console.log(`Estimated fees: ${result.estimated_fees}`);

if (result.validation_errors.length > 0) {
  console.error('Validation errors:', result.validation_errors);
} else {
  // Confirm the batch to start processing
  await zenpays.payouts.confirmBatch(result.batch_id);
}
```

  </TabItem>
  <TabItem value="javascript" label="JavaScript">

```javascript
const timestamp = new Date().toISOString();
const signature = crypto
  .createHmac('sha256', secretSalt)
  .update(timestamp)
  .digest('hex');

const formData = new FormData();
formData.append('file', fs.createReadStream('./batch-payouts.csv'));
formData.append('webhookUrl', 'https://your-server.com/webhooks/batch-payout');

const response = await fetch(
  'https://api.zenpays.com/payment/api/v1/batch-payouts/upload',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'X-Timestamp': timestamp,
      'X-Signature': signature,
      'X-Secret-Salt': secretSalt,
      'X-Merchant-Id': merchantId,
      'X-Request-Id': `req_${Date.now()}`,
    },
    body: formData,
  }
);

const { data } = await response.json();
console.log(`Batch ${data.batch_id}: ${data.total_payouts} payouts, ${data.status}`);
```

  </TabItem>
</Tabs>

</CodeRail>

## Related Endpoints

- [Batch Payout Template](/docs/rest-api/endpoints/payouts/batch-payout-template) — Get column definitions and sample CSV
- [Create Batch Payout](/docs/rest-api/endpoints/payouts/create-batch-payout) — Create a batch payout via JSON
- [Confirm Batch Payout](/docs/rest-api/endpoints/payouts/confirm-batch-payout) — Confirm and start processing a batch
- [Get Batch Payout](/docs/rest-api/endpoints/payouts/get-batch-payout) — Check batch status
