API
Memo répond aux programmes comme aux navigateurs. Cette page donne toutes les adresses que le serveur sert, ce qui ouvre chacune, et ce qui revient.
Tout ce que la liste des tableaux et la page d'administration font en HTTP, un
programme peut le faire aussi. Tout part de /api/v1, et GET /api/v1 liste
ses propres routes sans rien demander.
Un appel dit qui il est dans un en-tête Authorization: Bearer, jamais dans un
cookie. C'est soit une clé prise dans Mon compte, soit un jeton acheté avec
un mot de passe. Comme il n'y a pas de cookie, rien là-dedans n'a besoin de
jeton CSRF.
Les clés API
Un autre programme peut créer des tableaux à votre place, sans navigateur et sans votre mot de passe : une extension de wiki qui ouvre un tableau chaque fois que quelqu'un écrit un compte rendu, par exemple. Mon compte a pour cela une section Clés API : dites à quoi la clé servira, et elle vous est montrée une fois, seule occasion de la lire. Memo n'en garde qu'une empreinte, comme des mots de passe.
La clé ouvre ensuite tout ce qui est sous /api/v1, décrit plus bas, au nom du
compte qui l'a faite :
curl -X POST https://memo.example/api/v1/boards \
-H 'Authorization: Bearer LA-CLÉ' \
-H 'Content-Type: application/json' \
-d '{"title": "Compte rendu du 12"}'
{
"name": "compte-rendu-du-12",
"room": "/compte-rendu-du-12",
"title": "Compte rendu du 12",
"kind": "board",
"notes": 0,
"visibility": "open",
"url": "https://memo.example/compte-rendu-du-12",
"relation": "owner"
}
Le tableau appartient au compte de la clé : il apparaît dans sa liste, et ce compte peut le fermer aux autres ou le supprimer. Une clé faite par un admin porte le rôle d'admin avec elle : traitez celle-là comme le mot de passe.
La liste dit quand chaque clé a servi la dernière fois, et Reprendre l'annule sur-le-champ. Une clé vaut pour un programme : donnez-en une par programme, pour pouvoir reprendre celle-là seule.
Entrer
| Appel | Ce qu'il fait |
|---|---|
GET /api/v1 | les routes ci-dessous, et le backend en place |
POST /api/v1/auth/login | un identifiant et un mot de passe contre un jeton |
POST /api/v1/auth/logout | met fin au jeton tout de suite |
GET /api/v1/auth/me | qui est ce porteur, et si c'est une clé |
curl -X POST https://memo.example/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"username": "vous", "password": "votre mot de passe"}'
La réponse contient un jeton bon pour une semaine d'usage. Cela marche là où
Memo garde lui-même les mots de passe, donc avec --auth=local et
--auth=ldap. Derrière un portail ou un fournisseur OIDC il n'y a pas de mot de
passe à vérifier ici, et c'est une clé qui ouvre la porte. Une clé ne peut pas
se déconnecter elle-même : c'est Reprendre, dans Mon compte, qui met fin
à une clé.
Les tableaux
| Appel | Ce qu'il fait |
|---|---|
GET /api/v1/boards | les tableaux créés, partagés avec vous, ou déjà ouverts |
POST /api/v1/boards | en créer un |
GET /api/v1/boards/NOM | un tableau, ses colonnes et ce qu'il porte |
PATCH /api/v1/boards/NOM | changer son title ou sa visibility |
DELETE /api/v1/boards/NOM | l'effacer, notes comprises |
GET /api/v1/boards/NOM/export | le tableau entier, comme dans le fichier d'export |
Le corps qui crée un tableau prend title, puis kind mis à mindmap pour une
carte mentale, template avec le nom d'un modèle (kanban, week, weather),
et visibility mis à restricted pour le fermer d'emblée. Le tableau
appartient au compte derrière l'appel.
L'administration
| Appel | Ce qu'il fait |
|---|---|
GET /api/v1/admin/overview | tous les tableaux et tous les comptes |
GET /api/v1/admin/boards | tous les tableaux, quel qu'en soit l'auteur |
DELETE /api/v1/admin/boards/NOM | effacer n'importe quel tableau |
GET /api/v1/admin/users | tous les comptes |
PATCH /api/v1/admin/users/ID | donner ou retirer le rôle d'admin |
DELETE /api/v1/admin/users/ID | effacer un compte |
GET /api/v1/admin/audit | ce qui s'est fait ici ces derniers temps |
GET /api/v1/admin/backups | les sauvegardes présentes sur le serveur |
POST /api/v1/admin/backups | en prendre une tout de suite |
GET /api/v1/admin/backups/NOM | en télécharger une |
DELETE /api/v1/admin/backups/NOM | en effacer une |
GET /api/v1/admin/appearance | les couleurs que montre l'onglet Apparence |
PUT /api/v1/admin/appearance | les changer |
DELETE /api/v1/admin/appearance | les remettre d'origine |
Une clé faite par un admin porte le rôle d'admin : un script de nuit peut donc prendre une sauvegarde sans mot de passe écrit dedans. Le revers, c'est qu'une telle clé vaut autant que le mot de passe. Donnez à un script un compte à lui quand vous le pouvez, et reprenez sa clé le jour où le script s'arrête.
Les adresses qui répondent sans porteur
Ce sont celles que le navigateur demande, et un programme peut les demander
pareil. Chacune répond à qui a le droit de voir le tableau derrière, par le
cookie de session ou par un lien de partage ?s=JETON.
| Appel | Ce qu'il fait |
|---|---|
GET /NOM/export.json | un tableau comme dans le fichier d'export |
GET /images/board/NOM/ID | une image d'un tableau, ?t pour la petite |
GET /images/shared/JETON/ID | la même image, atteinte par un lien de partage |
GET /account/avatar/ID | la photo de quelqu'un |
GET /css/instance.css | les couleurs changées ici, vide si rien n'a bougé |
GET /api/name?t=TITRE | le nom libre qu'un titre prendrait |
GET /api/wiki?url=ADRESSE | les jeux de cartes présents à une adresse |
Les deux dernières demandent un navigateur identifié, sauf si
--allowAnonymousBoards est activé : c'est la page d'accueil en train de
calculer le nom d'un nouveau tableau.
L'ancienne façon de créer un tableau
curl -X POST https://memo.example/api/boards \
-H 'Authorization: Bearer LA-CLÉ' \
-H 'Content-Type: application/json' \
-d '{"title": "Compte rendu du 12"}'
POST /api/boards fait ce que fait POST /api/v1/boards, prend le même corps,
et répond toujours pour que ce qui a été écrit avant /api/v1 continue de
marcher. Les nouveaux programmes prendront /api/v1/boards, qui accepte aussi
un jeton de session et pas seulement une clé.
Ce que les pages s'appellent à elles-mêmes
Les pages du navigateur parlent à un deuxième jeu d'adresses. Elles passent par
le cookie de session avec un jeton CSRF dans le corps, elles refusent une
requête venue d'une autre origine, et /api/v1 fait le même travail pour un
programme. Elles sont listées ici pour que rien dans un journal ne surprenne.
| Appel | Ce qu'il fait |
|---|---|
POST /new | le formulaire de la page d'accueil |
POST /login, POST /register | les formulaires de connexion et d'inscription |
POST /logout | met fin à la session |
GET /account/api/boards | le compte et ses tableaux |
POST /account/api/boards/visits | retient les tableaux ouverts par ce navigateur |
POST /account/api/boards/forget | en retire un de cette liste |
POST /account/api/boards/favourite | met une étoile, ou l'enlève |
GET, POST /account/api/keys | les clés API, et une nouvelle |
POST /account/api/keys/delete | reprend une clé |
POST /account/api/password | change le mot de passe |
POST /account/api/language | retient la langue choisie |
POST /account/api/avatar | met ou enlève la photo |
GET /admin/api/overview | les tableaux et comptes de la page d'admin |
POST /admin/api/boards/delete | efface les tableaux cochés |
GET /admin/api/backups | les sauvegardes sur le serveur |
POST /admin/api/backups/take | en prend une |
POST /admin/api/backups/delete | en efface une |
GET /admin/api/backups/NOM | en télécharge une |
POST /admin/api/users/admin | donne le rôle d'admin ou le retire |
POST /admin/api/users/delete | efface les comptes cochés |
GET /admin/api/appearance | les couleurs et le CSS personnalisé |
POST /admin/api/appearance/save | les enregistre |
POST /admin/api/appearance/reset | les remet d'origine |
Le reste de ce à quoi le serveur répond, ce sont les pages et les fichiers
qu'elles chargent : /, /NOM pour un tableau, /s/JETON pour un lien de
partage, /docs, /demo, /login, /register, /account, /admin,
/auth/callback où revient un fournisseur OIDC, et les fichiers statiques
/css/, /images/, /i18n/, /board/, /mind/, /shared/, /vendor/, les
scripts des pages et la police.
Tout ce qui se passe sur un tableau ouvert passe par le WebSocket /ws : les
notes, les colonnes, les boîtes, les gens présents. Ce n'est pas une partie de
cette API et ses messages changent avec le client qui les parle.