Client libraries
Two official clients are generated from the same OpenAPI document as the
reference. They contain generated code only and are published under the
MIT license. For any other language, generate a client from the OpenAPI document yourself:
openapi.json is OpenAPI 3.1, and a 3.0 version is published next to it
for generators that do not read 3.1 yet.
Module github.com/112tech/pluspanel-go:
go get github.com/112tech/pluspanel-gopackage main
import ( "context" "fmt" "log" "os"
"github.com/112tech/pluspanel-go")
func main() { c, err := pluspanel.NewWithAPIKey("https://panel.example.com", os.Getenv("PLUSPANEL_API_KEY")) if err != nil { log.Fatal(err) } res, err := c.ListServersWithResponse(context.Background(), &pluspanel.ListServersParams{}) if err != nil { log.Fatal(err) } if err := pluspanel.CheckResponse(res.HTTPResponse, res.Body); err != nil { log.Fatal(err) // a *pluspanel.Problem: Code, Detail, RequestID… } for _, s := range *res.JSON200.Items { fmt.Println(s.Id, s.Name, s.Status) }}The base URL is your panel’s address; /api/v1 is added when it has no path. Errors come back as
problem details (pluspanel.IsProblem(err, "not_found") tests the code). See the module’s README for
pagination, idempotency keys and custom HTTP clients.
TypeScript
Section titled “TypeScript”Package @pluspanel/api on npm: the API’s types, generated with openapi-typescript, and a small
layer over the type-safe openapi-fetch client (its only runtime dependency). ESM only; Node.js 20+,
Deno, Bun and browsers.
npm install @pluspanel/apiimport { createClient, isProblem, unwrap } from "@pluspanel/api";
const api = createClient({ baseUrl: "https://panel.example.com", // /api/v1 is added when the URL has no path apiKey: process.env.PLUSPANEL_API_KEY ?? "",});
// Every page of servers.let cursor: string | undefined;do { const query = { limit: 100, ...(cursor ? { cursor } : {}) }; const page = await unwrap(api.GET("/servers", { params: { query } })); for (const s of page.items ?? []) console.log(s.id, s.name, s.status); cursor = page.next_cursor ?? undefined;} while (cursor);
// Errors are problem details: unwrap throws a ProblemError (code, detail, requestId…).try { await unwrap(api.GET("/servers/{id}", { params: { path: { id: "6f1c2d3e-…" } } }));} catch (err) { if (isProblem(err, "not_found")) console.log("gone"); else throw err;}Paths, parameters, bodies and answers are typed from the OpenAPI document: a wrong path or member is a
compile error. The package also exports ProblemError, the types paths, components and
operations, and VERSION. Send an Idempotency-Key on a retried POST with
{ headers: { "Idempotency-Key": "…" } }.
Compatibility
Section titled “Compatibility”Both clients follow the versioning policy: they ignore unknown members and enumeration values, so a newer control plane does not break an older client. Update them to use new operations.