Authentication
Every request is authenticated with your API key and a per-request SHA-256 hash computed from your secret salt.
API Key & Secret Salt
Your account is issued two credentials:
| Credential | Where it goes | Description |
|---|---|---|
| API Key | X-API-Key header | Public identifier for your merchant account. |
| Salt | Server-side only | Secret used to compute the request Hash. Never transmitted. |
The salt is a secret. Keep it on your server, out of source control, browsers and mobile apps. All values shown in these docs (e.g. YOUR_API_KEY, YOUR_API_SALT) are placeholders.
Required Headers
| Header | Type | Required | Description |
|---|---|---|---|
| X-API-Key | string | Required | Your merchant API key. |
| Hash | string | Required | The SHA-256 signature for this request (see below). |
| Content-Type | string | Required | Always application/json for JSON bodies. |
The Signature / Hash
The Hash is the lowercase hex SHA-256 digest of a pipe-delimited string that always begins with your
API key and ends with your salt. The fields in the middle depend on the endpoint:
Hash = SHA256( key | <fields…> | salt )
| Endpoint | Hash input |
|---|---|
| Initiate Payment | key|merchant_transaction_id|transaction_amount|salt |
| Transaction Status | key|merchant_transaction_id|salt |
| Cancel Transaction | key|merchant_transaction_id|salt |
| Refund Initiate | key|transaction_id|refund_amount|salt |
| Refund Status | key|refund_id|salt |
The hash is computed over the raw string values. If you hash "1499.00" but send "1499.0", the signatures will not match and the request is rejected with 401. Always sign and send the identical value.
Worked example — Initiate Payment
The snippet below computes the hash for Initiate Payment
(key|merchant_transaction_id|transaction_amount|salt) and signs the request. Switch languages with the tabs.
# 1. Compute the auth hash: sha256(key|merchant_transaction_id|transaction_amount|salt)
API_KEY="YOUR_API_KEY"
API_SALT="YOUR_API_SALT"
HASH=$(printf '%s' "$API_KEY|ORDER-2026-0001|1499.00|$API_SALT" | openssl dgst -sha256 | awk '{print $2}')
# 2. Call the API
curl -X POST "https://api.growthbnk.com/v1/route/initiate_payment" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-H "Hash: $HASH" \
-d '{
"merchant_transaction_id": "ORDER-2026-0001",
"transaction_amount": "1499.00",
"currency": "INR",
"payment_method": "UPI",
"surl": "https://merchant.example.com/payment/success",
"furl": "https://merchant.example.com/payment/failure",
"customer_details": {
"customer_name": "Jane Doe",
"customer_email": "jane.doe@example.com",
"customer_phone": "9876543210"
}
}'import hashlib
import requests
API_KEY = "YOUR_API_KEY"
API_SALT = "YOUR_API_SALT"
BASE_URL = "https://api.growthbnk.com"
payload = {
'merchant_transaction_id': 'ORDER-2026-0001',
'transaction_amount': '1499.00',
'currency': 'INR',
'payment_method': 'UPI',
'surl': 'https://merchant.example.com/payment/success',
'furl': 'https://merchant.example.com/payment/failure',
'customer_details': {
'customer_name': 'Jane Doe',
'customer_email': 'jane.doe@example.com',
'customer_phone': '9876543210'
}
}
# Auth hash: sha256(key|merchant_transaction_id|transaction_amount|salt)
signing = f"{API_KEY}|ORDER-2026-0001|1499.00|{API_SALT}"
auth_hash = hashlib.sha256(signing.encode("utf-8")).hexdigest()
response = requests.post(
f"{BASE_URL}/v1/route/initiate_payment",
json=payload,
headers={
"Content-Type": "application/json",
"X-API-Key": API_KEY,
"Hash": auth_hash,
},
timeout=30,
)
response.raise_for_status()
print(response.json())<?php
$apiKey = 'YOUR_API_KEY';
$apiSalt = 'YOUR_API_SALT';
$baseUrl = 'https://api.growthbnk.com';
$payload = [
'merchant_transaction_id' => 'ORDER-2026-0001',
'transaction_amount' => '1499.00',
'currency' => 'INR',
'payment_method' => 'UPI',
'surl' => 'https://merchant.example.com/payment/success',
'furl' => 'https://merchant.example.com/payment/failure',
'customer_details' => [
'customer_name' => 'Jane Doe',
'customer_email' => 'jane.doe@example.com',
'customer_phone' => '9876543210'
]
];
// Auth hash: sha256(key|merchant_transaction_id|transaction_amount|salt)
$signing = "{$apiKey}|ORDER-2026-0001|1499.00|{$apiSalt}";
$authHash = hash('sha256', $signing);
$ch = curl_init("{$baseUrl}/v1/route/initiate_payment");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
"X-API-Key: {$apiKey}",
"Hash: {$authHash}",
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;const crypto = require('crypto');
const API_KEY = 'YOUR_API_KEY';
const API_SALT = 'YOUR_API_SALT';
const BASE_URL = 'https://api.growthbnk.com';
const payload = {
'merchant_transaction_id': 'ORDER-2026-0001',
'transaction_amount': '1499.00',
'currency': 'INR',
'payment_method': 'UPI',
'surl': 'https://merchant.example.com/payment/success',
'furl': 'https://merchant.example.com/payment/failure',
'customer_details': {
'customer_name': 'Jane Doe',
'customer_email': 'jane.doe@example.com',
'customer_phone': '9876543210'
}
};
// Auth hash: sha256(key|merchant_transaction_id|transaction_amount|salt)
const signing = `${API_KEY}|ORDER-2026-0001|1499.00|${API_SALT}`;
const authHash = crypto.createHash('sha256').update(signing).digest('hex');
const response = await fetch(`${BASE_URL}/v1/route/initiate_payment`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY,
'Hash': authHash,
},
body: JSON.stringify(payload),
});
console.log(await response.json());import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
public class GrowthBnkExample {
public static void main(String[] args) throws Exception {
String apiKey = "YOUR_API_KEY";
String apiSalt = "YOUR_API_SALT";
String baseUrl = "https://api.growthbnk.com";
String payload = """
{
"merchant_transaction_id": "ORDER-2026-0001",
"transaction_amount": "1499.00",
"currency": "INR",
"payment_method": "UPI",
"surl": "https://merchant.example.com/payment/success",
"furl": "https://merchant.example.com/payment/failure",
"customer_details": {
"customer_name": "Jane Doe",
"customer_email": "jane.doe@example.com",
"customer_phone": "9876543210"
}
}
""";
// Auth hash: sha256(key|merchant_transaction_id|transaction_amount|salt)
String signing = apiKey + "|ORDER-2026-0001|1499.00|" + apiSalt;
String authHash = sha256Hex(signing);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/v1/route/initiate_payment"))
.header("Content-Type", "application/json")
.header("X-API-Key", apiKey)
.header("Hash", authHash)
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
private static String sha256Hex(String input) throws Exception {
byte[] digest = MessageDigest.getInstance("SHA-256")
.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : digest) sb.append(String.format("%02x", b));
return sb.toString();
}
}using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
class GrowthBnkExample
{
static async Task Main()
{
var apiKey = "YOUR_API_KEY";
var apiSalt = "YOUR_API_SALT";
var baseUrl = "https://api.growthbnk.com";
var payload = """
{
"merchant_transaction_id": "ORDER-2026-0001",
"transaction_amount": "1499.00",
"currency": "INR",
"payment_method": "UPI",
"surl": "https://merchant.example.com/payment/success",
"furl": "https://merchant.example.com/payment/failure",
"customer_details": {
"customer_name": "Jane Doe",
"customer_email": "jane.doe@example.com",
"customer_phone": "9876543210"
}
}
""";
// Auth hash: sha256(key|merchant_transaction_id|transaction_amount|salt)
var signing = $"{apiKey}|ORDER-2026-0001|1499.00|{apiSalt}";
var authHash = Convert.ToHexString(
SHA256.HashData(Encoding.UTF8.GetBytes(signing))).ToLowerInvariant();
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", apiKey);
client.DefaultRequestHeaders.Add("Hash", authHash);
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync($"{baseUrl}/v1/route/initiate_payment", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"net/http"
)
func main() {
apiKey := "YOUR_API_KEY"
apiSalt := "YOUR_API_SALT"
baseURL := "https://api.growthbnk.com"
payload := []byte(`{
"merchant_transaction_id": "ORDER-2026-0001",
"transaction_amount": "1499.00",
"currency": "INR",
"payment_method": "UPI",
"surl": "https://merchant.example.com/payment/success",
"furl": "https://merchant.example.com/payment/failure",
"customer_details": {
"customer_name": "Jane Doe",
"customer_email": "jane.doe@example.com",
"customer_phone": "9876543210"
}
}`)
// Auth hash: sha256(key|merchant_transaction_id|transaction_amount|salt)
signing := apiKey + "|ORDER-2026-0001|1499.00|" + apiSalt
sum := sha256.Sum256([]byte(signing))
authHash := hex.EncodeToString(sum[:])
req, _ := http.NewRequest("POST", baseURL+"/v1/route/initiate_payment", bytes.NewReader(payload))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", apiKey)
req.Header.Set("Hash", authHash)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require 'digest'
require 'json'
require 'net/http'
require 'uri'
api_key = 'YOUR_API_KEY'
api_salt = 'YOUR_API_SALT'
base_url = 'https://api.growthbnk.com'
payload = {
'merchant_transaction_id' => 'ORDER-2026-0001',
'transaction_amount' => '1499.00',
'currency' => 'INR',
'payment_method' => 'UPI',
'surl' => 'https://merchant.example.com/payment/success',
'furl' => 'https://merchant.example.com/payment/failure',
'customer_details' => {
'customer_name' => 'Jane Doe',
'customer_email' => 'jane.doe@example.com',
'customer_phone' => '9876543210'
}
}
# Auth hash: sha256(key|merchant_transaction_id|transaction_amount|salt)
signing = "#{api_key}|ORDER-2026-0001|1499.00|#{api_salt}"
auth_hash = Digest::SHA256.hexdigest(signing)
uri = URI("#{base_url}/v1/route/initiate_payment")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri, {
'Content-Type' => 'application/json',
'X-API-Key' => api_key,
'Hash' => auth_hash
})
request.body = payload.to_json
response = http.request(request)
puts response.bodySecurity Best Practices
- Compute the hash server-side only; never ship the salt to a browser or mobile client.
- Store the API key and salt in environment variables or a secrets manager — not in source control.
- Always call the API over HTTPS; reject plaintext connections.
- Rotate your salt immediately if you suspect it was exposed.
- Verify inbound webhooks with the same hashing scheme before acting on them — see Webhooks.
- Use a unique, idempotent
merchant_transaction_idper order to avoid accidental double-charges.