API Basics
Everything Pano does for visitors is available over HTTP. This page is the short version: where the API lives, what an answer looks like, how lists are paged, and how Pano tells you something is going away.
Where it lives
Every public path starts with /api/v1. Try it on your own site:
curl http://localhost:8088/api/v1/site-info| Part | Path | Promise |
|---|---|---|
| Site API (core) | /api/v1/... | Public. Only additions. |
| A plugin's API | /api/plugins/<pluginId>/... | Public. <pluginId> is the full id, for example pano-plugin-market. |
| Per-plugin services of core | /api/v1/plugins/<pluginId>/_/... | Public. _ is reserved for core. |
| Panel API | /api/v1/panel/... | Internal. Panel and platform ship together. |
| Setup, node, maintenance | /api/v1/setup, /node, /maintenance | Internal. |
Plugin panel endpoints live at /api/plugins/<pluginId>/panel/.... Nothing else under /api is served, and /panel/api no longer exists.
Plugin namespace
- A plugin's paths carry no version:
/api/plugins/<pluginId>/.... A plugin owns its API and versions it itself; core's/api/v1promise does not cover it. The old/api/v1/plugins/<pluginId>/...paths answer 404. paneland_are reserved first segments.panelmarks the plugin's admin endpoints,_marks core's own services about the plugin (translations,openapi.json,ui.zip), which stay under/api/v1/plugins/<pluginId>/_/.- Plugin management stays in core at
/api/v1/panel/plugins/.... - Five core lists were renamed to
items: support sidebaronlineAdmins, panel player searchplayers, pending serversservers, server playersplayersand softwaresoftware. Only paged lists carrypage.
Answers
A good answer is a plain JSON object. There is no result wrapper:
{ "message": "hi" }A failed answer always has one shape, whatever the endpoint:
{ "error": { "code": "INVALID_FIELDS", "fields": { "email": "EXISTS" } } }code is always there and never changes between releases. message (English, for people reading logs), details and fields appear only when they have something to say. Check code, never the HTTP text.
Every answer also carries the header Pano-Api-Level: the API level of this Pano. It rises when the extension contract gains something.
Lists and pages
Ask for a page with page (starts at 1) and pageSize (up to 100):
curl "http://localhost:8088/api/v1/posts?page=2&pageSize=20"{ "items": [ ], "page": { "number": 2, "size": 20, "totalItems": 57, "totalPages": 3 } }- A
pageSizeoutside1..100is refused withINVALID_FIELDSandfields.pageSize = OUT_OF_RANGE. It is never silently clamped. - A page past the last one answers
404 PAGE_NOT_FOUND. An empty list answers page 1 withtotalPages: 0. - A few internal lists (console search, alerts) use
limitandcursorand answerpage.nextCursor.
Levels, stability, deprecation
- Public operations only grow. Nothing is removed or renamed, no field changes type or disappears, no request field becomes required, no error code changes.
- Deprecated operations still work. They are marked
deprecated: truein the OpenAPI document and answer the headersDeprecation: trueandSunset: <date>. - A deprecated operation is removed no sooner than 6 months after the release that deprecated it, on the
Sunsetdate. - Plugins and themes declare the API level they need. Pano starts a resource only if its level is between the minimum and the current level of the site.
Rate limits
Calls are limited per visitor address. Limited calls answer 429 RATE_LIMIT_EXCEEDED and the headers X-RateLimit-Limit, X-RateLimit-Remaining and Retry-After. A front-end that serves many visitors uses a front-end key so it gets its own buckets.
Next
- Reading the API reference: find every operation and its schema.
- Access: cookies, CSRF, keys, WebSocket.