HSPay

Build on HSPay.

Connect your loan system, billing software or app to HSPay with signed server-to-server requests, and let us call you back with signed webhooks.

Every request is signed

Send your client id, a timestamp, a one-time nonce and an HMAC-SHA256 signature of the request with your secret. Requests that are old, replayed or altered are refused.

Sandbox first, then production

Create sandbox keys as soon as you sign up. Production keys are available once your business KYC is approved. Each key can be limited to what it needs.

Safe to retry

Send an Idempotency-Key with requests that change something. If the network drops and you send it again, nothing happens twice.

Webhooks you can trust

Events are sent to your HTTPS endpoint with an HSPay-Signature header. Failed deliveries are retried for a day — after 1 minute, 5 minutes, 30 minutes, 2, 6, 12 and 24 hours — and every attempt is logged.

Signing a request

Join six lines — method, path, sorted query, SHA-256 of the body, timestamp and nonce — and sign them with your secret.

// Node.js
const crypto = require('crypto');
const ts = Math.floor(Date.now() / 1000).toString();
const nonce = crypto.randomUUID();
const body = '';                      // exact bytes you send
const canonical = [
  'GET', '/api/v1/partner/company', '',
  crypto.createHash('sha256').update(body).digest('hex'),
  ts, nonce,
].join('\n');
const signature = crypto
  .createHmac('sha256', process.env.HSPAY_SECRET)
  .update(canonical).digest('hex');
// headers: X-Client-Id, X-Timestamp, X-Nonce, X-Signature

Checking a webhook

The header looks like t=1759312800,v1=…. Sign t + "." + raw body with your endpoint secret and compare.

const [t, v1] = header.split(',')
  .map((p) => p.split('=')[1]);
const expected = crypto
  .createHmac('sha256', endpointSecret)
  .update(`${t}.${rawBody}`).digest('hex');
const ok = crypto.timingSafeEqual(
  Buffer.from(expected), Buffer.from(v1));
// also reject if t is more than 5 minutes old

Available today

Company details, your retailers and their KYC status, and the event feed (KYC submitted, approved, sent back or rejected; retailer added). Mandate and collection endpoints arrive with the mandate launch — your keys, signing and webhooks stay the same.