Go SDK — Getting Started
Go SDK — Getting Started
Section titled “Go SDK — Getting Started”sdk-go is a Go client for the Sencai Platform API (/api/v1/*), generated from the public
OpenAPI spec (openapi-generator-cli, go template — F4.DEVPORTAL.02). It lives at sdk-go/ in
the monorepo, module github.com/sencai/sdk-go.
Installation
Section titled “Installation”github.com/sencai/sdk-go is a placeholder import path, not yet published — the final module
path is a decision tied to a future public release (its own repository/org), and public
pkg.go.dev indexing is a separate business/release decision, out of scope for the SDK
generation work itself. Until then:
go get github.com/sencai/sdk-gothen add a replace directive in your consuming project’s go.mod pointing at a local checkout
or a git ref of this directory:
replace github.com/sencai/sdk-go => /path/to/code/sdk-goInitialize the client
Section titled “Initialize the client”package main
import ( "context" "os"
sencaisdk "github.com/sencai/sdk-go")
func main() { cfg := sencaisdk.NewConfiguration() cfg.Servers = sencaisdk.ServerConfigurations{ // Local dev: http://api.sencai.localhost/api/v1 or http://localhost:1337/api/v1 // Production: https://api.sencai.space/api/v1 {URL: os.Getenv("SENCAI_API_BASE_URL")}, } // Bearer JWT (Keycloak access token today) — or a future API-key header. The // client only provides the injection point; it does not fetch or refresh // the token for you. cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("SENCAI_ACCESS_TOKEN"))
client := sencaisdk.NewAPIClient(cfg) ctx := context.Background() _ = ctx _ = client}Configuration.Servers and the Authorization header are always set at runtime — the package
never hardcodes a production URL.
Complete example: list organisations, invite a member
Section titled “Complete example: list organisations, invite a member”Verified against a local run-local-dev.sh stack (backend, backend-db, auth profiles).
package main
import ( "context" "fmt" "os"
sencaisdk "github.com/sencai/sdk-go")
func main() { cfg := sencaisdk.NewConfiguration() cfg.Servers = sencaisdk.ServerConfigurations{{URL: os.Getenv("SENCAI_API_BASE_URL")}} cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("SENCAI_ACCESS_TOKEN")) client := sencaisdk.NewAPIClient(cfg) ctx := context.Background()
// List organisations the caller belongs to. result, _, err := client.OrganisationAPI.FindOrganisation(ctx).PaginationPageSize(10).Execute() if err != nil { panic(err) } for _, org := range result.Data { fmt.Println(org.Name) } // -> QA Admin Workspace // e2e-org-d18a54e2 // e2e-org-d9e67836
targetOrg := result.Data[0]
// Invite an existing Strapi user into that organisation. `POST // /organisations/{id}/invite` requires the invitee to already have a // registered account (see the Error handling section below for what // happens otherwise) and the caller to be admin+ in the organisation. body := sencaisdk.NewOrganisationInviteMemberRequest("new-member@example.com", "viewer") invite, _, err := client.OrganisationAPI. OrganisationInviteMember(ctx, *targetOrg.DocumentId). OrganisationInviteMemberRequest(*body). Execute() if err != nil { panic(err) } fmt.Printf("%+v\n", invite.Data)}Error handling
Section titled “Error handling”A non-2xx response returns a non-nil error (the typed method’s result is left at its zero
value) that can be unwrapped to *sencaisdk.GenericOpenAPIError, exposing the raw response body
via .Body(). Error bodies follow Strapi’s standard envelope:
{ "error": { "status", "name", "message", "details" } }.
import ( "encoding/json" "errors")
type errorEnvelope struct { Error struct { Status int `json:"status"` Name string `json:"name"` Message string `json:"message"` Details map[string]any `json:"details"` } `json:"error"`}
_, _, err := client.OrganisationAPI. OrganisationInviteMember(ctx, *targetOrg.DocumentId). OrganisationInviteMemberRequest(*body). Execute()if err != nil { var apiErr *sencaisdk.GenericOpenAPIError if errors.As(err, &apiErr) { var body errorEnvelope _ = json.Unmarshal(apiErr.Body(), &body) fmt.Println(body.Error.Status, body.Error.Name, body.Error.Message) // A real, commonly hit example — the organisation's plan seat limit: // 402 PaymentRequired "Member limit reached (3/3). Upgrade your plan." }}Other status codes you should expect from this endpoint specifically: 400 (missing/invalid
email/role, or no Strapi user registered with that email — this endpoint does not invite
not-yet-registered emails), 401 (missing/expired token), 403 (caller is not admin+ in the
organisation), 409 (that user is already a member).
SDK versioning & breaking changes
Section titled “SDK versioning & breaking changes”The package’s version is tracked in .openapi-generator/VERSION and derived from the OpenAPI
spec’s info.version on every regeneration — it is never bumped by hand. Go’s own module
versioning works through git tags on a standalone repository, once one exists (out of scope for
this task). A breaking API change ships as a new spec major version, which regenerates this SDK
accordingly. See API versioning for what counts as breaking, the
/api/v1/ → /api/v2/ migration path, and the SUNSET_DATE deprecation-header convention — this
page does not repeat that policy, only how it surfaces in the generated client.
For the full generated reference of every operation this client exposes, see the API Reference.