Overview
Below is a brief overview of how to make API calls:- Send your IP address to our support team via email ([email protected]).
- Create the JWT token
- Generate the bodyhash by taking the JWT token and hashing it with SHA256 using the API Secret
- Sign JWTs with the Private Key
- Make the API call
Example Implementation
Here’s a complete example of how to implement the authentication process and make your first API call:Copy
const axios = require("axios");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
// API configuration - replace these placeholders with actual values
const apiKey = "<<REPLACE_HERE>>"; // Your API key identifier
const audience = "<<REPLACE_HERE>>"; // JWT audience (usually the API service identifier)
const apiSecretBase64 = "<<REPLACE_HERE>>"; // Base64-encoded HMAC secret for body hashing
const hmacSecret = Buffer.from(apiSecretBase64, "base64"); // Convert base64 secret to buffer
// Your EC private key (P-256) for JWT signing
const ecPrivateKey = "<<REPLACE_HERE>>";
// API endpoint configuration
const API_PREFIX = "/api/v1/liquidity";
const BASE_URL = `https://api.mansafinance.co${API_PREFIX}`;
/**
* Builds authentication headers required for API requests
* Uses JWT with ES256 signing and HMAC-SHA512 body hashing for security
*/
function buildAuthHeaders(path, body = undefined) {
// Construct the full API path
const fullPath = `${API_PREFIX}${path}`;
// JWT timestamp claims (Unix timestamps)
const now = Math.floor(Date.now() / 1000);
const nbf = now - 1; // "Not before" - token valid from 1 second ago
const iat = now; // "Issued at" - current timestamp
const exp = iat + 20; // "Expires" - token expires in 20 seconds (short-lived)
// Prepare request body for hashing (empty object if no body provided)
const rawBody = body ? JSON.stringify(body) : "{}";
// Create HMAC-SHA512 hash of path + body + nbf timestamp
// This prevents replay attacks and ensures request integrity
const bodyHash = crypto
.createHmac("sha512", hmacSecret)
.update(fullPath + rawBody + nbf)
.digest("base64");
// JWT payload containing all necessary claims
const payload = {
sub: apiKey, // Subject - identifies the API client
uri: fullPath, // The API endpoint being accessed
nbf, // Not before timestamp
iat, // Issued at timestamp
exp, // Expiration timestamp
bodyHash // Hash of request content for integrity verification
};
// Sign the JWT using ES256 algorithm (ECDSA with P-256 and SHA-256)
const token = jwt.sign(payload, ecPrivateKey, {
algorithm: "ES256",
audience, // Intended recipient of the token
});
// Return headers required for authenticated requests
return {
"x-api-key": apiKey, // API key header
authorization: `Bearer ${token}`, // JWT bearer token
};
}
// HTTP client wrapper that automatically adds authentication headers
const request = {
get: (path, config = {}) =>
axios.get(`${BASE_URL}${path}`, {
...config,
headers: buildAuthHeaders(path), // Automatically add auth headers
}),
};
/**
* Main function demonstrating API usage
* Fetches active corridors with pagination
*/
async function main() {
try {
console.log("Fetching corridors...");
// API endpoint path
const path = "/corridors";
// Make authenticated GET request with query parameters
const response = await request.get(path, {
params: {
page: 1, // Pagination: first page
limit: 50, // Pagination: 50 items per page
status: "ACTIVE" // Filter: only active corridors
},
});
// Log successful response
console.log("Status:", response.status);
console.log("Corridors:", response.data);
} catch (err) {
// Handle errors with detailed logging
if (err.response) {
// API returned an error response
console.error("Error status:", err.response.status);
console.error("Error data:", err.response.data);
} else {
// Network or other request failure
console.error("Request failed:", err.message);
}
}
}
// Execute the main function
main();
This is a simplified example. In production, you’ll need to properly sign the JWT with your private key and handle all error cases.

