Skip to main content

Overview

Kotani Pay uses a comprehensive set of status codes to track the lifecycle of different transaction types. Understanding these statuses is crucial for building robust integrations and handling transaction states correctly.

Status Categories

Terminal Statuses

Terminal statuses indicate that a transaction has reached its final state and will not change further. You should stop polling for updates once a transaction reaches a terminal status. Terminal statuses include:
  • SUCCESSFUL / SUCCESS
  • FAILED
  • CANCELLED
  • EXPIRED
  • DECLINED
  • PERMANENTLY_FAILED
  • REVERSED

Intermediate Statuses

Intermediate statuses indicate that a transaction is still being processed. You should continue polling or wait for webhooks when a transaction is in an intermediate status. Intermediate statuses include:
  • PENDING
  • INITIATED
  • IN_PROGRESS
  • PROCESSING
  • RETRY

Special Statuses

Special statuses are used for specific scenarios:
  • DUPLICATE - Transaction is a duplicate of an existing one
  • ERROR_OCCURRED - An error occurred during processing
  • REQUIRE_REVIEW - Transaction requires manual review
  • NOT_INITIATED - Transaction has not been initiated yet

Deposit Transaction Statuses

Used for mobile money deposits, bank deposits, and card deposits.
PENDING
string
Initial status. Payment request has been created but not yet sent to the provider.
INITIATED
string
Payment request has been sent to the provider and is awaiting customer action.
IN_PROGRESS
string
Customer has initiated payment and it’s being processed by the provider.
SUCCESSFUL
string
Terminal Status - Payment completed successfully. Funds have been credited to your fiat wallet.
SUCCESS
string
Terminal Status - Alternative success status used by some providers.
FAILED
string
Terminal Status - Payment failed. Common reasons include insufficient funds, network errors, or provider issues.
EXPIRED
string
Terminal Status - Payment request expired before customer completed payment (typically 30 minutes timeout).
CANCELLED
string
Terminal Status - Payment was cancelled by customer or system.
DECLINED
string
Terminal Status - Payment was declined by the provider or payment network.
REVERSED
string
Terminal Status - Payment was reversed/refunded.
DUPLICATE
string
Duplicate transaction detected (same reference ID already exists).
ERROR_OCCURRED
string
An unexpected error occurred during processing.
REQUIRE_REVIEW
string
Transaction flagged for manual review.
RETRY
string
Transaction is being retried after a temporary failure.
PERMANENTLY_FAILED
string
Terminal Status - Transaction failed permanently after all retry attempts exhausted.

Withdrawal Transaction Statuses

Used for mobile money withdrawals and bank withdrawals.
NOT_INITIATED
string
Withdrawal request created but not yet sent to provider.
PENDING
string
Withdrawal request queued for processing.
INITIATED
string
Withdrawal request sent to provider.
TRANSACTION_INITIATED
string
Provider has initiated the withdrawal transaction.
IN_PROGRESS
string
Withdrawal is being processed by the provider.
SUCCESSFUL
string
Terminal Status - Withdrawal completed successfully. Funds have been sent to the recipient.
FAILED
string
Terminal Status - Withdrawal failed.
CANCELLED
string
Terminal Status - Withdrawal was cancelled.
DECLINED
string
Terminal Status - Withdrawal was declined by provider.
EXPIRED
string
Terminal Status - Withdrawal request expired.
REVERSED
string
Terminal Status - Withdrawal was reversed.
ERROR_OCCURRED
string
An error occurred during withdrawal processing.
REQUIRE_REVIEW
string
Withdrawal requires manual review.
RETRY
string
Withdrawal is being retried.
TRANSACTION_RETRY
string
Provider is retrying the withdrawal transaction.
TRANSACTION_RETRY_SUCCESSFUL
string
Terminal Status - Retry attempt was successful.
TRANSACTION_RETRY_FAILED
string
Terminal Status - Retry attempt failed.

Onramp Transaction Statuses

Onramp transactions use two separate status fields:

depositStatus

