Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.kotanipay.com/llms.txt

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

A settlement moves your Kotani Pay balance to an external account — a bank account, mobile money wallet, or crypto address. This guide covers the full lifecycle from submission to completion, including batch and merge patterns, the PAUSED state, and the webhook events fired at each transition.

Before You Start

  • An API key — see API Keys
  • A fiat wallet with a deposit or payout balance to settle from
  • A beneficiary destination — either inline beneficiaryDetails or a saved beneficiary
  • A callbackUrl on your server if you want programmatic status notifications

Settlement Lifecycle

PENDING → UNDER_REVIEW → APPROVED → PROCESSED

Active States

StateDescription
PENDINGRequest submitted and awaiting review. The only state in which you can cancel.
UNDER_REVIEWA Kotani Pay agent has picked up the request for manual review.
APPROVEDReview passed. Funds are being disbursed to the destination account.
PAUSEDAn admin has paused the settlement pending additional information or due to a compliance hold — see PAUSED State.

Terminal States

StateDescription
PROCESSEDFunds have been delivered. The settlement is complete.
REJECTEDReview failed. Not approved. The reason is recorded on the settlement record.
CANCELLEDCancelled by the integrator before review began. Only possible from PENDING.
FAILEDAn error occurred during disbursement after approval. Contact support with the settlement ID.
REVERSEDDisbursement was sent but subsequently reversed. Contact support to confirm balance treatment.
Stop polling once a settlement reaches a terminal state. Use the callbackUrl or configure notification preferences to receive status-change events instead.

PAUSED State

An admin can pause a settlement at any point before PROCESSED. When paused:
  • pauseReason on the settlement record explains why it was paused
  • pausedUntil indicates when the system will automatically resume the settlement (if set)
  • A settlement.paused webhook fires immediately — see Webhook Events
The settlement resumes automatically on pausedUntil if set. Otherwise it resumes when the admin lifts the hold. Check your registered notification email or Slack channel for context from the Kotani Pay team.

Checking the Schedule

Call GET /api/v3/integrator/settlements/schedule before submitting to confirm settlements are open and your amount is within limits. Key fields:
  • enabled — if false, requests will be rejected
  • allowedDays — requests on unlisted days are queued to the next allowed day
  • cutoffEnabled / cutoffTime / timezone — requests after the cutoff are queued to the next allowed day
  • minAmount / maxAmount — both in USD; your local-currency amount is converted before this check

Previewing Fees

Call GET /api/v3/integrator/settlements/fee-preview with ?amount=&walletId= before submitting. The response shows the fee, net amount, and USD-equivalent values used for limit checking.

Single Settlement Flow

1. Check the schedule — confirm settlements are enabled and your amount is within minAmount/maxAmount. 2. Preview the fee — confirm the net amount is acceptable. 3. Submit — call POST /api/v3/integrator/settlements. The response includes the settlement ID and initial status PENDING. 4. Wait for review — status moves to UNDER_REVIEW then APPROVED. 5. Funds disbursed — status moves to PROCESSED once funds reach your destination. 6. You are notified — via callbackUrl or notification preferences at each status transition.

Batch Settlement Flow

Batch settlements submit multiple wallet requests in one call. Each child settlement is processed independently. The batch status reflects the aggregate of its children. 1. Prepare your requests array — each item follows the same schema as a single settlement request: walletId, amount, balanceSource, plus beneficiaryDetails or savedBeneficiaryId. 2. Submit the batch — call POST /api/v3/integrator/settlements/batch with an optional batchReference for your own tracking. 3. Track the batch — call GET /api/v3/integrator/settlements/batch/:batchId for the overall status. Each child can also be fetched individually via GET /api/v3/integrator/settlements/:id. 4. Cancelling — call DELETE /api/v3/integrator/settlements/batch/:batchId. Children still in PENDING are cancelled; children in UNDER_REVIEW or later are not affected.

Batch Status at Completion

ConditionWebhook fired
All children PROCESSEDsettlement.batch.processed
All children REJECTEDsettlement.batch.rejected
Mix of PROCESSED and REJECTED/FAILEDsettlement.batch.partial
Batch cancelledsettlement.batch.cancelled
Batch approved by adminsettlement.batch.approved

Merge Flow

The merge endpoint converts two or more existing individual settlements into a batch after the fact. 1. Identify settlements to merge — all must be PENDING or UNDER_REVIEW and not already in a batch. 2. Submit the merge — call POST /api/v3/integrator/settlements/merge with the settlementIds array (minimum 2). 3. A new batch is created — the response contains the new batch ID. The source settlements become children of that batch.
You cannot un-merge settlements once grouped into a batch. To cancel, use DELETE /api/v3/integrator/settlements/batch/:batchId.

Webhook Events

Settlement events are delivered via the signed webhook system — see Webhook Notifications for verification and retry details.
EventWhen it fires
settlement.approvedSettlement moves to APPROVED
settlement.rejectedSettlement is REJECTED after review
settlement.processedSettlement reaches PROCESSED — funds delivered
settlement.cancelledSettlement cancelled by integrator
settlement.pausedAdmin pauses the settlement
settlement.batch.approvedBatch approved by admin
settlement.batch.rejectedAll children in a batch are REJECTED
settlement.batch.processedAll children in a batch reach PROCESSED
settlement.batch.partialSome children PROCESSED, others REJECTED or FAILED
settlement.batch.cancelledBatch cancelled by integrator

Example: settlement.paused

{
  "event": "settlement.paused",
  "data": {
    "settlementId": "stl_abc123",
    "status": "PAUSED",
    "pauseReason": "Additional KYC documentation required for this destination",
    "pausedUntil": "2025-05-10T00:00:00.000Z",
    "currency": "KES",
    "amount": 50000
  },
  "signature": "sha256=a1b2c3..."
}

Example: settlement.batch.partial

{
  "event": "settlement.batch.partial",
  "data": {
    "batchId": "bat_def789",
    "processedCount": 3,
    "rejectedCount": 1,
    "failedCount": 0,
    "totalCount": 4
  },
  "signature": "sha256=b2c3d4..."
}

Saved Beneficiaries

Store destination details once and reference by ID on any settlement or batch request.
  1. Create — POST /api/v3/integrator/settlement-config/beneficiaries
  2. Use savedBeneficiaryId in your settlement or batch request
  3. Update — PATCH /api/v3/integrator/settlement-config/beneficiaries/:id
  4. Delete — DELETE /api/v3/integrator/settlement-config/beneficiaries/:id

Notification Preferences

Configure email and Slack notifications via PATCH /api/v3/integrator/settlements/notification-preferences. These supplement signed webhook delivery and are intended for human awareness rather than programmatic integration.

Dashboard Settlements API

Full parameter reference for all settlement endpoints

Webhook Notifications

Signed webhooks, verification, and retry behaviour

Balances & Settlement

Deposit vs payout balances

Transaction Statuses

All status codes across the API