1. Bank Cashout
Nilpay
  • NilPay Bank Integration API
    • Custody Bank Deposit
      • Integration Guide
      • Initiate deposit transaction
      • Complete deposit transaction
    • Bank Cashout
      • Integration Guide
      • Inquiry for bank cashout
        POST
      • Initiate bank cashout
        POST
      • Complete bank cashout with OTP
        POST
    • Schemas
      • InitiateDepositRequest
      • BankCashoutInquiryRequest
      • CompleteDepositRequest
      • BankCashoutInitiateRequest
      • BankCashoutCompleteRequest
      • Depositor
      • BankCashoutInquirySuccessResponse
      • InitiateDepositSuccessResponse
      • ChargeResponse
      • BankCashoutInitiateSuccessResponse
      • AccountBasicInfo
      • BankCashoutCompleteSuccessResponse
      • CompleteDepositSuccessResponse
      • WalletBasicInfo
      • ErrorResponse
      • ValidationErrorResponse
      • TransactionResponse
      • ProblemDetailsResponse
  • NilPay External Party Transfer API
    • Transactions
      • Integration Guide
      • External Party Transfer To Wallet
    • Schemas
      • ExternalPartyTransferRequest
      • TransactionResponseData
      • ExternalPartyTransferSuccessResponse
      • ErrorResponse
  1. Bank Cashout

Integration Guide

1) Getting Started#

Overview#

This guide explains how partner banks integrate with NilPay Bank Cashout APIs using a 3-phase flow:
1.
POST /v1/transactions/bank-cashout/inquiry
2.
POST /v1/transactions/bank-cashout/initiate
3.
POST /v1/transactions/bank-cashout/complete

Base URL#

https://api.dev.pynil.com

Version Prefix#

All routes start with /v1.

2) Authentication and Security#

All requests require:
Authorization: Basic <BASE64(username:password)>
X-Signature: <HMAC_SHA256_UPPERCASE_HEX>
X-Timestamp: <UNIX_TIMESTAMP_SECONDS>
Content-Type: application/json

HMAC Payload (Current Implementation)#

Use this exact payload format:
HTTP_METHOD + "\n" + REQUEST_PATH + "\n" + UNIX_TIMESTAMP
Example request path:
/v1/transactions/bank-cashout/inquiry

Security Rules#

Timestamp tolerance: 5 minutes.
Replay protection is validated using timestamp + signature.
Signature comparison is case-insensitive, but use uppercase hex in clients.
HMAC secret is resolved from authenticated bank user (with optional system fallback).

3) Endpoint: Inquiry#

URL#

POST /v1/transactions/bank-cashout/inquiry

Purpose#

Validates wallet status and balance, then returns applicable charges and total fees.

Request Body#

{
  "walletNumber": "101000001",
  "amount": 100,
  "timestamp": "2026-01-08",
  "notes": "Test request"
}

Request Notes#

Required fields: walletNumber, amount
Optional fields: timestamp, notes

Success Response (200)#

{
  "success": true,
  "message": "Success.",
  "statusCode": 200,
  "data": {
    "wallet": {
      "branchCode": "MAIN",
      "currencyCode": "SDG",
      "walletName": "Marwa Omar",
      "status": "Active"
    },
    "charges": [
      {
        "name": "Custody Cashout",
        "amount": 20.0
      }
    ],
    "totalFees": 20.0
  }
}

Common Errors#

400: validation error or Insufficient funds
404: Wallet account not found

4) Endpoint: Initiate#

URL#

POST /v1/transactions/bank-cashout/initiate

Purpose#

Creates pending cashout transactions and sends OTP to customer.

Request Body#

{
  "walletNumber": "101000001",
  "amount": 100,
  "timestamp": "2026-01-08",
  "notes": "Test request"
}

Request Notes#

Required fields: walletNumber, amount
Optional fields: timestamp, notes

Success Response (200)#

{
  "success": true,
  "message": "OTP sent successfully",
  "statusCode": 200,
  "data": {
    "nilpayTranRef": "333"
  }
}

Common Errors#

Same categories as inquiry (400/404/500) plus OTP delivery failures.

5) Endpoint: Complete#

URL#

POST /v1/transactions/bank-cashout/complete

Purpose#

Verifies OTP and completes pending transaction set.

Request Body#

{
  "transactionRef": "333",
  "otp": "1632",
  "bankReference": "BANK-41128"
}

Request Notes#

Required fields: transactionRef, otp, bankReference
otp must be exactly 4 digits.
bankReference max length is 100 chars.

Success Response (200)#

{
  "success": true,
  "message": "Transaction was Completed successfully.",
  "statusCode": 200,
  "data": {
    "transactionId": "333-1",
    "reference": 333,
    "date": "2026-02-03",
    "direction": "Debit",
    "amount": 100.0,
    "description": "Bank Cashout - Marwa Omar"
  }
}

Common Errors#

{
  "success": false,
  "message": "The transaction has already been completed",
  "statusCode": 400,
  "data": null
}
{
  "success": false,
  "message": "Invalid or Wrong OTP",
  "statusCode": 400,
  "data": null
}
{
  "success": false,
  "message": "OTP has expired, please request a new one",
  "statusCode": 400,
  "data": null
}
{
  "success": false,
  "message": "The transaction was not found",
  "statusCode": 404,
  "data": null
}

6) Authentication Error Example (401)#

401 from HMAC/auth filters returns ProblemDetails style:
{
  "type": "about:blank",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Invalid signature"
}

7) Error Codes#

HTTP CodeError TypeDescriptionAction Required
400Validation / Business Rule ErrorInvalid request, insufficient funds, OTP or state errorsFix request/OTP/state and retry
401Authentication FailedInvalid Basic Auth, signature, timestamp, or replay validationVerify credentials, signature payload, and timestamp
404Not FoundWallet, bank wallet, or transaction not foundVerify identifiers
500Internal Server ErrorUnrecoverable server errorRetry later and contact support if persistent

8) cURL Example (Inquiry)#


9) cURL Example (Initiate)#


10) cURL Example (Complete)#

Previous
Complete deposit transaction
Next
Inquiry for bank cashout
Built with