Tracks the fiat payment status (mobile money/bank deposit). Uses the same statuses as Deposit Transaction Statuses.

onchainStatus

Tracks the crypto transfer status (sending crypto to external wallet).
PENDING
string
Crypto transfer is pending. Waiting for deposit to complete first.
IN_PROGRESS
string
Crypto transfer is being processed on the blockchain.
SUCCESSFUL
string
Terminal Status - Crypto successfully sent to recipient address. Transaction hash available.
FAILED
string
Terminal Status - Crypto transfer failed.
CANCELLED
string
Terminal Status - Crypto transfer cancelled (usually because deposit failed).

Used for payment link transactions.
pending
string
Payment link created but no payment attempted yet.
processing
string
Customer is completing the payment.
successful
string
Terminal Status - Payment completed successfully.
failed
string
Terminal Status - Payment failed.
cancelled
string
Terminal Status - Payment cancelled by customer or expired.
expired
string
Terminal Status - Payment link expired before payment was completed.

Callback Statuses

Internal statuses tracking callback delivery to your webhook URL.
COMPLETED
number
default:"0"
Callback delivered successfully to your webhook.
PENDING
number
default:"1"
Callback waiting to be sent.
PROCESSING
number
default:"2"
Callback is being sent.
FAILED
number
default:"-1"
Callback delivery failed (will retry).
PERMANENTLY_FAILED
number
default:"-2"
Callback delivery permanently failed after all retries.

Best Practices

Stop polling when a transaction reaches any terminal status:
  • SUCCESSFUL / SUCCESS
  • FAILED
  • CANCELLED
  • EXPIRED
  • DECLINED
  • PERMANENTLY_FAILED
  • REVERSED
Different failure statuses indicate different scenarios:
  • FAILED - Temporary failure, user can retry creating a new transaction
  • DECLINED - Provider declined the transaction (insufficient funds, limits, etc.)
  • EXPIRED - Timeout, user can create a new transaction
  • CANCELLED - User or system cancelled, no action needed
  • PERMANENTLY_FAILED - Unrecoverable failure, investigate the error
Recommended: Use webhooks for real-time status updates instead of polling.Configure webhook URLs in your integration to receive automatic notifications when transaction statuses change.See Webhooks documentation for setup instructions.
For onramp transactions, monitor BOTH statuses:
  1. depositStatus - Tracks if customer paid (mobile money/bank)
  2. onchainStatus - Tracks if crypto was sent
Success criteria: BOTH must be SUCCESSFULCommon flow:
depositStatus: PENDING → INITIATED → SUCCESSFUL
onchainStatus: PENDING → IN_PROGRESS → SUCCESSFUL
When you receive ERROR_OCCURRED or REQUIRE_REVIEW:
  1. Check the error or errorMessage field in the response for details
  2. Log the full transaction details for support
  3. Contact support if the issue persists
  4. Do not retry automatically - these statuses often require manual intervention

Common Status Flows

Successful Deposit Flow

PENDING → INITIATED → IN_PROGRESS → SUCCESSFUL

Failed Deposit Flow

PENDING → INITIATED → FAILED

Expired Deposit Flow

PENDING → INITIATED → EXPIRED

Successful Withdrawal Flow

NOT_INITIATED → PENDING → INITIATED → IN_PROGRESS → SUCCESSFUL

Successful Onramp Flow

Deposit:  PENDING → INITIATED → SUCCESSFUL
Onchain:  PENDING → IN_PROGRESS → SUCCESSFUL

Failed Onramp Flow (Deposit Fails)

Deposit:  PENDING → INITIATED → FAILED
Onchain:  PENDING → CANCELLED

Failed Onramp Flow (Crypto Transfer Fails)

Deposit:  PENDING → INITIATED → SUCCESSFUL
Onchain:  PENDING → IN_PROGRESS → FAILED
Note: If deposit succeeds but crypto transfer fails, your fiat wallet is still credited. The crypto transfer will be automatically retried or can be manually retried via support.