Skip to content

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:

Terminal window
go get github.com/112tech/pluspanel-go
package 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.

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.

Terminal window
npm install @pluspanel/api
import { 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": "…" } }.

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.