Skip to main content
PlaySmart uses JSON Web Tokens (JWT) signed with HS256 to authenticate API requests. When you register or log in, the API returns two tokens. You send the access token with every protected request, and use the refresh token to obtain new credentials when the access token expires.

Tokens

PlaySmart issues two tokens on every successful authentication:
TokenHeader claimExpiryPurpose
access_tokenAuthorization: Bearer30 daysAuthenticate API requests
refresh_token180 daysRe-authenticate after access token expiry
The access token’s sub claim contains the player’s auth_user_id. Protected endpoints read this claim to identify the caller. The refresh token carries a kind: "refresh" claim and is used solely to issue a new access token — pass it to /auth/login or a dedicated refresh endpoint as appropriate for your integration.
Tokens are not revocable server-side. If a token is compromised, it remains valid until it expires. Treat both tokens like passwords: store them in secure, device-local storage and never log or transmit them in plain text.

Register a new player

Send a POST request to /auth/register to create a player account. The deviceId you provide becomes the player’s permanent auth_user_id and is embedded as the JWT sub claim. Request fields
email
string
required
A valid email address. Must be unique across all players.
password
string
required
The player’s password. Minimum 8 characters.
deviceId
string
required
A stable, unique identifier for the player’s device. Stored as auth_user_id.
Example request
curl -X POST https://api.playsmart.io/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "player@example.com",
    "password": "hunter12345",
    "deviceId": "device-abc-123"
  }'
Example response201 Created
{
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiJ9...",
    "refresh_token": "eyJhbGciOiJIUzI1NiJ9...",
    "user": {
      "id": "device-abc-123",
      "email": "player@example.com",
      "pseudo": "",
      "total_games_completed": 0
    }
  }
}

Log in an existing player

Send a POST request to /auth/login with the player’s credentials. The response structure is identical to registration. Request fields
email
string
required
The player’s registered email address.
password
string
required
The player’s password.
Example request
curl -X POST https://api.playsmart.io/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "player@example.com",
    "password": "hunter12345"
  }'
Example response200 OK
{
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiJ9...",
    "refresh_token": "eyJhbGciOiJIUzI1NiJ9...",
    "user": {
      "id": "device-abc-123",
      "email": "player@example.com",
      "pseudo": "",
      "total_games_completed": 0
    }
  }
}

Using the access token

Pass the access_token in the Authorization header on every request to a protected endpoint:
curl https://api.playsmart.io/ingest/events \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..."
The API also accepts the token in an X-Forwarded-Authorization header, which takes precedence over Authorization when both are present.

Error responses

HTTP statuscodemessageCause
400 Bad RequestBAD_REQUESTinvalid_payloadRequest body is missing, malformed, or fails validation (e.g. password too short, invalid email)
401 UnauthorizedUNAUTHORIZEDinvalid_credentialsEmail not found, or password does not match
401 UnauthorizedUNAUTHORIZEDmissing_bearer_tokenProtected endpoint called without an Authorization header
409 ConflictCONFLICTemail_already_registeredA player with this email address already exists