Take a payment in the portal
A borrower signs in to the white-label portal, sees the authoritative amount due, and pays — with explicit authorization and idempotent submission that cannot double-charge.
On May 6, Maya signs in to the portal and pays the past-due $517.14 — keeping the promise she made to Nova five days earlier. The self-service API is borrower-scoped throughout: these calls run against the portal origin with a borrower session, not an operator token.
Sign in as the borrower
Borrower-scoped sessioncurl -X POST "$PORTAL_BASE/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{ "email": "maya@example.test", "password": "********" }'{ "sessionToken": "st_9a3...", "expiresAt": "2027-05-06T18:40:00Z", "stepUpRequiredFor": ["ADD_PAYMENT_METHOD", "SIGN_AGREEMENT"] }The session can only ever be Maya: short-lived, signed, rate-limited for the open internet. Sensitive operations demand one-time-code step-up on top of it.
Read the loan as the borrower sees it
Authoritative factscurl "$PORTAL_BASE/v1/loans/7204" \
-H "Authorization: Bearer st_9a3..."{
"loanRef": "7204",
"productName": "Harbor Personal Loan",
"status": "PAST_DUE",
"amountDue": { "amount": 517.14, "currency": "USD" },
"dueDate": "2027-04-12",
"paymentsMade": 7,
"paymentsTotal": 18,
"asOf": "2027-05-06T17:58:11Z"
}Every money fact comes from the authoritative core on this read — the portal UI derives nothing, and the progress figure counts payments made rather than re-computing dollars. Past-due renders amber in the shipped app, and no status rests on color alone.
Pay with idempotent submission
Cannot double-chargecurl -X POST "$PORTAL_BASE/v1/loans/7204/payments" \
-H "Authorization: Bearer st_9a3..." \
-H "Idempotency-Key: portal-hbr-2027-05-06-1" \
-H "Content-Type: application/json" \
-d '{
"amount": { "amount": 517.14, "currency": "USD" },
"paymentMethodId": 705,
"authorization": { "acknowledged": true, "acknowledgedAt": "2027-05-06T18:01:40Z" }
}'{ "paymentRef": "9014", "status": "PROCESSING", "receiptRef": "rcpt-9014", "submittedAt": "2027-05-06T18:01:41Z" }The key is caller-minted and reused across retries — a network blip replays to the original result instead of a second charge. Authorization is explicit and recorded; the payment settles and posts through the same pipeline as any other, and the posting event is what marks Maya’s promise KEPT.