Authentication
Authentication

Authentication

Business Sznd API uses HMAC-based authentication on top of API keys.

HMAC headers

Send these headers with every authenticated request:

X-API-Key: your_api_key_here
X-Signature: generated_signature_here
X-Timestamp: 2025-01-15T10:30:00Z
  • X-API-Key: the public identifier for your business API key.
  • X-Timestamp: RFC3339 UTC timestamp (e.g. 2025-01-15T10:30:00Z), used to prevent replay attacks (5‑minute freshness window, 1‑minute future tolerance).
  • X-Signature: hex-encoded HMAC-SHA256 of body + "|" + timestamp using your secret key.

The server recomputes the HMAC using the request body and timestamp; if anything has been tampered with (body or timestamp), the signature fails and the request is rejected.

Signing algorithm (conceptual)

  1. Serialize the JSON request body (empty string if there is no body).
  2. Generate an RFC3339 timestamp.
  3. Build the string: data_to_sign = body + "|" + timestamp.
  4. Compute HMAC-SHA256(secret_key, data_to_sign) and hex-encode the result.
  5. Send the signature as X-Signature with the same body and timestamp.

Authentication errors

Common authentication failures return 401 Unauthorized or 403 Forbidden, for example:

  • Missing headers: x-api-key, x-signature or x-timestamp.
  • Invalid timestamp format or a timestamp that is too old / too far in the future.
  • Invalid signature (body or timestamp changed in transit).
  • Inactive or expired API key.

Business API key management (/business routes)

Business API keys are managed via dedicated /business endpoints. For example:

  • List business API keys
    • Method: GET
    • Path: /api/v1/business/api-keys
    • Description: Returns all active API keys associated with your business user, including metadata such as name, is_active, last_used_at, and expires_at. Secret keys are never returned once created.

Use these endpoints to rotate keys regularly, configure webhook URLs per key, and keep inactive keys disabled.


Postman Setup

To use HMAC authentication in Postman, add this pre-request script to automatically generate signatures for all your requests.

Pre-request Script

Add this script to Postman's Pre-request Script tab (in your request or collection):

// Postman Pre-request Script for HMAC Authentication
// This script automatically generates HMAC signatures for API requests
 
// Get API key and secret key from environment variables
const apiKey = pm.environment.get("api_key");
const secretKey = pm.environment.get("secret_key");
 
if (!apiKey || !secretKey) {
    console.error("⚠️  Please set 'api_key' and 'secret_key' in your Postman environment variables");
    throw new Error("Missing API credentials - set api_key and secret_key in environment");
}
 
// Get request body (empty string if no body)
let requestBody = "";
if (pm.request.body) {
    // Handle different body types
    if (pm.request.body.raw) {
        requestBody = pm.request.body.raw;
    } else if (pm.request.body.urlencoded) {
        // Convert URL encoded to string representation
        requestBody = pm.request.body.urlencoded.toString();
    } else if (pm.request.body.formdata) {
        // Convert form data to string representation
        requestBody = pm.request.body.formdata.toString();
    }
    // If body is JSON object, it will be in raw as string already
}
 
// Generate RFC3339 timestamp (UTC)
const now = new Date();
const timestamp = now.toISOString();
 
// Create data to sign: body + "|" + timestamp
const dataToSign = requestBody + "|" + timestamp;
 
// Generate HMAC-SHA256 signature using CryptoJS
const signature = CryptoJS.HmacSHA256(dataToSign, secretKey).toString(CryptoJS.enc.Hex);
 
// Remove existing headers if they exist (to avoid duplicates)
pm.request.headers.remove("x-api-key");
pm.request.headers.remove("x-timestamp");
pm.request.headers.remove("x-signature");
 
// Set headers automatically
pm.request.headers.add({
    key: "x-api-key",
    value: apiKey
});
 
pm.request.headers.add({
    key: "x-timestamp",
    value: timestamp
});
 
pm.request.headers.add({
    key: "x-signature",
    value: signature
});
 
// Log for debugging (optional - remove in production)
console.log("🔐 HMAC Authentication");
console.log("API Key:", apiKey);
console.log("Timestamp:", timestamp);
console.log("Data to sign:", dataToSign);
console.log("Signature:", signature);

Setup Instructions

  1. Create/Select Environment:

    • Click the environment dropdown in Postman (top right)
    • Create a new environment or select an existing one
    • Click "Edit" to add variables
  2. Add Environment Variables:

    • Variable name: api_key → Value: Your API key (e.g., tf_live_abc123...)
    • Variable name: secret_key → Value: Your secret key (e.g., sk_live_def456...)
    • Click "Save"
  3. Add Pre-request Script:

    • Option A - Collection Level (Recommended):
      • Right-click your collection → "Edit"
      • Go to "Pre-request Script" tab
      • Paste the script above
      • All requests in the collection will use it automatically
    • Option B - Request Level:
      • Open your request
      • Go to "Pre-request Script" tab
      • Paste the script above
      • Only this request will use it
  4. Make Requests:

    • The script runs automatically before each request
    • Headers are generated and added automatically
    • No manual signature calculation needed!

Testing the Setup

  1. Create a test request to any client API endpoint (e.g., POST /api/v1/client/customers)
  2. Add your request body in the "Body" tab
  3. Send the request
  4. Check the Postman Console (View → Show Postman Console) to see the generated signature
  5. If authentication fails, check:
    • Environment variables are set correctly
    • Secret key matches the API key
    • Request body matches what's being signed

Troubleshooting

Error: "Missing API credentials"

  • Ensure api_key and secret_key are set in your active environment
  • Check that the correct environment is selected

Error: "CryptoJS is not defined"

  • Postman includes CryptoJS by default
  • If you see this error, try updating Postman to the latest version

Error: "Invalid signature"

  • Check the Postman Console to see what data is being signed
  • Ensure the request body matches exactly (no extra spaces, correct JSON format)
  • Verify your secret key is correct

Headers not being added

  • Check that the script is in the correct tab (Pre-request Script, not Tests)
  • Ensure you're not manually setting these headers (they'll conflict)