Payer sessions
The separate payer OpenAPI 0.5.0 and generated/payer-typescript SDK expose fresh device/passcode unlock and protected session endpoints. Enrollment still returns session_issued=false. Request POST /v1/payer/unlock-challenges with {device_id, passcode} and a mutation UUID; sign the returned UNLOCK challenge with the enrolled P-256 key and complete /{id}/complete with {passcode, signature} and a second mutation UUID. Passcode is a six-digit string, never an issuer PIN. The challenge expires after 120 seconds. Keep exact requests/UUIDs across uncertain responses; completion retries preserve one session and cannot bypass expiry or revocation.
The payer API runs only in the local sandbox: the hosted sandbox does not serve it yet.
Opening a session requires the already enrolled device and the Futa passcode. Five wrong passcodes in fifteen minutes lock unlocking for fifteen minutes; a new challenge or an SMS does not reset that limit. The additional limits per device and source also persist. A temporary saturation returns 503: retry the same request. These settings are a local test policy.
The response contains an opaque access_token, token_type=DPoP, session/payer/device IDs, a server nonce and deadlines. Use exactly one Authorization: DPoP <token> and one DPoP: <signed JWS> header. Every request needs a fresh UUIDv4 jti, ES256 signature, public enrolled JWK, actual uppercase method, trusted query-free URL, integer current time, base64url SHA-256 token hash and server nonce. Unlock signatures use DER; DPoP uses JOSE 64-byte R||S. The SDK supplies transport types only: generate a fresh proof per HTTP attempt with request overrides; never put a reusable proof into static configuration. Keep token/key material in platform-protected storage and out of logs.
GET /v1/payer/session reads the session’s metadata without extending it. POST /v1/payer/session/activity, with {} and an Idempotency-Key UUID, records an explicit foreground activity. A retry uses the same logical UUID and a new proof; it does not extend the timeout a second time. Reads, background tasks and nonce requests are not user activity.
A valid token/device signature with an expired or unknown nonce receives 401 DPOP_NONCE_REQUIRED and DPoP-Nonce / WWW-Authenticate headers. Retry once using the new nonce and a fresh proof. Nonces last 60 seconds and issuance is limited to five per session/minute. Reused proofs fail. Five minutes without explicit activity or one hour since issuance requires unlock again; there is no refresh token or bearer fallback.
POST /v1/payer/session/sign-out, with {} and a UUID, revokes the session immediately. Any later use, including another sign-out attempt, returns 401 INVALID_SESSION. Clear local credentials even if the sign-out response is lost. Android and iOS implement proofs and secure storage separately; Android keeps Retrofit, Room and Hilt.
Only synthetic loopback identity is available. Sessions do not authorize money movement. The security alert inbox now records first-device login events with synthetic receipts. Remote-device sign-out now revokes an already-trusted target device and its sessions. Additional-device enrollment, recovery, issuer linking and native journeys follow separately. Live providers, TLS deployment, hardware attestation and external security review remain release gates.