Skip to main content

Authentication

HMAC-SHA256 signature authentication guide for using the OOZOO PAY API.

API Key

API request authentication requires a Client Key and Secret Key. These can be issued per project from the Merchant Dashboard.

KeyFormatPurpose
Client Keypk_xxxIncluded in request headers to identify the project
Secret Keysk_xxxUsed for HMAC signature generation (server-side only)
Secret Key Security

The Secret Key must never be exposed on the client side (browser, app). Always use it server-side only.

Required Headers

All API requests must include the following headers.

HeaderTypeRequiredDescription
X-Client-KeystringClient Key
X-TimestampstringUnix timestamp (seconds)
X-SignaturestringHMAC-SHA256 signature
Content-Typestringapplication/json

Signature Generation Guide

Step 1. Generate HMAC Key

Use the SHA-256 hash of the Secret Key as the HMAC Key.

import * as crypto from 'crypto';

const hmacKey = crypto.createHash('sha256').update(secretKey).digest('hex');

Step 2. Construct Signature Message

The message to be signed is constructed in the following format. Each element is joined with a period (.).

{timestamp}.{method}.{path}.{body}

ElementDescriptionExample
timestampSame value as the X-Timestamp header1706500000
methodHTTP method (uppercase)POST
pathAPI path (including query string)/api/invoices
bodyJSON string of the request body{"price":100,...}
When there is no body

For GET requests or other requests without a body, use an empty string ("").

Step 3. Generate HMAC-SHA256 Signature

Generate the HMAC-SHA256 signature for the constructed message.

const message = `${timestamp}.${method}.${path}.${body}`;
const signature = crypto.createHmac('sha256', hmacKey).update(message).digest('hex');

Code Examples

POST Request (Create Invoice)

import * as crypto from 'crypto';

const clientKey = 'pk_xxxxxxxxxxxxxxxx';
const secretKey = 'sk_xxxxxxxxxxxxxxxx';

// 1. HMAC Key
const hmacKey = crypto.createHash('sha256').update(secretKey).digest('hex');

// 2. Request Info
const timestamp = Math.floor(Date.now() / 1000).toString();
const method = 'POST';
const path = '/api/invoices';
const body = JSON.stringify({
price: 100,
chainId: '11155111',
tokenAddress: '0xaA8E...',
sender: '0x1234...',
});

// 3. Generate Signature
const message = `${timestamp}.${method}.${path}.${body}`;
const signature = crypto.createHmac('sha256', hmacKey).update(message).digest('hex');

// 4. API Request
const response = await fetch('https://api.oozoopay.com/api/invoices', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Client-Key': clientKey,
'X-Timestamp': timestamp,
'X-Signature': signature,
},
body,
});

// 5. Response: { success: true, data: { invoiceId: "uuid" } }
const result = await response.json();
console.log(result.data.invoiceId);

GET Request (List Invoices)

const timestamp = Math.floor(Date.now() / 1000).toString();
const method = 'GET';
const path = '/api/invoices?page=1&limit=10';
const body = ''; // Empty string for GET requests

const message = `${timestamp}.${method}.${path}.${body}`;
const signature = crypto.createHmac('sha256', hmacKey).update(message).digest('hex');

const response = await fetch(`https://api.oozoopay.com${path}`, {
headers: {
'X-Client-Key': clientKey,
'X-Timestamp': timestamp,
'X-Signature': signature,
},
});

// Response: { success: true, data: { items: [...], meta: {...} } }
const result = await response.json();
console.log(result.data.items);

Important Notes

ItemDescription
Timestamp ValidityMust be within ±5 minutes of server time. Ensure your server time is synchronized with NTP.
Body SerializationThe string serialized with JSON.stringify() must be identical in both the signature message and request body.
Path FormatWhen query strings are present, include them in the signature. (e.g., /api/invoices?page=1)
Method CaseHTTP methods must be in uppercase. (GET, POST)