Partner Handoff
Partner Handoff lets you drop a user who is already signed in to your application straight into the Kora Remittance flow — landing on the dashboard with an active session, without a second phone/OTP login. It is the recommended way to minimise drop-off when embedding transfers.
How it works
┌──────────────┐ 1. mint ┌────────────────┐
│ Your backend │─────────────▶│ Kora auth │
│ │◀─────────────│ /partner-token │
└──────┬───────┘ {token,url} └────────────────┘
│ 2. redirect browser to redirectUrl
▼
┌──────────────┐ 3. exchange ┌────────────────┐
│ /handoff │─────────────▶│ Kora auth │
│ (hosted UI) │◀─────────────│ /exchange-token│
└──────┬───────┘ {session} └────────────────┘
│ 4. land on dashboard (signed in)
▼
Transfer flow
- Your backend mints a one-time handoff token.
- You redirect the user's browser to the returned URL.
- The hosted handoff page exchanges the token for a session.
- The user lands in the dashboard, already authenticated.
Step 1: Mint a handoff token
Call from your backend with your partner key. The token is one-time-use and short-lived.
curl -X POST "https://api.korastratum.com/api/v1/remittance/auth/partner-token" \
-H "X-Partner-API-Key: $KORA_PARTNER_KEY" \
-H "Content-Type: application/json" \
-d '{
"partnerUserId": "usr_abc123",
"phone": "+15551234567",
"email": "user@example.com",
"firstName": "Alex",
"lastName": "Rivera",
"countryCode": "US",
"returnUrl": "https://app.yourbrand.com/wallet",
"context": { "cashOutBalanceUsd": "25.00" }
}'
| Field | Required | Notes |
|---|---|---|
partnerUserId | yes | Your stable id for the user; links to the Kora user across handoffs |
phone / email | recommended | Used to match or create the Kora user |
firstName / lastName / countryCode / dateOfBirth | optional | Pre-fills the profile |
returnUrl | optional | Where "back to your app" links go; must pass your allowlist (https by default) |
context | optional | Arbitrary values passed through to the flow (e.g. a cash-out amount to pre-fill) |
Response:
{
"token": "<one-time-jwt>",
"redirectUrl": "https://app.yourbrand.com/handoff?t=<one-time-jwt>",
"expiresIn": 120
}
Step 2: Redirect the user
Send the user's browser to redirectUrl. The hosted handoff page reads the token from the query string and immediately exchanges it, so it never persists in browser history.
Step 3: Exchange (handled for you)
The hosted /handoff page calls POST /auth/exchange-token with the token and receives a normal session. If you build your own handoff page instead of using the hosted one, exchange it yourself:
curl -X POST "https://api.korastratum.com/api/v1/remittance/auth/exchange-token" \
-H "Content-Type: application/json" \
-d '{ "token": "<one-time-jwt>" }'
The response is a session (token, refreshToken, expiresIn) you use as the end-user session token for creating transfers and listing history.
Handoff establishes a session; it does not bypass compliance. A user who has not completed KYC will still be routed through identity verification before a transfer can settle.
Security notes
- Handoff tokens are one-time-use and expire in ~2 minutes.
returnUrlis validated against your tenant's allowlist before the token is signed. By default onlyhttpstargets are accepted; contact us to allowlist a custom scheme or host (e.g. a deep link back into your mobile app).- The partner key is a server-side secret — never ship it in a client.