BridgPay Docs

Generate Request Signature

HMAC-SHA256 request signing helpers for legacy HMAC v1 and preferred HMAC v2 merchant API calls.

HMAC v1 TypeScript

import crypto from 'crypto';
 
export function generateApiSignature({
  method,
  path,
  body,
  apiSecret,
}: {
  method: string;
  path: string;
  body: unknown;
  apiSecret: string;
}): { timestamp: string; signature: string } {
  const timestamp = Date.now().toString();
 
  const canonicalBody = ['GET', 'DELETE', 'HEAD', 'OPTIONS'].includes(
    method.toUpperCase(),
  )
    ? ''
    : body
      ? JSON.stringify(body)
      : '';
 
  const canonicalString = [method.toUpperCase(), path, timestamp, canonicalBody].join('|');
 
  const signature = crypto
    .createHmac('sha256', apiSecret)
    .update(canonicalString)
    .digest('hex');
 
  return { timestamp, signature };
}

Use HMAC v1 only for requests without query strings. Use HMAC v2 for list/search endpoints and new integrations.

HMAC v2 TypeScript

HMAC v2 is a signing format for /v1/... endpoints. Do not switch the URL to /v2/....

import crypto from 'crypto';
 
export function generateApiSignatureV2({
  method,
  host,
  pathAndQuery,
  body,
  apiKey,
  apiSecret,
}: {
  method: string;
  host: string;
  pathAndQuery: string;
  body: string;
  apiKey: string;
  apiSecret: string;
}): Record<string, string> {
  const timestamp = Date.now().toString();
  const nonce = crypto.randomUUID();
  const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
  const canonicalString = [
    method.toUpperCase(),
    host.toLowerCase(),
    pathAndQuery,
    apiKey,
    timestamp,
    nonce,
    bodyHash,
  ].join('|');
 
  return {
    'x-bridg-sig-version': '2',
    'x-api-key': apiKey,
    'x-timestamp': timestamp,
    'x-nonce': nonce,
    'x-signature': crypto
      .createHmac('sha256', apiSecret)
      .update(canonicalString)
      .digest('hex'),
  };
}

HMAC v1 Python

import hmac
import hashlib
import json
import time
 
def generate_api_signature(method: str, path: str, body, api_secret: str):
    timestamp = str(int(time.time() * 1000))
 
    if method.upper() in ('GET', 'DELETE', 'HEAD', 'OPTIONS'):
        canonical_body = ''
    else:
        canonical_body = json.dumps(body, separators=(',', ':')) if body else ''
 
    canonical = '|'.join([method.upper(), path, timestamp, canonical_body])
    signature = hmac.new(
        api_secret.encode('utf-8'),
        canonical.encode('utf-8'),
        hashlib.sha256,
    ).hexdigest()
 
    return timestamp, signature

HMAC v1 Java

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Set;
 
public class BridgSignature {
    private static final Set<String> EMPTY_BODY = Set.of("GET", "DELETE", "HEAD", "OPTIONS");
 
    public static String[] generate(String method, String path, String body, String apiSecret) throws Exception {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String canonicalBody = EMPTY_BODY.contains(method.toUpperCase()) ? "" : (body == null ? "" : body);
        String canonical = String.join("|", method.toUpperCase(), path, timestamp, canonicalBody);
 
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(apiSecret.getBytes("UTF-8"), "HmacSHA256"));
        byte[] sig = mac.doFinal(canonical.getBytes("UTF-8"));
 
        StringBuilder hex = new StringBuilder();
        for (byte b : sig) hex.append(String.format("%02x", b));
 
        return new String[]{ timestamp, hex.toString() };
    }
}

HMAC v1 PHP

<?php
function generate_api_signature(string $method, string $path, $body, string $apiSecret): array {
    $timestamp = (string) round(microtime(true) * 1000);
 
    if (in_array(strtoupper($method), ['GET', 'DELETE', 'HEAD', 'OPTIONS'], true)) {
        $canonicalBody = '';
    } else {
        $canonicalBody = $body ? json_encode($body, JSON_UNESCAPED_SLASHES) : '';
    }
 
    $canonical = implode('|', [strtoupper($method), $path, $timestamp, $canonicalBody]);
    $signature = hash_hmac('sha256', $canonical, $apiSecret);
 
    return ['timestamp' => $timestamp, 'signature' => $signature];
}

On this page