Skip to main content

Authentication

The Betflow B2B API supports two authentication methods: API Key and OAuth2 Client Credentials. Your account is configured for one or both methods during onboarding.

Authentication Methods

Each account has an authentication method setting that determines which flows are available. This is configured by your administrator during onboarding.

Auth MethodAPI Key (X-API-Key)Bearer Token (Authorization: Bearer)OAuth Login (/v1/oauth/login)API Key Login (/v1/auth/login)
api_key
oauth
both
  • api_key — You can call the API directly with your API key in the X-API-Key header, or exchange it for a JWT token pair via /v1/auth/login and use Bearer tokens. OAuth login is not available.
  • oauth — You must use your client_id and client_secret to obtain a JWT token pair via /v1/oauth/login, then call the API with Bearer tokens. Direct API key usage is not available.
  • both — All authentication flows are available. You can use API keys directly, exchange them for tokens, or use OAuth client credentials.
info

To check which method your account uses, call GET /v1/account/config — the auth_method field shows your current setting. Attempting to use a flow that isn't enabled for your account will result in a 401 Unauthorized response.

API Key Authentication

The simplest way to authenticate. Send your API key with every request:

curl https://api.odditt.com/v1/references/sports \
-H "X-API-Key: YOUR_API_KEY"

You can also exchange your API key for a JWT token pair if you prefer token-based authentication:

curl -X POST https://api.odditt.com/v1/auth/login \
-H "X-API-Key: YOUR_API_KEY"

OAuth2 Client Credentials

For OAuth2 authentication, exchange your client_id and client_secret for a JWT token pair:

curl -X POST https://api.odditt.com/v1/oauth/login \
-H "Content-Type: application/json" \
-d '{
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}'

Response

Both login endpoints return the same token pair:

{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "dGhpcyBpcyBhIHJlZnJl...",
"token_type": "Bearer",
"expires_at": "2026-03-17T16:15:00Z",
"expires_in": 900
}
FieldDescription
access_tokenJWT token to use in the Authorization header
refresh_tokenOpaque token used to obtain new access tokens
token_typeAlways Bearer
expires_atISO 8601 timestamp of when the access token expires
expires_inAccess token TTL in seconds

Using Access Tokens

Once you have an access token, include it in the Authorization header:

curl https://api.odditt.com/v1/trends/mixed-flows \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"sport_id": 1, "league_id": 7, "page": 1, "page_size": 10}'

Refreshing Tokens

Access tokens expire after the duration indicated in expires_in. Before or after expiry, use the refresh token to get a new token pair without re-sending your credentials.

API key flow:

curl -X POST https://api.odditt.com/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "YOUR_REFRESH_TOKEN"}'

OAuth flow:

curl -X POST https://api.odditt.com/v1/oauth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "YOUR_REFRESH_TOKEN"}'

Refresh Token Rotation

The API uses refresh token rotation for security:

  • Each refresh request returns a new refresh token.
  • The old refresh token is immediately revoked.
  • Always store and use the latest refresh token.
Login → access_token_1 + refresh_token_1
Refresh (refresh_token_1) → access_token_2 + refresh_token_2 (refresh_token_1 is now revoked)
Refresh (refresh_token_2) → access_token_3 + refresh_token_3 (refresh_token_2 is now revoked)
warning

If you attempt to use an already-revoked refresh token, the request will fail with a 401 response. You will need to re-authenticate using your API key or client credentials.

JWT Claims

The access token is a standard JWT (HS256) containing:

ClaimDescription
client_idYour client identifier (UUID)
tenant_idYour tenant identifier (UUID)
tierYour account tier (free, pro, enterprise)
issToken issuer
subSubject (same as client_id)
iatIssued at timestamp
expExpiration timestamp
┌──────────────┐
│ Your App │
└──────┬───────┘

│ 1. POST /v1/oauth/login (or /v1/auth/login)

┌──────────────┐
│ Betflow API │ → Returns access_token + refresh_token
└──────┬───────┘

│ 2. Use access_token for API calls
│ Authorization: Bearer <access_token>

┌──────────────┐
│ Betflow API │ → Returns data
└──────┬───────┘

│ 3. When access_token expires:
│ POST /v1/oauth/refresh (or /v1/auth/refresh)

┌──────────────┐
│ Betflow API │ → Returns NEW access_token + refresh_token
└──────────────┘

Best Practices

  1. Store tokens securely — never expose access tokens or refresh tokens in client-side code, URLs, or logs.
  2. Refresh proactively — refresh your access token before it expires to avoid failed requests. Use the expires_in or expires_at field to schedule refreshes.
  3. Handle 401 gracefully — if you receive a 401, attempt a token refresh. If the refresh also fails, re-authenticate with your credentials.
  4. Use Bearer tokens in production — while API keys work on every request, using JWT tokens reduces how often your API key is sent over the wire.