API keys and scopes
How a tool you write asks a LibrePortal server for information with an access key, and which scope each address needs.
On this page
If you write a tool that talks to a LibrePortal server, it signs in with an access key, not with anyone's login. An administrator makes the key; you ask them for one with the scopes you need. How they make it, and how to revoke it, is on Access keys.
Send the key#
curl -H "Authorization: Bearer <key>" http://<server>/api/v1/apps
The key goes in the header only, never in the address. It works only on the /api/v1/ interface; it never opens the control panel. Answers are JSON with stable field names. Reading works from the server's own network, the VPN and trusted places. Changing an app's sign-in works only from the server itself, the VPN, or over https.
What each scope opens#
| Scope | Address | Page |
|---|---|---|
apps:read |
GET /api/v1/apps, GET /api/v1/apps/<app>/auth, GET /api/v1/apps/<app>/address |
Same JSON as libreportal app list --json. The address is the one in Commands for other software |
events:read |
GET /api/v1/events?since= |
Events and webhooks |
people:read |
GET /api/v1/people, /groups, /access |
People, groups and who can reach which app. Never passwords |
system:read |
GET /api/v1/system/maintenance |
Maintenance status |
system:read |
GET /api/v1/system/security |
Security status |
apps:auth-write |
POST /api/v1/apps/<app>/auth |
Change an app's sign-in source. apps:auth-write@forgejo limits it to one app |
A key's scopes are fixed when it is made. Ask for the fewest you need. A call without the right scope is refused with 403, and one from outside the allowed places is refused too.
Good behaviour#
Most documents are copies LibrePortal refreshes about once a minute, so polling faster gains nothing. If you get a 503 right after a server starts, wait and try again. For events, pass since=id:<next_id> from the last answer so you pick up where you left off, or use a webhook and let the server tell you.