Skip to content

Authentication

Every protected request sends Authorization: Bearer <token>. There are two distinct credentials:

Credential Issued to Used for
OAuth M2M access token Your trusted backend Server events, profile operations, purchases, and issuing client credentials
User-bound client credential Your authenticated browser or mobile user Scoring model, client event batches, and that user’s profile

Create an OAuth M2M client in the workspace for the intended environment. Request only the scopes that service needs. Exchange its ID and secret using HTTP Basic authentication:

Terminal window
curl --fail-with-body https://api.qa.streakline.dev/api/auth/oauth2/token \
--user "$STREAKLINE_CLIENT_ID:$STREAKLINE_CLIENT_SECRET" \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'resource=https://api.qa.streakline.dev' \
--data-urlencode 'scope=events:write profiles:read'

Requested scopes must be allowed for the client. The response includes access_token, token_type, expires_in, and scope information. Renew the token before its expiry by making another exchange; M2M tokens do not include a refresh token.

The TypeScript server SDK accepts a token or an async auth callback. It does not exchange client secrets, cache tokens, or renew them. Your backend’s token provider owns that lifecycle.

Scope Purpose
events:write Track single and batched server events
events:read Read a user’s event history
profiles:read Read a user’s profile and achievements
profiles:write Import existing user progress
profiles:delete Delete a user
store:purchase Purchase a configured store item
client_credentials:issue Issue a user-bound client credential

Use a separate backend OAuth client with client_credentials:issue. After authenticating a request in your application, derive the user’s internal UUID from the server session and issue their credential:

import { StreaklineServer } from "@streakline/sdk/server";
const issuer = new StreaklineServer({
baseUrl: "https://api.qa.streakline.dev",
auth: process.env.STREAKLINE_ISSUER_ACCESS_TOKEN!,
});
// Inside your authenticated backend route:
// session.user.internalId comes from your own verified session.
const credential = await issuer.createClientCredential({
userId: session.user.internalId,
});
// Return this structured response to the same authenticated user.

Client credentials expire after five minutes and are bound to one user, project, and environment. The web and React Native SDKs accept the full structured response, check its subject and expiry, and retry once with a new credential after a 401.

Keep server secrets and M2M access tokens out of browser and mobile bundles. The client SDK keeps the user-bound token in memory rather than persisting it.