Skip to main content
The handshake is the only host route the mobile SDK needs for balance, ledger, and top-up. Debits still use a separate host route with jaza.consume.

Flow

  1. User signs in to your app
  2. App calls your POST /api/jaza/init (or similar)
  3. Host resolves customerId and calls jaza.init({ customerId })
  4. Host returns InitResult (sessionToken, wallet/features snapshot, expiry)
  5. JazaProvider stores the session and calls Jaza client APIs with the session JWT + publishable key
Keep the secret key on the server. The app only holds the publishable key and the short-lived session token returned by your BFF.

Host route

InitResult includes at least: Create the customer once at signup with jaza.createCustomer, then store customer.id on your user row.

Provider wiring

Prefer getSession: a function that hits your init route and returns InitResult.

authEndpoint alternative

Pass a URL instead of a function. The SDK POSTs that endpoint and expects the same InitResult JSON. If both are set, getSession wins.

Legacy getBalance

getBalance alone still works for older apps, but you should migrate to getSession / authEndpoint so top-up and ledger use the client session. Do not treat host-minted top-up JWTs (onRequestToken) as the primary path.

Session lifecycle

  • After init, the SDK refreshes wallet/ledger via client routes (GET /v1/client/wallet, etc.)
  • On 401 from a client API, the SDK re-runs the handshake once
  • If re-init fails → status UNAUTHENTICATED and onAuthError
  • Use useJaza().status (INITIALIZING | AUTHENTICATED | UNAUTHENTICATED | ERROR) to gate your UI

Security checklist

  • Secret key only on the host
  • Init route requires your app authentication
  • Never expose jaza.consume or secret-backed routes to the device as a public “debit” API without your own auth
  • UI gates (JazaActionButton) are not authorization — always consume on the server

Next