Skip to main content

REST API Authentication

All REST API requests must include authentication headers. ZenPays uses API Key + HMAC Signature authentication for secure request verification.

Required Headers

HeaderRequiredDescription
AuthorizationYesBearer {api_key} - Your API key
X-SignatureYesHMAC-SHA256 signature of the request
X-TimestampYesISO 8601 timestamp (UTC)
X-Secret-SaltYesYour secret salt for HMAC signature validation
Content-TypeYes*application/json for POST/PUT/PATCH requests
X-Merchant-IDNoOptional merchant ID for multi-merchant setups

API Keys

ZenPays uses prefixed API keys to identify the environment:

PrefixEnvironmentUsage
zp_live_ProductionReal payments
zp_test_SandboxTesting and development

Getting Your API Key

  1. Log in to your ZenPays Dashboard
  2. Navigate to SettingsAPI Keys
  3. Copy your API key and Secret Salt
warning

Keep your API keys and Secret Salt secure. Never expose them in client-side code or commit them to version control.

Signature Generation

Every request must include an HMAC-SHA256 signature to verify its integrity.

Signature Formula

signature = HMAC-SHA256(timestamp + body, secret_salt)

Where:

  • timestamp - The value of the X-Timestamp header
  • body - JSON stringified request body (empty string for GET requests)
  • secret_salt - Your secret salt from the dashboard

Implementation Examples

const crypto = require('crypto');

function generateSignature(timestamp, body, secretSalt) {
const data = timestamp + JSON.stringify(body);
return crypto
.createHmac('sha256', secretSalt)
.update(data)
.digest('hex');
}

// Example usage
const timestamp = new Date().toISOString();
const body = { amount: 1000, currency: 'USD' };
const signature = generateSignature(
timestamp,
body,
process.env.ZENPAYS_SECRET_SALT
);

console.log('Signature:', signature);
// Output: a1b2c3d4e5f6...

Complete Request Example

#!/bin/bash

API_KEY="zp_test_xxxxx"
SECRET_SALT="your_secret_salt"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")

BODY='{"amount":1000,"currency":"USD","description":"Order #123"}'

# Generate signature (requires openssl)
SIGNATURE=$(echo -n "${TIMESTAMP}${BODY}" | openssl dgst -sha256 -hmac "$SECRET_SALT" | cut -d' ' -f2)

curl -X POST https://api.zenpayz.com/api/v1/payment-intents \
-H "Authorization: Bearer $API_KEY" \
-H "X-Timestamp: $TIMESTAMP" \
-H "X-Signature: $SIGNATURE" \
-H "X-Secret-Salt: $SECRET_SALT" \
-H "Content-Type: application/json" \
-d "$BODY"

Timestamp Validation

The X-Timestamp header must be within ±5 minutes of the server time. Requests with timestamps outside this window are rejected to prevent replay attacks.

{
"success": false,
"error": {
"code": "TIMESTAMP_EXPIRED",
"message": "Request timestamp is outside the allowed window"
}
}
tip

Always use UTC timestamps and ensure your server clock is synchronized with NTP.

GET Request Authentication

For GET requests without a body, use an empty object {} when calculating the signature:

// For GET requests
const timestamp = new Date().toISOString();
const data = timestamp + '{}';
const signature = crypto
.createHmac('sha256', secretSalt)
.update(data)
.digest('hex');

const response = await fetch('https://api.zenpayz.com/api/v1/payment-intents/pi_xxx', {
method: 'GET',
headers: {
'Authorization': `Bearer ${apiKey}`,
'X-Timestamp': timestamp,
'X-Signature': signature,
'X-Secret-Salt': secretSalt,
},
});

IP Whitelisting

For enhanced security, you can restrict API access to specific IP addresses:

  1. Go to DashboardSettingsAPI Security
  2. Add your server IP addresses to the whitelist
  3. Enable IP restriction for your API keys

Requests from non-whitelisted IPs will receive:

{
"success": false,
"error": {
"code": "IP_NOT_WHITELISTED",
"message": "Request from unauthorized IP address"
}
}

Authentication Errors

Error CodeHTTP StatusDescription
UNAUTHORIZED401Missing or invalid API key
INVALID_SIGNATURE401Signature verification failed
TIMESTAMP_EXPIRED401Timestamp outside allowed window
API_KEY_REVOKED401API key has been revoked
IP_NOT_WHITELISTED403Request from unauthorized IP
INSUFFICIENT_PERMISSIONS403API key lacks required scope

Best Practices

  1. Use environment variables - Never hardcode API keys or secrets
  2. Rotate keys regularly - Create new keys and revoke old ones periodically
  3. Use minimal scopes - Only grant necessary permissions to each key
  4. Enable IP whitelisting - Restrict access to known server IPs
  5. Monitor API usage - Check the dashboard for unusual activity
  6. Use HTTPS only - Never send credentials over unencrypted connections

Next Steps