Account routes
Generated from openapi.yaml of games-api 0.7.0: 8 routes.
POST /v1/account/magic-link: Email a sign-in linkPOST /v1/account/magic-link/consume: Exchange the link token for an account player tokenPOST /v1/account/magic-link/consume-code: Exchange the code of a sign-in email for an account player tokenPOST /v1/account/sign-in: Sign in with email and passwordPUT /v1/account/password: Set or change the account’s passwordDELETE /v1/account/password: Remove the password; the account signs in by link or code onlyGET /v1/account/export: Everything stored about the playerDELETE /v1/account: Delete the player and all data
POST /v1/account/magic-link
curl -X POST 'https://api.filudi.com/v1/account/magic-link' \ -H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \ -H 'content-type: application/json' \ -d '{ "email": "you@example.com", "redirect": "string"}'// playerToken: the fp1 token of POST /v1/sdk/playersconst response = await fetch('https://api.filudi.com/v1/account/magic-link', { method: 'POST', headers: { authorization: `Bearer ${playerToken}`, 'content-type': 'application/json' }, body: JSON.stringify({ email: 'you@example.com', redirect: 'string', }),});// No body: check response.ok.import requests
# player_token: the fp1 token of POST /v1/sdk/playersresponse = requests.post( 'https://api.filudi.com/v1/account/magic-link', headers={'authorization': f'Bearer {player_token}'}, json={ 'email': 'you@example.com', 'redirect': 'string', },)response.raise_for_status()# No body: the status says it all.Email a sign-in link
Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here.
Request body
Section titled “Request body”application/json, required.
| Property | Type | Required | Description |
|---|---|---|---|
email | string (email) | yes | |
redirect | string | no | Path on the site to return to after verification |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
| 202 | none | Sent, or silently not sent for an unknown reason the client must not learn. |
| 403 | none | Accounts are off for this site. |
| 429 | Error | Too many requests. Headers: Retry-After. |
POST /v1/account/magic-link/consume
curl -X POST 'https://api.filudi.com/v1/account/magic-link/consume' \ -H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \ -H 'content-type: application/json' \ -d '{ "token": "string"}'// playerToken: the fp1 token of POST /v1/sdk/playersconst response = await fetch('https://api.filudi.com/v1/account/magic-link/consume', { method: 'POST', headers: { authorization: `Bearer ${playerToken}`, 'content-type': 'application/json' }, body: JSON.stringify({ token: 'string', }),});const data = await response.json();import requests
# player_token: the fp1 token of POST /v1/sdk/playersresponse = requests.post( 'https://api.filudi.com/v1/account/magic-link/consume', headers={'authorization': f'Bearer {player_token}'}, json={ 'token': 'string', },)response.raise_for_status()data = response.json()Exchange the link token for an account player token
With a guest token, the API merges the guest into the account player (ADR 0005).
Credential, optional: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here. Without a token the answer is the anonymous one.
Request body
Section titled “Request body”application/json, required.
| Property | Type | Required | Description |
|---|---|---|---|
token | string | yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
| 200 | ConsumeResponse | Account player and token. |
| 400 | none | Link expired, used or unknown. |
| 403 | none | Accounts are off for this site. |
POST /v1/account/magic-link/consume-code
curl -X POST 'https://api.filudi.com/v1/account/magic-link/consume-code' \ -H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \ -H 'content-type: application/json' \ -d '{ "email": "you@example.com", "code": "string", "site": "filudi"}'// playerToken: the fp1 token of POST /v1/sdk/playersconst response = await fetch('https://api.filudi.com/v1/account/magic-link/consume-code', { method: 'POST', headers: { authorization: `Bearer ${playerToken}`, 'content-type': 'application/json' }, body: JSON.stringify({ email: 'you@example.com', code: 'string', site: 'filudi', }),});const data = await response.json();import requests
# player_token: the fp1 token of POST /v1/sdk/playersresponse = requests.post( 'https://api.filudi.com/v1/account/magic-link/consume-code', headers={'authorization': f'Bearer {player_token}'}, json={ 'email': 'you@example.com', 'code': 'string', 'site': 'filudi', },)response.raise_for_status()data = response.json()Exchange the code of a sign-in email for an account player token
Same effect as consuming the link (ADR 0011). The page that asked for the link sends the 6-digit
code the email shows; spaces are ignored. The API checks it against the most recent link of this
email on the site that is neither consumed nor expired. The fifth wrong code burns that link.
The site is the token’s; without a token, site names it. An invalid or dead bearer counts as no
token, and site is then required. redirect is never set: it travels inside the link, not with
the code. 20 attempts per IP per hour.
Credential, optional: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here. Without a token the answer is the anonymous one.
Request body
Section titled “Request body”application/json, required.
| Property | Type | Required | Description |
|---|---|---|---|
email | string (email) | yes | |
code | string | yes | Six digits, “123456” or “123 456”; pattern ^[0-9 ]{6,7}$ |
site | string | no | Site slug. Required without a player token; with one, it must be the token’s site |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
| 200 | ConsumeResponse | Account player and token. |
| 400 | Error | “This code is wrong, expired or already used. Ask for a new email.” Also a missing or mismatched site, and an account scheduled for deletion. |
| 403 | none | Accounts are off for this site. |
| 404 | none | Unknown site slug. |
| 429 | Error | Too many requests. Headers: Retry-After. |
| 503 | none | Redis is down; the rate limit cannot be checked. |
POST /v1/account/sign-in
curl -X POST 'https://api.filudi.com/v1/account/sign-in' \ -H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \ -H 'content-type: application/json' \ -d '{ "email": "you@example.com", "password": "string", "site": "filudi"}'// playerToken: the fp1 token of POST /v1/sdk/playersconst response = await fetch('https://api.filudi.com/v1/account/sign-in', { method: 'POST', headers: { authorization: `Bearer ${playerToken}`, 'content-type': 'application/json' }, body: JSON.stringify({ email: 'you@example.com', password: 'string', site: 'filudi', }),});const data = await response.json();import requests
# player_token: the fp1 token of POST /v1/sdk/playersresponse = requests.post( 'https://api.filudi.com/v1/account/sign-in', headers={'authorization': f'Bearer {player_token}'}, json={ 'email': 'you@example.com', 'password': 'string', 'site': 'filudi', },)response.raise_for_status()data = response.json()Sign in with email and password
For an account that set a password (ADR 0011). With a guest token of the site, the API merges the
guest into the account as consume does. An unknown email, an account without a password and a
wrong password get the same 401 in the same time. The site is the token’s; without a token,
site names it. An invalid or dead bearer counts as no token, and site is then required.
10 attempts per email per 15 minutes and 30 per IP per hour, right or wrong.
Credential, optional: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here. Without a token the answer is the anonymous one.
Request body
Section titled “Request body”application/json, required.
| Property | Type | Required | Description |
|---|---|---|---|
email | string (email) | yes | |
password | string | yes | A password over 128 characters answers 401; the 8 to 128 rule applies when it is set; 1 to 1024 characters; write only |
site | string | no | Site slug. Required without a player token; with one, it must be the token’s site |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
| 200 | ConsumeResponse | Account player and token. |
| 400 | Error | A missing or mismatched site, or an account scheduled for deletion. |
| 401 | Error | “Email or password is wrong.”. |
| 403 | none | Accounts are off for this site. |
| 404 | none | Unknown site slug. |
| 429 | Error | Too many requests. Headers: Retry-After. |
| 503 | none | Redis is down; the rate limit cannot be checked. |
PUT /v1/account/password
curl -X PUT 'https://api.filudi.com/v1/account/password' \ -H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \ -H 'content-type: application/json' \ -d '{ "password": "string", "current": "string"}'// playerToken: the fp1 token of POST /v1/sdk/playersconst response = await fetch('https://api.filudi.com/v1/account/password', { method: 'PUT', headers: { authorization: `Bearer ${playerToken}`, 'content-type': 'application/json' }, body: JSON.stringify({ password: 'string', current: 'string', }),});// No body: check response.ok.import requests
# player_token: the fp1 token of POST /v1/sdk/playersresponse = requests.put( 'https://api.filudi.com/v1/account/password', headers={'authorization': f'Bearer {player_token}'}, json={ 'password': 'string', 'current': 'string', },)response.raise_for_status()# No body: the status says it all.Set or change the account’s password
Account players only (ADR 0011). 8 to 128 characters after NFC normalization, not equal to the
account’s email (case-insensitive), no other rule. When a password exists, current is required
and checked. 20 attempts per player per hour, right or wrong. Other devices stay signed in.
Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here.
Request body
Section titled “Request body”application/json, required.
| Property | Type | Required | Description |
|---|---|---|---|
password | string | yes | 8 to 128 characters; write only |
current | string | no | Required when the account has a password; 1 to 128 characters; write only |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
| 204 | none | Saved. |
| 400 | Error | Validation failed. |
| 401 | Error | Missing or invalid token, or current is wrong; then the body carries details: { field: "current" }. |
| 403 | none | A guest: “Add your email first: a password needs an account.”. |
| 429 | Error | Too many requests. Headers: Retry-After. |
| 503 | none | Redis is down; the rate limit cannot be checked. |
DELETE /v1/account/password
curl -X DELETE 'https://api.filudi.com/v1/account/password' \ -H "authorization: Bearer $FILUDI_PLAYER_TOKEN"// playerToken: the fp1 token of POST /v1/sdk/playersconst response = await fetch('https://api.filudi.com/v1/account/password', { method: 'DELETE', headers: { authorization: `Bearer ${playerToken}` },});// No body: check response.ok.import requests
# player_token: the fp1 token of POST /v1/sdk/playersresponse = requests.delete( 'https://api.filudi.com/v1/account/password', headers={'authorization': f'Bearer {player_token}'},)response.raise_for_status()# No body: the status says it all.Remove the password; the account signs in by link or code only
Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here.
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
| 204 | none | Removed. |
| 401 | Error | Missing or invalid token. |
| 403 | none | A guest has no password. |
GET /v1/account/export
curl 'https://api.filudi.com/v1/account/export' \ -H "authorization: Bearer $FILUDI_PLAYER_TOKEN"// playerToken: the fp1 token of POST /v1/sdk/playersconst response = await fetch('https://api.filudi.com/v1/account/export', { headers: { authorization: `Bearer ${playerToken}` },});const data = await response.json();import requests
# player_token: the fp1 token of POST /v1/sdk/playersresponse = requests.get( 'https://api.filudi.com/v1/account/export', headers={'authorization': f'Bearer {player_token}'},)response.raise_for_status()data = response.json()Everything stored about the player
Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here.
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
| 200 | PlayerExport | JSON file. Headers: Content-Disposition. |
DELETE /v1/account
curl -X DELETE 'https://api.filudi.com/v1/account' \ -H "authorization: Bearer $FILUDI_PLAYER_TOKEN"// playerToken: the fp1 token of POST /v1/sdk/playersconst response = await fetch('https://api.filudi.com/v1/account', { method: 'DELETE', headers: { authorization: `Bearer ${playerToken}` },});// No body: check response.ok.import requests
# player_token: the fp1 token of POST /v1/sdk/playersresponse = requests.delete( 'https://api.filudi.com/v1/account', headers={'authorization': f'Bearer {player_token}'},)response.raise_for_status()# No body: the status says it all.Delete the player and all data
Scheduled; cron:purge removes the rows within 24 hours. The token stops working now.
Credential: a player token (fp1), sent as Authorization: Bearer <token>. A game token (fg1) answers 401 here.
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
| 202 | none | Deletion scheduled. |