USB HSM Vault API
Issue and claim physical bearer assets (USB Keys) for secure, offline, inter-bank settlements.
Introduction
The USB Vault API allows partner banks and financial institutions to issue and accept physical bearer assets (H-Keys) interoperably. This service operates on a dedicated endpoint and is designed for server-to-server communication.
Workflows: Inter-Bank Settlement
1. Issuance Workflow (Bank A)
When a partner bank (Bank A) wishes to create a USB key for its client, it calls the /issue endpoint. CashPay **immediately debits Bank A's fleet account** for the key's value plus any issuance fees. The funds are then "vaulted" in an isolated record within the central hardware_keys ledger. CashPay returns a signature and a ready-to-use file content. It is Bank A's responsibility to save this content as a .cpk file to deliver to its client.
2. Claim Workflow (Bank B)
When a bearer presents a USB key to another institution (Bank B), Bank B's system scans the .cpk file and calls the /claim endpoint with the extracted H-Key. CashPay verifies the key's signature, confirms it is active, and **instantly credits Bank B's fleet account** by releasing the vaulted funds. Bank B can then safely credit its customer's account.
Issue HSM Key
/api/v1/b2b/hsm/issueIssues a new hardware key signature and vaults the corresponding funds, debiting the partner's fleet account.
curl -X POST 'https://api.cashpay-all.com/api/v1/b2b/hsm/issue' \
-H 'Authorization: Bearer <YOUR_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000.00,
"currency": "USD",
"keyPin": "1234"
}'Success Response
{
"success": true,
"hsm_signature": "a1b2c3d4e5f6...",
"key_reference": "HSM-ISSU-ABCD",
"fileContent": "-----BEGIN CASH PAY KEY-----\nVERSION: 2.1\n..."
}Using the API Response to Generate the .cpk File
After a successful call to the /issue endpoint, you receive the full content of the .cpk file in the `fileContent` field. Your application is responsible for saving this content into a file and delivering it to the end user. This process can be done on your server or directly on the client-side.
Recommended Practice: ZIP Archive
Example Implementation
This example shows how to call the API and then use the response to generate a .zip archive containing the .cpk file.
import fs from 'fs';
import fetch from 'node-fetch';
import JSZip from 'jszip';
// Assume this is loaded from environment variables
const CASHPAY_API_KEY = 'YOUR_API_KEY';
async function generateHsmKey(amount, currency, pin) {
// 1. Call the CashPay API to get the signature and file content
const apiResponse = await fetch('https://api.cashpay-all.com/api/v1/b2b/hsm/issue', {
method: 'POST',
headers: {
'Authorization': `Bearer ${CASHPAY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ amount, currency, keyPin: pin })
});
const result = await apiResponse.json();
if (!result.success) {
throw new Error(`API Error: ${result.error}`);
}
const { hsm_signature, fileContent } = result;
// 2. You now have the full file content. Create a ZIP archive.
const zip = new JSZip();
zip.file(`${hsm_signature}.cpk`, fileContent);
const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' });
const zipFileName = `CashPay-Key-${hsm_signature.substring(0,8)}.zip`;
fs.writeFileSync(zipFileName, zipBuffer);
console.log(`File ${zipFileName} created successfully.`);
return { zipFileName };
}
// Example usage:
// generateHsmKey(1000, 'USD', '1234');Claim HSM Key
To claim a key, your application must first read the .cpk file (either directly or from within a .zip archive) to extract the unique signature. This signature is then sent to our API along with the user's PIN to validate and process the claim.
/api/v1/b2b/hsm/claimClaims the value of an active hardware key using its signature, crediting the claiming partner's fleet account.
How to Implement the Claim Process
The process involves two main steps: reading the file on your server, and then calling our API. Your frontend should provide a file upload interface for your user to select their .cpk or .zip file.
Example: Handling File Upload in Node.js (with Express & JSZip)
import express from 'express';
import multer from 'multer';
import JSZip from 'jszip';
import fetch from 'node-fetch';
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
// Function to parse the secure block and get the signature
function getSignatureFromCpk(fileContent) {
const secureMatch = fileContent.match(/\[SECURE-DATA-BLOCK\]\n([\s\S]*?)\n\[\/SECURE-DATA-BLOCK\]/);
if (!secureMatch || !secureMatch[1]) {
throw new Error("Invalid .cpk file format.");
}
const decoded = Buffer.from(secureMatch[1].trim(), 'base64').toString('utf-8');
const data = JSON.parse(decoded);
if (!data.h) {
throw new Error("Signature not found in .cpk payload.");
}
return data.h;
}
// The API route on your server to handle the claim
app.post('/claim-hsm-key', upload.single('hsmFile'), async (req, res) => {
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded.' });
}
const { pin } = req.body;
if (!pin) {
return res.status(400).json({ error: 'PIN is required.' });
}
try {
let cpkContent;
if (req.file.originalname.endsWith('.zip')) {
const zip = await JSZip.loadAsync(req.file.buffer);
const cpkFile = Object.values(zip.files).find(f => f.name.endsWith('.cpk'));
if (!cpkFile) throw new Error("No .cpk file found in ZIP archive.");
cpkContent = await cpkFile.async('string');
} else {
cpkContent = req.file.buffer.toString('utf-8');
}
const signature = getSignatureFromCpk(cpkContent);
// Now, call the CashPay API
const cashPayResponse = await fetch('https://api.cashpay-all.com/api/v1/b2b/hsm/claim', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CASHPAY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ signature: signature, keyPin: pin })
});
const cashPayResult = await cashPayResponse.json();
if (!cashPayResponse.ok) {
throw new Error(cashPayResult.error || 'Failed to claim key.');
}
res.json(cashPayResult);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Example frontend call to this route would be a multipart/form-data requestCheck Key Status
/api/v1/b2b/hsm/status/:signatureChecks the current status of a hardware key (active, claimed, or cancelled).
Example Response
{
"success": true,
"status": "active"
}Cancel HSM Key
/api/v1/b2b/hsm/:signature/cancelCancels an 'active' key that you have issued. The vaulted funds are returned to your fleet account.
Success Response
{
"success": true,
"message": "Clé HSM annulée et fonds remboursés."
}