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.
| Key | Format | Purpose |
|---|---|---|
| Client Key | pk_xxx | Included in request headers to identify the project |
| Secret Key | sk_xxx | Used 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.
| Header | Type | Required | Description |
|---|---|---|---|
X-Client-Key | string | ✓ | Client Key |
X-Timestamp | string | ✓ | Unix timestamp (seconds) |
X-Signature | string | ✓ | HMAC-SHA256 signature |
Content-Type | string | ✓ | application/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}
| Element | Description | Example |
|---|---|---|
timestamp | Same value as the X-Timestamp header | 1706500000 |
method | HTTP method (uppercase) | POST |
path | API path (including query string) | /api/invoices |
body | JSON 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
| Item | Description |
|---|---|
| Timestamp Validity | Must be within ±5 minutes of server time. Ensure your server time is synchronized with NTP. |
| Body Serialization | The string serialized with JSON.stringify() must be identical in both the signature message and request body. |
| Path Format | When query strings are present, include them in the signature. (e.g., /api/invoices?page=1) |
| Method Case | HTTP methods must be in uppercase. (GET, POST) |