Go
There is no published Go module: you generate the Go code yourself with buf, from the voplica/api repository, which holds the configuration for Go. The native gRPC endpoint opens soon; today the JSON API is served, and the generated messages give you type-safe requests and responses for it: protojson turns a request into the JSON body of a call, and the JSON answer back into a response.
Generate the code
Section titled “Generate the code”You need git, Go 1.25 or later, and the buf CLI, 1.36 or later.
-
Check out the definitions at the version you want, today
v1.0.1:Terminal window git clone --depth 1 --branch v1.0.1 https://github.com/voplica/api.gitcd api -
From the repository’s root, generate the Go code with the configuration in
clients/go/buf.gen.yaml:Terminal window buf generate --template clients/go/buf.gen.yamlIt writes a Go package for each package of the definitions under
clients/go/gen/, for examplegithub.com/voplica/api/clients/go/gen/voplica/api/payment: the messages and enums, made by protoc-gen-go, and the gRPC client and server of each service, made by protoc-gen-go-grpc. A later run replaces what an earlier one wrote.The two generators run on the Buf Schema Registry, at the versions the configuration pins. Without an account it allows 10
buf generateruns an hour from one address;buf registry login, with a free account, raises the limit. -
clients/go/is already a Go module,github.com/voplica/api/clients/go, with itsgo.modandgo.sum, so the generated code builds at once:Terminal window cd clients/gogo build ./...
Use it from your module
Section titled “Use it from your module”Your module uses the generated one through a replace directive. From the directory that holds the api checkout:
mkdir balance && cd balancego mod init example.com/balancego mod edit -replace=github.com/voplica/api/clients/go=../api/clients/goA first call
Section titled “A first call”Save this as main.go in your module. call sends a request message as JSON to a method of the API, by its full name
<package>.<Service>/<Method>, and reads the answer into a response message:
package main
import ( "bytes" "fmt" "io" "log" "net/http" "os" "time"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto"
"github.com/voplica/api/clients/go/gen/voplica/api/ai/model" "github.com/voplica/api/clients/go/gen/voplica/api/payment" "github.com/voplica/api/clients/go/gen/voplica/types/ai/common")
const api = "https://api.voplica.com"
var client = &http.Client{Timeout: 30 * time.Second}
// call sends request as JSON to a method of the API and reads the answer into response. apiKey is empty for a method// that needs no key.func call(method string, request, response proto.Message, apiKey string) error { body, err := protojson.Marshal(request) if err != nil { return err } httpRequest, err := http.NewRequest(http.MethodPost, api+"/"+method, bytes.NewReader(body)) if err != nil { return err } httpRequest.Header.Set("Content-Type", "application/json") if apiKey != "" { httpRequest.Header.Set("Authorization", "Bearer "+apiKey) } answer, err := client.Do(httpRequest) if err != nil { return err } defer answer.Body.Close() data, err := io.ReadAll(answer.Body) if err != nil { return err } if answer.StatusCode != http.StatusOK { return fmt.Errorf("%s: %s", answer.Status, data) } // A later version of the API may add fields: skip the ones this code does not know. return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(data, response)}
func main() { // A method that needs no key: the model variant Voplica recommends for LoRAs of a family. recommended := &model.GetRecommendedBaseModelVariantResponse{} request := &model.GetRecommendedBaseModelVariantRequest{ CompatibleLoraModelFamily: common.ModelFamily_FLUX_2_KLEIN_9B.Enum(), } if err := call("voplica.api.ai.model.ModelVariantService/GetRecommendedBaseModelVariant", request, recommended, ""); err != nil { log.Fatal(err) } fmt.Println("Recommended:", recommended.GetModelVariant().GetVariantName())
// A method that needs your key. The key comes from the environment, never from your code. apiKey := os.Getenv("VOPLICA_API_KEY") if apiKey == "" { log.Fatal("Set VOPLICA_API_KEY to your API key first.") } info := &payment.GetBillingInfoResponse{} if err := call("voplica.api.payment.PaymentService/GetBillingInfo", &payment.GetBillingInfoRequest{}, info, apiKey); err != nil { log.Fatal(err) } fmt.Println("Anytime credits, in thousandths:", info.GetBillingInfo().GetPermanentCreditsMilli())}Then, in the shell where you set VOPLICA_API_KEY, let Go resolve the imports and run it:
go mod tidygo run .It prints the name of the recommended model variant, then your Anytime credits in thousandths of a credit.
- Requests are the generated structs. An
optionalfield takes a pointer, so an enum value goes in through itsEnum()method, ascommon.ModelFamily_FLUX_2_KLEIN_9B.Enum()above. - Answers are read with
DiscardUnknown, so the code keeps working when a later version of the API adds a field. - 64-bit numbers, which the API sends as JSON strings, arrive in the structs’
int64anduint64fields.
Errors
Section titled “Errors”A call that fails answers with an HTTP status other than 200, and call returns that status with the body. The body
is nearly always the JSON error, with its code and message (the JSON API’s errors); a few refusals
are plain text (answers that are not JSON), to be read by their status.
The gRPC stubs
Section titled “The gRPC stubs”The generated code also holds each service’s gRPC client, such as payment.NewPaymentServiceClient. It needs the
native gRPC endpoint, which opens soon; until then, call the API as JSON, as above.
Versions
Section titled “Versions”The code you generate is the version of the API you checked out, today v1.0.1. For a later version,
check out its tag and generate again; Versioning and changelog lists what each version changed.