Sign In

Merchant Ledger Entry

Create a debit or credit entry in a merchant's cash ledger.

POST/v1/route/ledger-entry

Creates a single entry in the merchant ledger and returns the resulting running balance. The request is authenticated with your API key and a per-request SHA-256 hash, exactly like the Transaction Status API — the key and hash travel in the request headers.

Authentication & Hash Generation

This endpoint is authenticated with your API key plus a per-request SHA-256 hash. Send the key in the X-API-Key header and the hash in the Hash header.

Hash formula

Hash = SHA256(key | amount | idempotency_key | salt), joined with the | character. idempotency_key is required. The salt is your merchant secret key — it is used only to compute the hash and must never be sent in the request. See the Authentication guide.

Hash the amount exactly as sent

Compute the hash using the amount string exactly as it appears in the request body (e.g. "1000.00"). A different string such as "1000.0" produces a different hash and fails validation.

Headers

HeaderTypeRequiredDescription
X-API-KeystringRequiredYour merchant API key.
HashstringRequiredSHA-256 auth hash — SHA256(key | amount | idempotency_key | salt).
Content-TypestringRequiredMust be application/json.

Request Parameters

Field NameData TypeRequiredDescriptionAllowed ValuesExample
amount Decimal Required Transaction amount in rupees (two-decimal precision). Included in the auth hash. Greater than 0, ≤ 13 digits 1000.00
ledger_type Integer Required Ledger entry direction. 1 = Debit, 2 = Credit 2
bank_transaction_id String Optional Optional bank transaction id. When supplied, it must be unique per merchant. ≤ 255 chars, unique per merchant BANKTXN1234567
bank_reference_number String Optional Bank reference number (e.g. UTR). ≤ 255 chars UTR1234567890
bank_narration String Optional Narration / description for the entry. NEFT credit from customer
value_date Date Optional Bank value date. Format YYYY-MM-DD 2026-07-13
transaction_date DateTime Optional Transaction date-time. ISO 8601 2026-07-13T22:20:00Z
customer_name String Optional Customer / counterparty name. Jane Doe
customer_account_number String Optional Customer account number. 1234567890
customer_bank_name String Optional Customer bank name. HDFC Bank
customer_ifsc String Optional Customer IFSC code. HDFC0000123
source String Optional Origin of the entry. Defaults to manual. transaction, email, manual, manual_cash, settlement, csv_import, swift manual
message_type String Optional Message type (e.g. NEFT / IMPS / RTGS). NEFT
idempotency_key String Required Key for safe retries — included in the auth hash. Must be unique per merchant; reusing one is rejected with 409. ≤ 128 chars, unique per merchant CRM-1
reference_type String Optional Business reference type stored on the entry. ≤ 64 chars MANUAL_CASH_ENTRY
reference_id String Optional Business reference id stored on the entry. ≤ 255 chars CRM-REF-1
remarks String Optional Free-text remarks / description stored on the entry. Cash received through merchant CRM
metadata Object Optional Arbitrary JSON object stored with the entry. JSON object {"source":"merchant_crm"}

Sample Request

Compute the hash, then POST the JSON body:

Request
# 1. Compute the auth hash: sha256(key|amount|idempotency_key|salt)
API_KEY="YOUR_API_KEY"
API_SALT="YOUR_API_SALT"
AMOUNT="1000.00"
IDEMPOTENCY_KEY="CRM-1"
HASH=$(printf '%s' "$API_KEY|$AMOUNT|$IDEMPOTENCY_KEY|$API_SALT" | openssl dgst -sha256 | awk '{print $2}')

# 2. Call the API (key + hash travel in the request headers)
curl -X POST "https://api.growthbnk.com/v1/route/ledger-entry" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -H "Hash: $HASH" \
  -d '{
    "amount": "'"$AMOUNT"'",
    "idempotency_key": "'"$IDEMPOTENCY_KEY"'",
    "ledger_type": 2,
    "bank_reference_number": "UTR1234567890",
    "remarks": "Cash received through merchant CRM",
    "source": "manual"
  }'
import hashlib
import requests

API_KEY = "YOUR_API_KEY"
API_SALT = "YOUR_API_SALT"
BASE_URL = "https://api.growthbnk.com"

amount = "1000.00"
idempotency_key = "CRM-1"

# Auth hash: sha256(key|amount|idempotency_key|salt)
signing = f"{API_KEY}|{amount}|{idempotency_key}|{API_SALT}"
auth_hash = hashlib.sha256(signing.encode("utf-8")).hexdigest()

payload = {
    "amount": amount,
    "idempotency_key": idempotency_key,
    "ledger_type": 2,               # 1 = Debit, 2 = Credit
    "bank_reference_number": "UTR1234567890",
    "remarks": "Cash received through merchant CRM",
    "source": "manual",
}

