Authentication
The Legacy API uses two different authentication schemes depending on the endpoint group.
Order Endpoints — SHA-512 Signature
Order endpoints (/api/order/*) are authenticated via a SHA-512 hash included in the request body.
Formula
signature = lowercase_hex( SHA512( clientId + "|" + orderId + "|" + totalAmount + "|" + clientSecret ) )
clientId— yourlegacy_client_idorderId— the merchant order ID from the request bodytotalAmount— the full IDR integer from the request body (not minor units)clientSecret— yourlegacy_client_secret- Fields are joined with pipe
|characters (no spaces)
Code Samples
function signOrder(string $clientId, string $orderId, int $totalAmount, string $clientSecret): string
{
$parts = implode('|', [$clientId, $orderId, (string)$totalAmount, $clientSecret]);
return hash('sha512', $parts);
}
// Usage:
$signature = signOrder('TEST_CLIENT_001', 'INV-2026-00123', 100000, 'TEST_SECRET_001');
const crypto = require('crypto');
function signOrder(clientId, orderId, totalAmount, clientSecret) {
const parts = [clientId, orderId, String(totalAmount), clientSecret].join('|');
return crypto.createHash('sha512').update(parts).digest('hex');
}
// Usage:
const signature = signOrder('TEST_CLIENT_001', 'INV-2026-00123', 100000, 'TEST_SECRET_001');
SIGNATURE=$(echo -n "TEST_CLIENT_001|INV-2026-00123|100000|TEST_SECRET_001" | sha512sum | awk '{print $1}')
totalAmount must be exactly the integer value you send in the request body. A mismatch (e.g., different whitespace or rounding) will cause an Invalid Signature error.
Disbursement Endpoints — RSA-SHA256 X-SIGNATURE
Disbursement endpoints (/api/disbursement/*) require an X-SIGNATURE header signed with your RSA private key.
How It Works
- Minify your JSON request body (compact, no extra whitespace)
- Compute
bodyHash = lowercase_hex( SHA256( minified_body ) ) - Build the string to sign:
stringToSign = clientId + "|" + clientSecret + "|" + bodyHash - Sign it:
rawSig = RSA_SHA256_sign( stringToSign, yourPrivateKey ) - Encode:
X-SIGNATURE: base64( rawSig )
The server verifies using your public key which you upload to the platform dashboard.
Generating Your RSA Key Pair
# Generate private key (keep this secret, never share)
openssl genrsa -out private.pem 2048
# Extract public key (upload this to the Admin Dashboard)
openssl rsa -in private.pem -pubout -out public.pem
Upload the contents of public.pem to the Admin Dashboard → Merchants → Your Merchant → Legacy Credentials.
Code Samples
function signDisbursement(array $body, string $clientId, string $clientSecret, string $privateKeyPem): string
{
$minifiedBody = json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$bodyHash = hash('sha256', $minifiedBody);
$stringToSign = implode('|', [$clientId, $clientSecret, $bodyHash]);
$privateKey = openssl_pkey_get_private($privateKeyPem);
openssl_sign($stringToSign, $rawSig, $privateKey, OPENSSL_ALGO_SHA256);
return base64_encode($rawSig);
}
// Usage:
$xSignature = signDisbursement(
['clientId' => 'TEST_CLIENT_001', 'orderId' => 'DISB-001', ...],
'TEST_CLIENT_001',
'TEST_SECRET_001',
file_get_contents('private.pem')
);
// Send as header: X-SIGNATURE: <value>
const crypto = require('crypto');
const fs = require('fs');
function signDisbursement(body, clientId, clientSecret, privateKeyPem) {
const minifiedBody = JSON.stringify(body);
const bodyHash = crypto.createHash('sha256').update(minifiedBody).digest('hex');
const stringToSign = [clientId, clientSecret, bodyHash].join('|');
return crypto.sign('sha256', Buffer.from(stringToSign), privateKeyPem).toString('base64');
}
// Usage:
const privateKey = fs.readFileSync('private.pem', 'utf8');
const xSignature = signDisbursement(requestBody, clientId, clientSecret, privateKey);
// Add to request: 'X-SIGNATURE': xSignature
The JSON body you hash must be byte-for-byte identical to the body you send in the HTTP request. Build the body object once, stringify it once, use that same string for both hashing and the request body.
Common Errors
| Message | Cause |
|---|---|
Invalid Client ID | clientId not found or merchant inactive |
Invalid X-SIGNATURE | Signature verification failed (wrong key or mismatched body) |
Public Key is not set | No RSA public key uploaded for this merchant |