Authentication
A bettor authenticates once per session. Your backend mints a session_request_id, the platform
exchanges it for a platform JWT, and your frontend sends that JWT on every bettor request.
The exchange is the same one the widget performs. Only the caller changes.
The flow
The diagram routes the exchange through your backend. A browser can call
POST /api/v1/auth/session itself instead, which removes the middle hop.
Exchange a session request for a platform JWT
Send both fields. partner_slug is required, and omitting it fails the exchange.
curl -X POST https://<your predictions host>/api/v1/auth/session \
-H "Content-Type: application/json" \
-d '{
"session_request_id": "sreq_01HZABC...",
"partner_slug": "your-partner-slug"
}'
{
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"bettor_id": "789e4567-e89b-12d3-a456-426614174999",
"account_id": "player-12345",
"currency": "USD"
}
| Field | Type | Description |
|---|---|---|
token | string | Platform JWT, RS256, valid for 24 hours |
bettor_id | uuid | The bettor's identifier on the platform |
account_id | string | Your own player identifier, returned by your auth endpoint |
currency | string | ISO 4217 code, fixed for the life of the session |
Send the platform JWT on every bettor request
The token travels in the Authorization header, as Bearer <token>. The platform does not
accept cookie credentials cross-origin, so a cookie session is not an option.
Read the bettor's identity and balance
curl https://<your predictions host>/api/v1/auth/me \
-H "Authorization: Bearer <token>"
{
"account_id": "player-12345",
"currency": "USD",
"balance": "125.50"
}
balance has three states. A decimal string is a real balance. "0" means no funds. null
means your wallet did not report one. The balance is advisory: the platform stays authoritative
on insufficient funds when it debits the stake.
Call this endpoint again after any failed bet placement. It is the only signal that a rolled-back stake returned to the bettor.
Handle a 401
Any 401 means the same thing: run the exchange again with a fresh session_request_id. A 401
arrives with an empty body, so do not branch on its content.
Plan for the token lifetime
The platform JWT is valid for 24 hours. Renew a session by running the exchange again, so keep
the path that mints a session_request_id reachable after the first page load.
A session_request_id is single-use and short-lived, so a failed exchange has one answer: mint a
fresh id and exchange it once more. Show a general error if the second attempt also fails.
Do not branch your recovery on the response status.