response = requests.post(
    f"{BASE_URL}/v1/route/ledger-entry",
    json=payload,
    headers={
        "Content-Type": "application/json",
        "X-API-Key": API_KEY,
        "Hash": auth_hash,
    },
    timeout=30,
)
print(response.status_code, response.json())
<?php
$apiKey  = 'YOUR_API_KEY';
$apiSalt = 'YOUR_API_SALT';
$baseUrl = 'https://api.growthbnk.com';

$amount = '1000.00';
$idempotencyKey = 'CRM-1';

// Auth hash: sha256(key|amount|idempotency_key|salt)
$signing  = "{$apiKey}|{$amount}|{$idempotencyKey}|{$apiSalt}";
$authHash = hash('sha256', $signing);

$payload = [
    'amount'                => $amount,
    'idempotency_key'       => $idempotencyKey,
    'ledger_type'           => 2, // 1 = Debit, 2 = Credit
    'bank_reference_number' => 'UTR1234567890',
    'remarks'               => 'Cash received through merchant CRM',
    'source'                => 'manual',
];

$ch = curl_init("{$baseUrl}/v1/route/ledger-entry");
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        "X-API-Key: {$apiKey}",
        "Hash: {$authHash}",
    ],
    CURLOPT_POSTFIELDS     => json_encode($payload),
]);
$response = curl_exec($ch);
echo $response;

Request body

Request body
{
    "amount": "1000.00",
    "bank_transaction_id": "BANKTXN1234567",
    "ledger_type": 2,
    "bank_reference_number": "UTR1234567890",
    "bank_narration": "NEFT credit from customer",
    "value_date": "2026-07-13",
    "transaction_date": "2026-07-13T22:20:00Z",
    "customer_name": "Jane Doe",
    "customer_account_number": "1234567890",
    "customer_bank_name": "HDFC Bank",
    "customer_ifsc": "HDFC0000123",
    "source": "manual",
    "message_type": "NEFT",
    "idempotency_key": "CRM-1",
    "reference_type": "MANUAL_CASH_ENTRY",
    "reference_id": "CRM-REF-1",
    "remarks": "Cash received through merchant CRM",
    "metadata": {
        "source": "merchant_crm"
    }
}

Response Format

A successful call returns HTTP 201 Created with the created entry and its running balance.

FieldTypeDescription
successbooleanAlways true on success.
messagestringHuman-readable status message.
data.ledger_entry_idstringUnique id (UUID) of the created ledger entry.
data.ledger_typeinteger1 = Debit, 2 = Credit.
data.amountstringEntry amount in rupees (two decimals).
data.opening_balancestringMerchant balance before this entry.
data.closing_balancestringMerchant balance after this entry.
data.bank_transaction_idstringEcho of the supplied bank transaction id.
data.sourcestringSource of the entry.
data.created_atstringISO-8601 creation timestamp.

Sample Success Response

Success
201 Created
{
    "success": true,
    "message": "Ledger entry created successfully",
    "data": {
        "ledger_entry_id": "b3f1c2a4-8d7e-4f2b-9a1c-6e5d4c3b2a10",
        "ledger_type": 2,
        "amount": "1000.00",
        "opening_balance": "5000.00",
        "closing_balance": "6000.00",
        "bank_transaction_id": "BANKTXN1234567",
        "source": "manual",
        "created_at": "2026-07-13T22:20:00Z"
    }
}

Error Responses

Invalid hash
401 Unauthorized
{
    "detail": "Invalid authentication hash."
}
Unauthorized (merchant not found)
401 Unauthorized
{
    "detail": "Unauthorized."
}
Idempotency key already exists
409 Conflict
{
    "detail": "Ledger entry with this idempotency_key already exists."
}
Validation error
400 Bad Request
{
    "success": false,
    "message": {
        "ledger_type": [
            "\"5\" is not a valid choice."
        ]
    }
}
Duplicate bank transaction id
409 Conflict
{
    "success": false,
    "message": "bank_transaction_id already exists"
}
Internal server error
500 Internal Server Error
{
    "success": false,
    "message": "Internal server error"
}

Status Codes

StatusMeaning
201 CreatedLedger entry created successfully.
400 Bad RequestMissing or invalid parameters (missing amount/idempotency_key or a serializer validation error).
401 UnauthorizedMissing/invalid API key or mismatched authentication hash.
409 ConflictThe idempotency_key (or a supplied bank_transaction_id) already exists for the merchant.
500 Internal Server ErrorUnexpected server error.

Error Codes

StatusMessageReason
401Invalid authentication hash.Computed hash does not match key|amount|idempotency_key|salt.
401Unauthorized.No merchant is registered for the supplied API key.
400amount and idempotency_key are required.A required auth/hash field is missing from the body.
409Ledger entry with this idempotency_key already exists.The idempotency_key was already used by this merchant — the entry is not created again.
409bank_transaction_id already existsA supplied bank_transaction_id already exists for this merchant.
400Validation errorA serializer field has the wrong type / choice.
500Internal server errorAn unexpected error occurred while creating the entry.

Notes