Skip to content

SDK routes

Generated from openapi.yaml of games-api 0.7.0: 13 routes.

POST /v1/sdk/players

POST /v1/sdk/players

Terminal window
curl -X POST 'https://api.filudi.com/v1/sdk/players' \
-H 'content-type: application/json' \
-d '{
"site": "filudi",
"locale": "en"
}'

Create an anonymous player and its token

Credential: none. The route is public.

application/json, required.

PropertyTypeRequiredDescription
sitestringyesSite slug
localestringno
StatusBodyDescription
201PlayerWithTokenPlayer and token.
404ErrorUnknown resource.
429ErrorToo many requests. Headers: Retry-After.

POST /v1/sdk/game-tokens

POST /v1/sdk/game-tokens

Terminal window
curl -X POST 'https://api.filudi.com/v1/sdk/game-tokens' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \
-H 'content-type: application/json' \
-d '{
"game": "gloop"
}'

Exchange a player token for a token limited to one game (ADR 0013)

Called by the hub, never by a game. Refuses a game token. Limited to 240 per player per hour. A game token (fg1) is valid 24 hours on these routes, for its own game: GET /v1/sdk/players/me (emailMasked null, hasPassword false), /v1/sdk/saves/{gameId}, POST /v1/sdk/sessions, /v1/sdk/leaderboards/{gameId}/*, POST /v1/sdk/events (403 when an item names another game). Those routes answer 403 for another game. Every other route that needs a player answers 401.

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here.

application/json, required.

PropertyTypeRequiredDescription
gamestringyesGame slug
StatusBodyDescription
201GameTokenGame token.
401ErrorMissing or invalid token.
404ErrorUnknown resource.
429ErrorToo many requests. Headers: Retry-After.

GET /v1/sdk/players/me

GET /v1/sdk/players/me

Terminal window
curl 'https://api.filudi.com/v1/sdk/players/me' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN"

Current player

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only.

StatusBodyDescription
200PlayerPlayer.
401ErrorMissing or invalid token.

PATCH /v1/sdk/players/me

PATCH /v1/sdk/players/me

Terminal window
curl -X PATCH 'https://api.filudi.com/v1/sdk/players/me' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \
-H 'content-type: application/json' \
-d '{
"nickname": "string",
"locale": "en"
}'

Change nickname or locale

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here.

application/json, required.

PropertyTypeRequiredDescription
nicknamestringno3 to 20 characters; pattern ^[\p{L}\p{N} _.-]+$
localestringno
StatusBodyDescription
200PlayerUpdated player.
400ErrorValidation failed.
401ErrorMissing or invalid token.

POST /v1/sdk/sessions

POST /v1/sdk/sessions

Terminal window
curl -X POST 'https://api.filudi.com/v1/sdk/sessions' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \
-H 'content-type: application/json' \
-d '{
"gameId": "gloop",
"gameVersion": "1.0.0",
"host": "filudi"
}'

Open a play session and get the score-signing key

Called by gameplay.start(). The key is HMAC-SHA256(version secret, session id), base64url. Valid 6 hours. The API rejects scores submitted outside a session.

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only.

application/json, required.

PropertyTypeRequiredDescription
gameIdstringyesGame slug
gameVersionstringnoBundle version; defaults to the live one
hoststringnodefault "filudi"
StatusBodyDescription
201objectSession.
401ErrorMissing or invalid token.
404ErrorUnknown resource.
429ErrorToo many requests. Headers: Retry-After.
503noneRedis is down, no session can open.

Body of 201

PropertyTypeRequiredDescription
sessionIdstring (uuid)yes
sessionKeystringyes
expiresAtstring (date-time)yes

GET /v1/sdk/saves

GET /v1/sdk/saves

Terminal window
curl 'https://api.filudi.com/v1/sdk/saves' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN"

List the player’s saves (metadata only)

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here.

StatusBodyDescription
200SaveMeta[]Saves.

GET /v1/sdk/saves/{gameId}

GET /v1/sdk/saves/{gameId}

Terminal window
curl 'https://api.filudi.com/v1/sdk/saves/gloop' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN"

Read a save

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only.

NameInTypeRequiredDescription
gameIdpathstringyesGame slug
StatusBodyDescription
200SaveSave. Headers: ETag.
404ErrorUnknown resource.

PUT /v1/sdk/saves/{gameId}

PUT /v1/sdk/saves/{gameId}

Terminal window
curl -X PUT 'https://api.filudi.com/v1/sdk/saves/gloop' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \
-H 'if-match: string' \
-H 'content-type: application/json' \
-d '{
"version": 1,
"data": {}
}'

Write a save

If-Match carries the version the client last saw (0 for none). The server accepts when the new version is greater than the stored one and If-Match equals the stored version. Otherwise 409 with the server copy.

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only.

NameInTypeRequiredDescription
gameIdpathstringyesGame slug
If-MatchheaderstringyesStored version as a quoted integer, e.g. “12”

application/json, required.

PropertyTypeRequiredDescription
versionintegeryesat least 1
dataanyyesAny JSON value, 64 kB max serialized
StatusBodyDescription
200SaveMetaSaved. Headers: ETag.
400ErrorValidation failed.
404ErrorUnknown resource.
409SaveServerCopyServer has another version, or none yet (version 0).
413ErrorBody over the limit.

DELETE /v1/sdk/saves/{gameId}

DELETE /v1/sdk/saves/{gameId}

Terminal window
curl -X DELETE 'https://api.filudi.com/v1/sdk/saves/gloop' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN"

Delete a save

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only.

NameInTypeRequiredDescription
gameIdpathstringyesGame slug
StatusBodyDescription
204noneDeleted or absent.

GET /v1/sdk/leaderboards/{gameId}/{board}

GET /v1/sdk/leaderboards/{gameId}/{board}

Terminal window
curl 'https://api.filudi.com/v1/sdk/leaderboards/gloop/height' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN"

Top entries

Credential, optional: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only. Without a token the answer is the anonymous one.

NameInTypeRequiredDescription
gameIdpathstringyesGame slug
boardpathstringyespattern ^[a-z][a-z0-9_]{0,31}$
periodqueryone of "day", "week", "all"nodefault "all"
limitqueryintegerno1 to 50; default 10
StatusBodyDescription
200LeaderboardTopTop entries; isMe is set when a token is sent. Headers: Cache-Control.
404ErrorUnknown resource.

GET /v1/sdk/leaderboards/{gameId}/{board}/me

GET /v1/sdk/leaderboards/{gameId}/{board}/me

Terminal window
curl 'https://api.filudi.com/v1/sdk/leaderboards/gloop/height/me' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN"

The player’s own entry

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only.

NameInTypeRequiredDescription
gameIdpathstringyesGame slug
boardpathstringyespattern ^[a-z][a-z0-9_]{0,31}$
periodqueryone of "day", "week", "all"nodefault "all"
StatusBodyDescription
200objectEntry or null.

Body of 200

PropertyTypeRequiredDescription
periodPeriodyesdefault "all"
entryLeaderboardEntry or nullyes

POST /v1/sdk/leaderboards/{gameId}/{board}/scores

POST /v1/sdk/leaderboards/{gameId}/{board}/scores

Terminal window
curl -X POST 'https://api.filudi.com/v1/sdk/leaderboards/gloop/height/scores' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \
-H 'content-type: application/json' \
-d '{
"score": 0,
"meta": {
"en": "string"
},
"sessionId": "00000000-0000-0000-0000-000000000000",
"nonce": "string",
"ts": 0,
"sig": "string"
}'

Submit a signed score

sig = base64url(HMAC-SHA256(sessionKey, ${playerId}|${gameId}|${board}|${score}|${nonce}|${ts})). ts is unix milliseconds, within 5 minutes of server time. The API accepts a nonce once per session.

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only.

NameInTypeRequiredDescription
gameIdpathstringyesGame slug
boardpathstringyespattern ^[a-z][a-z0-9_]{0,31}$

application/json, required.

PropertyTypeRequiredDescription
scoreintegeryes
metaobjectno512 bytes max
meta.*string or numberno
sessionIdstring (uuid)yes
noncestringyes16 to 64 characters
tsintegeryes
sigstringyes
StatusBodyDescription
201objectAccepted.
400objectRejected.
429ErrorToo many requests. Headers: Retry-After.

Body of 201

PropertyTypeRequiredDescription
rankobjectyes0 when Redis could not rank the score; the next rebuild fixes it
rank.dayintegeryes
rank.weekintegeryes
rank.allintegeryes
bestbooleanyesNew personal best on this board

Body of 400

PropertyTypeRequiredDescription
error"invalid"yes
reasonone of "bounds", "signature", "session", "board", "nonce", "clock", "meta"yes
messagestringno

POST /v1/sdk/events

POST /v1/sdk/events

Terminal window
curl -X POST 'https://api.filudi.com/v1/sdk/events' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \
-H 'content-type: application/json' \
-d '{
"events": [
{
"name": "string",
"props": {
"en": "string"
},
"ts": 0,
"gameId": "gloop",
"gameVersion": "1.0.0",
"sessionId": "00000000-0000-0000-0000-000000000000",
"host": "string",
"locale": "en"
}
]
}'

Batch of events

The SDK sends application/json normally and the same JSON body as text/plain from a keepalive fetch on page hide (sendBeacon only on portals, without a token). The API parses both as JSON. 64 kB max. With a game token, an item that names another game refuses the whole batch with 403, and an item that names none takes the token’s game.

Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) also opens this route, for its own game only.

application/json, required, also accepted as text/plain. The body is a EventBatch.

PropertyTypeRequiredDescription
eventsEventIn[]yesat most 50 items
StatusBodyDescription
202noneQueued for write; the API drops invalid items and counts them in metrics.
400noneMore than 50 items, or a body that is not a batch.
401ErrorMissing or invalid token.
403ErrorNot allowed for this role or site.
413ErrorBody over the limit.
429ErrorToo many requests. Headers: Retry-After.