Memo
API
Sign in Create an account
Administration

API

Memo answers to programs as well as to browsers. This page has every address the server serves, what opens each one, and what comes back.

Whatever the board list and the admin page do over HTTP, a program can do too. It all hangs off /api/v1, and GET /api/v1 lists its own routes without asking for anything.

A call carries who it is in an Authorization: Bearer header, never a cookie. That is either a key from My account, or a token bought with a password. Because no cookie is involved, none of it needs a CSRF token.

API keys

Another program can make boards for you, with no browser and without your password: a wiki extension that opens a board whenever somebody writes minutes, say. My account has an API keys section for that: say what the key is for, and it is shown to you once, the only time it can be read. Memo keeps a hash of it, the way it keeps passwords.

A key opens everything under /api/v1, described below, as the account that made it:

curl -X POST https://memo.example/api/v1/boards \
  -H 'Authorization: Bearer THE-KEY' \
  -H 'Content-Type: application/json' \
  -d '{"title": "Minutes of the 12th"}'
{
  "name": "minutes-of-the-12th",
  "room": "/minutes-of-the-12th",
  "title": "Minutes of the 12th",
  "kind": "board",
  "notes": 0,
  "visibility": "open",
  "url": "https://memo.example/minutes-of-the-12th",
  "relation": "owner"
}

The board belongs to the key's account: it shows up in that list, and that account can close it to others or delete it. A key made by an admin carries the admin role with it, so treat that one the way you treat the password.

The list says when each key last worked, and Take it back ends it there and then. A key is for one program: give one key per program, so that you can take back that one alone.

Getting in

CallWhat it does
GET /api/v1the routes below, and which backend runs
POST /api/v1/auth/logina username and a password for a token
POST /api/v1/auth/logoutends the token now
GET /api/v1/auth/mewho this bearer is, and whether it is a key
curl -X POST https://memo.example/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username": "you", "password": "your password"}'

The answer holds a token good for a week of use. This works where Memo is the one keeping passwords, so with --auth=local and --auth=ldap. Behind a portal or an OIDC provider there is no password here to check, and a key is the way in. A key cannot log itself out; Take it back in My account is what ends a key.

Boards

CallWhat it does
GET /api/v1/boardsthe boards you made, were let into, or have opened
POST /api/v1/boardsmake one
GET /api/v1/boards/NAMEone board, its columns and what is on it
PATCH /api/v1/boards/NAMEchange its title, or its visibility
DELETE /api/v1/boards/NAMEtake it away, notes and all
GET /api/v1/boards/NAME/exportthe whole board, as the export file holds it

The body that makes a board takes title, and then kind set to mindmap for a mind map, template naming a template (kanban, week, weather), and visibility set to restricted to close it from the start. The board belongs to the account behind the call.

Administration

CallWhat it does
GET /api/v1/admin/overviewevery board and every account at once
GET /api/v1/admin/boardsevery board, whoever made it
DELETE /api/v1/admin/boards/NAMEdelete any board
GET /api/v1/admin/usersevery account
PATCH /api/v1/admin/users/IDgive the admin role or take it back
DELETE /api/v1/admin/users/IDdelete an account
GET /api/v1/admin/auditwhat has been done here lately
GET /api/v1/admin/backupsthe snapshots on the server
POST /api/v1/admin/backupstake one now
GET /api/v1/admin/backups/NAMEdownload one
DELETE /api/v1/admin/backups/NAMEremove one
GET /api/v1/admin/appearanceeverything the Appearance tab shows
PUT /api/v1/admin/appearancechange them
DELETE /api/v1/admin/appearanceput them back

A key made by an admin carries the admin role, so a nightly script can take a backup with no password sitting in it. The other side of that is that such a key is worth as much as the password. Give a script an account of its own where you can, and take its key back the day the script stops.

Addresses that answer without a bearer

These are what a browser asks for, and a program can ask for them the same way. Each answers to whoever may see the board behind it, through the session cookie or a ?s=TOKEN share link.

CallWhat it does
GET /NAME/export.jsona board as the export file holds it
GET /images/board/NAME/IDa picture on a board, ?t for the small one
GET /images/shared/TOKEN/IDthe same picture, reached through a share link
GET /account/avatar/IDsomebody's picture
GET /css/instance.cssthe colours this instance changed, empty if none
GET /api/name?t=TITLEthe free board name a title would take
GET /api/wiki?url=ADDRESSthe card decks sitting at an address

The last two ask for a signed-in browser unless --allowAnonymousBoards is on, since they are the home page working out what a new board would be called.

The older way to make a board

curl -X POST https://memo.example/api/boards \
  -H 'Authorization: Bearer THE-KEY' \
  -H 'Content-Type: application/json' \
  -d '{"title": "Minutes of the 12th"}'

POST /api/boards does what POST /api/v1/boards does, takes the same body, and still answers so that anything written before /api/v1 keeps working. New programs should use /api/v1/boards, which also takes a session token and not only a key.

What the pages call for themselves

The pages in the browser talk to a second set of addresses. They go by the session cookie with a CSRF token in the body, they refuse a request from another origin, and /api/v1 does all the same work for a program. They are listed here so that nothing in a log comes as a surprise.

CallWhat it does
POST /newthe form on the home page
POST /login, POST /registerthe sign-in and sign-up forms
POST /logoutends the session
GET /account/api/boardsthe account and its boards
POST /account/api/boards/visitsremembers the boards this browser opened
POST /account/api/boards/forgetdrops one from that list
POST /account/api/boards/favouritestars one, or unstars it
GET, POST /account/api/keysthe API keys, and a new one
POST /account/api/keys/deletetakes a key back
POST /account/api/passwordchanges the password
POST /account/api/languageremembers the language chosen
POST /account/api/avatarsets or clears the picture
GET /admin/api/overviewthe boards and accounts the admin page shows
POST /admin/api/boards/deletedeletes the ticked boards
GET /admin/api/backupsthe snapshots on the server
POST /admin/api/backups/taketakes one
POST /admin/api/backups/deleteremoves one
GET /admin/api/backups/NAMEdownloads one
POST /admin/api/users/admingives the admin role or takes it back
POST /admin/api/users/deletedeletes the ticked accounts
GET /admin/api/appearanceeverything the Appearance tab shows
POST /admin/api/appearance/savesaves them
POST /admin/api/appearance/resetputs them back
POST /admin/api/appearance/logosends the logo, or takes it away

Everything else the server answers to is a page or a file a page loads: /, /NAME for a board, /s/TOKEN for a share link, /docs, /demo, /login, /register, /account, /admin and its tabs /admin/boards, /admin/users, /admin/backups, /admin/appearance, /auth/callback where an OIDC provider comes back, /logo.webp for the instance's logo, and the static /css/, /images/, /i18n/, /board/, /mind/, /shared/, /vendor/, the page scripts and the font.

Everything that happens on an open board goes through the WebSocket at /ws instead: notes, columns, boxes, the people present. It is not part of this API and its messages change with the client that speaks them.

Documentation

Getting started Installation API

On this page