Skip to main content

Overview

The Bulk Payout API sends NGN to multiple Nigerian bank accounts from one CSV file. A batch can be funded by your permanent master NGN wallet or by a subaccount wallet owned by your business. FossaPay validates the complete request, confirms that the selected wallet can cover the recipient amounts and fees, and submits the batch for immediate processing.
Bulk payouts currently support IMMEDIATE execution only. To run payouts on a schedule, call the create endpoint from your own scheduler or cron job at the required time.

Processing model

  1. FossaPay authenticates the production API key and verifies the business.
  2. The source accountNumber is checked against the merchant’s master wallet and subaccounts.
  3. Every CSV row and bank name is validated.
  4. The configured NGN payout fee is calculated independently for every row.
  5. FossaPay verifies that the source available balance covers totalAmount + totalFee.
  6. The batch is submitted for immediate processing and returned as processing.
  7. A signed terminal webhook, or a later status reconciliation, changes the batch to completed or failed.
Batch execution is all-or-nothing. Do not treat an HTTP 202 response or an approvalStatus as proof that recipients were paid.

Prerequisites

  • A verified FossaPay business
  • An active production API key with full permission
  • A permanent master NGN wallet or an active subaccount owned by the authenticated business
  • Enough available balance for all recipient amounts and all per-item fees
  • A webhook endpoint configured with your webhook secret
  • A UTF-8 .csv file containing at least one recipient

Prepare the CSV

The first row must contain these four headers. Header matching is case-insensitive, but using the names exactly as shown is recommended.
The required header must be the first non-empty row. Files with spreadsheet column labels such as A,B,C,D above the header are invalid. Fields must be comma-separated; semicolon- and tab-delimited exports are not accepted. Quoted CSV fields and both LF and CRLF line endings are supported. Do not upload an Excel workbook, JSON file, or renamed non-CSV file. FossaPay does not impose an explicit recipient-count limit, but the HTTP request-size limit still applies.
Retrieve the current bank directory from GET /api/v1/transfers/fiat/supported-banks before generating the file.

Create a batch

Create one globally unique batchReference and one X-Idempotency-Key for the logical batch. Send the request as multipart/form-data; let your HTTP client generate the multipart boundary.
The source account must belong to the business identified by the API key. A wallet belonging to another business is rejected before any funds move. The endpoint returns HTTP 202 after submission:
Persist id, reference, and the idempotency key. totalDebit is the aggregate recipient amount plus the fee calculated for each row.

Idempotency and retries

  • Retrying the identical fields and identical CSV bytes with the same idempotency key returns the existing batch without funding it again.
  • Reusing that key with different fields or file contents returns HTTP 409.
  • batchReference is globally unique across FossaPay batches, not only within one merchant.
  • If the create request times out, retry the exact multipart request with the original key and original file. Do not generate a new key or reference.
  • Keep the original CSV bytes available until the request is resolved; even a harmless file edit changes the request hash.

Retrieve and reconcile

Use the FossaPay batch id returned by the create endpoint:
The recipients endpoint reports row-level validation results when they are available. Updating or deleting submitted rows is not currently exposed by the FossaPay API; correct the source data and contact support before attempting a replacement batch.

Status fields

Only completed is a successful terminal state. An uncertain processing result remains non-terminal while FossaPay reconciles it, preventing duplicate payouts.

Webhooks

FossaPay sends one of these terminal events:
  • payout.batch.completed
  • payout.batch.failed
Verify the x-fossapay-signature, deduplicate by eventId, acknowledge with HTTP 2xx, and update your batch using data.batchId or data.batchReference. See Webhook Events.

Schedule batches from your system

The API does not store future schedules. Your application can provide scheduled or recurring payouts by invoking the immediate endpoint from a durable job scheduler. For every intended run:
  1. Build and validate the CSV.
  2. Generate a new globally unique batch reference.
  3. Generate and persist one idempotency key.
  4. Submit the immediate batch once.
  5. After a timeout, retry the exact request with the same file, reference, and key.
  6. Track the terminal webhook and poll the status endpoint as a reconciliation fallback.
Protect the job with a database uniqueness constraint or distributed lock so two workers cannot create separate logical batches for the same schedule occurrence.

Error handling

Go-live checklist

  • Use only an active full-permission production API key.
  • Confirm the source account belongs to the authenticated business.
  • Generate bank names from the supported-bank directory.
  • Validate every account number, amount, and narration before upload.
  • Store the exact CSV bytes, globally unique reference, and idempotency key.
  • Ensure the available balance covers totalAmount + totalFee.
  • Treat HTTP 202 and processing as non-terminal.
  • Verify webhook signatures and deduplicate eventId values.
  • Reconcile delayed webhooks through the status endpoint.
  • Prevent overlapping scheduler executions for the same logical run.

API reference

Create Batch

Upload and submit an immediate CSV batch

List Batches

Review previous bulk payouts

Get Batch

Retrieve one batch

Get Recipients

Inspect every recipient row

Get Status

Reconcile processing state

Webhook Events

Handle terminal batch events