API and plugins
last updated
monbooru has a REST API under /api/v1/, which is what monloader,
plugins and your own scripts use. The full endpoint reference comes
with the app and always matches the version you run:
/api/v1/docsfor the HTML reference (also linked in the footer),/api/v1/openapi.jsonfor the OpenAPI spec.
This page covers what that reference doesn’t: tokens, calling it from a browser, and writing a plugin.
Tokens#
The API stays off until you create a token under Settings -> Authentication. Each token has a name, can be revoked on its own, and carries the permissions you give it:
read: everyGET(search, fetch, tags…)write:POSTandPATCH(upload, edit, tag, relate…)delete:DELETE
The secret is shown once, when you create it. Send it as a bearer token:
curl -H "Authorization: Bearer <token>" \
"http://localhost:8455/api/v1/images/search?q=1girl"
The errors you’re most likely to meet: 401 unauthorized for a
missing or wrong token, 403 insufficient_scope when the token lacks
the permission, and 503 api_disabled when no token exists yet.
Requests go to the active gallery. Add ?gallery=<name> or an
X-Monbooru-Gallery header to talk to another one.
Tokens for monloader and plugins are made by pairing rather than by hand.
Calling it from a web page#
A page monbooru serves can call the API right away when you reach
monbooru at its IP address, at localhost, or at the address in
server.base_url. A page served from anywhere else, like your own
tool on another port or a browser extension, is blocked by the browser
until you add its address to server.cors_origins in
the config file, for example
http://192.168.1.50:5173. * allows any page. Scripts, curl
and monloader aren’t browsers and don’t need this. /api/v1/docs
shows the addresses currently allowed.
Writing a plugin#
A plugin is an HTTP service that pairs with monbooru and gets a few buttons in its interface. It can be written in anything. It needs at most three things:
GET /healthanswering 200. monbooru checks it before approving the pairing and to decide whether to show your buttons. Answer{"version": "..."}and your version shows on the settings row.- If you declared relay buttons, a handler for the relay
POST. It receives{payload, monbooru, gallery, slot, button, image_ids}with your token as a bearer header, and answers{"ok": true, "message": "...", "refresh": true}. monbooru waits up to 10 seconds for the answer. - If you declared open buttons, the pages they point at. monbooru
serves them through itself under
/plugins/<name>/, so use relative links inside them.
Buttons go in one of two slots, detail-actions (an image’s page) or
batch-bar (under the gallery’s batch bar, relay only). A button’s
path can use {image_id}, {gallery} and {back_url}. Give a
button media when it doesn’t handle everything: any of image,
archive and animated, comma-separated. monbooru then hides it on
other files and leaves them out of a batch.
Everything else goes through the REST API with the token you’re
issued. Pairing is a few calls: POST /api/v1/pair/request with your
name, address, the permissions you need and your buttons, then poll
/api/v1/pair/status until the user approves, and keep the token it
returns. Ask for read and write, and for delete only if your
plugin really deletes images. Changing your buttons in a later release
means offering again: the user approves a request marked re-pair.
To ship it as a folder people drop into plugins/, add a
plugin.toml with the launch line, command = "./yourplugin" (and
command_windows if Windows needs another one). monbooru starts it
with the folder as working directory and MONBOORU_URL in its
environment, and stops it by closing its stdin, so exit when stdin
closes. monbooru installs nothing, so ship a self-contained program.
What monbooru keeps stable for plugins: the /api/v1 API, the pairing
exchange, the relay message, the button slots and variables, the
/plugins/<name>/ mount, and the theme variables. Templates,
/internal/ URLs and the database are not part of that and can
change in any release.
That contract has a number, currently 1. Send it as "contract" in
the pairing request and put contract = 1 in plugin.toml. A monbooru
that speaks an older contract than your plugin refuses the pairing
(409, code contract_unsupported) and doesn’t start the folder,
instead of half working. The number only moves when a change would
break a plugin written against the old one.
examples/simple-edit
in the plugins registry is a working plugin to copy: it pairs, rotates
images from a relay button, and serves a crop page behind an open
button.
