Authentication
Authentication
Every request to the Indicpay Payments API must include three headers:
| Header | Value |
|---|---|
Content-Type | application/json |
merchant-id | Your merchant ID (issued by Indicpay) |
Authorization | Bearer <generated_token> |
The Authorization token is not static — it's a short-lived, AES-encrypted token that you generate for
every request using the credentials Indicpay issues you:
merchant_idsecret_keyencryption_keyencryption_iv
Keep these credentials secret. Never exposesecret_key,encryption_key, orencryption_ivinclient-side code, mobile apps, or public repositories. Token generation should always happen on your server.
How the token works
- Build a small JSON payload:
{ timestamp, secret, reqId }timestamp— current Unix timestamp (seconds)secret— yoursecret_keyreqId— a random unique ID (e.g. a UUID/GUID) per request
- Encrypt that JSON payload using AES-256-CBC, with:
- Key = your
encryption_key(first 32 bytes, UTF-8) - IV = your
encryption_iv(UTF-8) - Padding = PKCS7
- Key = your
- Base64-encode the ciphertext — that's your token.
- Send it as
Authorization: Bearer <token>.
Important:
- Each token is valid for 5 minutes only.
- Each token can be used for one request only — generate a fresh token every time.
Below are code samples in six languages. Replace the placeholder values with your own credentials.
Node.js
const crypto = require("crypto");
const { v4: uuidv4 } = require("uuid");
const secretKey = "YOUR_SECRET_KEY";
const encryptionKey = "YOUR_ENCRYPTION_KEY"; // first 32 chars are used
const encryptionIv = "YOUR_ENCRYPTION_IV";
function generateAuthToken() {
const timestamp = Math.floor(Date.now() / 1000);
const reqId = uuidv4();
const payload = JSON.stringify({ timestamp, secret: secretKey, reqId });
const key = Buffer.from(encryptionKey.substring(0, 32), "utf8");
const iv = Buffer.from(encryptionIv, "utf8");
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
const encrypted = Buffer.concat([cipher.update(payload, "utf8"), cipher.final()]);
return encrypted.toString("base64");
}
const token = generateAuthToken();
console.log(`Bearer ${token}`);Python
import base64
import json
import time
import uuid
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
SECRET_KEY = "YOUR_SECRET_KEY"
ENCRYPTION_KEY = "YOUR_ENCRYPTION_KEY" # first 32 chars are used
ENCRYPTION_IV = "YOUR_ENCRYPTION_IV"
def generate_auth_token():
payload = json.dumps({
"timestamp": int(time.time()),
"secret": SECRET_KEY,
"reqId": str(uuid.uuid4()),
})
key = ENCRYPTION_KEY[:32].encode("utf-8")
iv = ENCRYPTION_IV.encode("utf-8")
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted = cipher.encrypt(pad(payload.encode("utf-8"), AES.block_size))
return base64.b64encode(encrypted).decode("utf-8")
token = generate_auth_token()
print(f"Bearer {token}")PHP
<?php
$secretKey = "YOUR_SECRET_KEY";
$encryptionKey = "YOUR_ENCRYPTION_KEY"; // first 32 chars are used
$encryptionIv = "YOUR_ENCRYPTION_IV";
function generateAuthToken($secretKey, $encryptionKey, $encryptionIv) {
$payload = json_encode([
"timestamp" => time(),
"secret" => $secretKey,
"reqId" => bin2hex(random_bytes(16)),
]);
$key = substr($encryptionKey, 0, 32);
$encrypted = openssl_encrypt(
$payload,
"AES-256-CBC",
$key,
OPENSSL_RAW_DATA,
$encryptionIv
);
return base64_encode($encrypted);
}
$token = generateAuthToken($secretKey, $encryptionKey, $encryptionIv);
echo "Bearer " . $token;Java
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.UUID;
public class IndicpayAuth {
static final String SECRET_KEY = "YOUR_SECRET_KEY";
static final String ENCRYPTION_KEY = "YOUR_ENCRYPTION_KEY"; // first 32 chars are used
static final String ENCRYPTION_IV = "YOUR_ENCRYPTION_IV";
public static String generateAuthToken() throws Exception {
long timestamp = System.currentTimeMillis() / 1000L;
String reqId = UUID.randomUUID().toString();
String payload = String.format(
"{\"timestamp\":%d,\"secret\":\"%s\",\"reqId\":\"%s\"}",
timestamp, SECRET_KEY, reqId
);
SecretKeySpec keySpec = new SecretKeySpec(
ENCRYPTION_KEY.substring(0, 32).getBytes("UTF-8"), "AES"
);
IvParameterSpec ivSpec = new IvParameterSpec(ENCRYPTION_IV.getBytes("UTF-8"));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(payload.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(encrypted);
}
public static void main(String[] args) throws Exception {
System.out.println("Bearer " + generateAuthToken());
}
}C# (.NET)
using System;
using System.Security.Cryptography;
using System.Text;
public class IndicpayAuth
{
static string SecretKey = "YOUR_SECRET_KEY";
static string EncryptionKey = "YOUR_ENCRYPTION_KEY"; // first 32 chars are used
static string EncryptionIv = "YOUR_ENCRYPTION_IV";
public static string GenerateAuthToken()
{
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string reqId = Guid.NewGuid().ToString();
string payload = $"{{\"timestamp\":{timestamp},\"secret\":\"{SecretKey}\",\"reqId\":\"{reqId}\"}}";
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(EncryptionKey.Substring(0, 32));
aes.IV = Encoding.UTF8.GetBytes(EncryptionIv);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
using (var encryptor = aes.CreateEncryptor())
{
byte[] payloadBytes = Encoding.UTF8.GetBytes(payload);
byte[] encrypted = encryptor.TransformFinalBlock(payloadBytes, 0, payloadBytes.Length);
return Convert.ToBase64String(encrypted);
}
}
}
public static void Main()
{
Console.WriteLine("Bearer " + GenerateAuthToken());
}
}Go
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
"github.com/google/uuid"
"time"
)
const (
secretKey = "YOUR_SECRET_KEY"
encryptionKey = "YOUR_ENCRYPTION_KEY" // first 32 chars are used
encryptionIv = "YOUR_ENCRYPTION_IV"
)
func pkcs7Pad(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := make([]byte, padding)
for i := range padText {
padText[i] = byte(padding)
}
return append(data, padText...)
}
func generateAuthToken() (string, error) {
timestamp := time.Now().Unix()
reqId := uuid.New().String()
payload := fmt.Sprintf(`{"timestamp":%d,"secret":"%s","reqId":"%s"}`, timestamp, secretKey, reqId)
key := []byte(encryptionKey)[:32]
iv := []byte(encryptionIv)
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
padded := pkcs7Pad([]byte(payload), aes.BlockSize)
encrypted := make([]byte, len(padded))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted, padded)
return base64.StdEncoding.EncodeToString(encrypted), nil
}
func main() {
token, _ := generateAuthToken()
fmt.Println("Bearer " + token)
}Common errors
| Response | Cause |
|---|---|
401 Unauthorized – Invalid or expired token | Token is older than 5 minutes, or has already been used once. |
401 Unauthorized – Invalid signature | Wrong encryption_key / encryption_iv, or key not truncated to 32 bytes. |
401 Unauthorized – Merchant not found | merchant-id header missing or incorrect. |
Generate a brand-new token immediately before each API call — do not cache or reuse tokens across requests.
Updated 3 days ago
Did this page help you?
