Skip to content

Errors

Every error is JSON with two fields and sometimes a third:

{
"error": "invalid",
"message": "nickname: 3 to 20 characters.",
"details": { "field": "nickname" }
}

error is one of nine codes. message is written for the developer who reads the response, in English, and says what failed. details is present when the API has something structured to add, such as the field at fault.

Read an error

Terminal window
curl -s -o body.json -w '%{http_code}\n' \
-X PATCH 'https://api.filudi.com/v1/sdk/players/me' \
-H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \
-H 'content-type: application/json' \
-d '{ "nickname": "a" }'
cat body.json
CodeStatusWhen
invalid400The body or a parameter breaks the schema. message names the field
unauthorized401No credential, or one the API refuses. For a player token: forget it and create a new guest
forbidden403The credential is valid and does not open this action: another game’s token, a role, a scope, an origin
not_found404Unknown resource, or one your credential may not see. An unknown site slug and a game outside a site’s catalog answer this too
conflict409The state refuses the change: a slug taken, a version already live, a quota reached
too_large413The body is over the route’s limit (64 kB for a save or an event batch)
rate_limited429Too many requests. Retry-After says how many seconds to wait; see Rate limits
unavailable503A dependency is down, usually Redis. Retry in a few seconds; Retry-After is set when the API knows
internal500An unexpected failure. The API logged it

The write routes of the admin API answer 400 invalid, 403 forbidden, 404 not_found and 409 conflict with this shape even where the reference lists only the success code.

PUT /v1/sdk/saves/{gameId} answers 409 with the server’s copy of the save, not an error: { gameId, version, etag, bytes, updatedAt, data }, with version 0 and data null when nothing is stored yet. Take it, merge if the game can, and write again with If-Match set to that version.

POST /v1/sdk/leaderboards/{gameId}/{board}/scores answers 400 with { error: "invalid", reason, message }. reason is one of bounds, signature, session, board, nonce, clock, meta, so a game logs why a score was refused.

  • details.field: "current" on a 401 of PUT /v1/account/password and PUT /v1/console/password: the session or token is fine, the current password is wrong. Keep the token.
  • The issue code game_host on a 400 of POST /v1/admin/sites and its PATCH: a domain is on or under the play domain, where no site may run.
  • A 403 of PUT /v1/admin/sites/{siteId}/catalog/{gameId} carries in message why the site may not list the game: pending, no live version, or first_party on a site that is not first-party.