Developers

A small integration, with the bank in control.

Expose two adapter endpoints, receive signed events, and choose how customers see HathPay: our embedded module in your app, or your own screens on our APIs.

Option A · fastest

Embedded module

Your backend opens a short-lived session and your app shows the HathPay module in a web view. Activation, PIN, limits, pause, history and removal are ready-made and carry your colours.

  • One server call opens a session
  • Your theme on every screen
  • Status changes pushed back to your app
Option B · full control

Headless partner API

Build every screen yourself and call the partner API for customers, limits, pause and history. Every event arrives as a signed webhook for your app and records.

  • The same capabilities as the module
  • You own every pixel
  • Native SDKs for a signed partner
In code

Signed both ways. Safe to retry.

Every request in either direction carries a timestamp, a single-use nonce and an HMAC-SHA256 signature. A repeated request is refused as a replay. A retried payment is recognised by its idempotency key and never charged twice.

  • Open a sessionAfter your own login, one call returns a token for the in-app module.
  • Decide every paymentYour adapter receives authorise-debit and returns approved or declined.
  • Verify every eventCheck the signature, the window and the nonce before you act on it.
# Your backend, after your own login
import hashlib, hmac, json, secrets, time, httpx

def signed(method, path, payload):
    body = json.dumps(payload).encode()
    ts, nonce = str(int(time.time())), secrets.token_hex(12)
    msg = f"{ts}\n{nonce}\n{method}\n{path}\n" + hashlib.sha256(body).hexdigest()
    sig = hmac.new(PARTNER_SECRET, msg.encode(), hashlib.sha256).hexdigest()
    return httpx.request(method, HATHPAY + path, content=body, headers={
        "X-HathPay-Bank": BANK_ID, "X-HathPay-Timestamp": ts,
        "X-HathPay-Nonce": nonce, "X-HathPay-Signature": sig})

r = signed("POST", "/v1/partner/sessions", {
    "customer_ref": customer.ref,
    "accounts": [{"account_token": a.token, "label": a.label}
                 for a in customer.accounts],
    "purpose": "activate",
})
session_token = r.json()["session_token"]   # hand to the in-app module
Python · illustrativeA reference bank is included to test against
The contract

Every call between you and HathPay.

Short on purpose. The money path is two endpoints on your side.

DirectionEndpointWhat it does
Bank → HathPayPOST /v1/partner/sessionsOpen a module session for a customer you have signed in.
Bank → HathPayGET /v1/partner/customers/{ref}HathPay status, linked account and limits for one customer.
Bank → HathPayPOST …/customers/{ref}/pause · /resumeStop or restart palm payments for a customer.
Bank → HathPayPUT …/customers/{ref}/limitsSet per-payment and daily limits within your caps.
Bank → HathPayGET …/customers/{ref}/transactionsPalm payment history for statements and support.
Bank → HathPayDELETE /v1/partner/customers/{ref}Remove HathPay for a customer and delete their templates.
HathPay → BankPOST {adapter}/authorize-debitApprove or decline one palm payment. You move the money.
HathPay → BankPOST {adapter}/reverseUndo an approved debit when a later step fails.
HathPay → BankPOST {webhook}Signed events: enrollment.completed, payment.authorized, payment.declined, customer.paused and more.
Architecture

Every surface is signed. Every decision is logged.

Three kinds of client talk to HathPay, each with its own credential. HathPay talks to the bank through two narrow contracts: the adapter the bank exposes, and the events it receives.

HathPay architecture Channels (bank app module, branch enrolment terminal, merchant terminal) connect to HathPay's API gateway. Inside the platform are the biometric service, risk engine, device trust, orchestrator, audit ledger and webhook outbox over separate data stores. The bank's backend opens sessions through the partner API; the orchestrator calls the bank adapter; the outbox delivers signed events to the bank. CHANNELS HATHPAY PLATFORM YOUR BANK Bank app · HathPay moduleactivate · limits · pause Branch enrolment terminalNIR 850 nm · guided captureown key · P-256 Merchant terminalamount · palm · PINown key · P-256 API GATEWAY Biometric servicequality · 1:N matchduplicate check Risk enginelimits · velocityPIN step-up Device trustapproval · healthrevocation Orchestratoridempotency · retriesreversal Audit ledgerhash-chainedverifiable Webhook outboxsigned · retriedin order separate stores · templates · operations · payments Bank backendopens module sessions Bank adapterPOST authorize-debitPOST reverse Webhook receiverpayments · enrolmentstatus changes core banking · rails session signed signed partner API · HMAC-SHA256 · nonce · 300 s signed signed

Scroll sideways to see the whole diagram.

API gateway

Four separate surfaces: partner, embedded, device and operations. A credential for one opens nothing on another.

rate-limited per terminal

Biometric service

Checks each capture, normalises the palm region, extracts features and searches the bank's gallery.

stores templates, never images

Risk engine

Bank and customer limits, velocity rules, PIN step-up and lockout, and a cooldown for terminals presenting unknown palms.

every rule outcome recorded

Device trust

Terminals generate their own keys and need approval before they work. Enrolment and merchant terminals cannot stand in for each other.

ECDSA P-256 · revocable

Orchestrator

Turns an identified palm into exactly one authorisation request. Idempotency keys stop double charges; failures trigger reversal.

2-minute payment window

Audit and events

A hash-chained log shows any altered row. Events reach the bank as signed webhooks, retried until delivered.

verifiable from the console

See it working, end to end, in thirty minutes.

Activation in a bank app, enrolment at a branch terminal and a palm payment settled through a simulated bank. Then the architecture and the pilot plan.