> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gcore.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Go SDK

The `gcore-go` module provides typed access to the full Gcore REST API from Go 1.22+. Generated from the OpenAPI specification using [Stainless](https://www.stainless.com/), all request structs use Go's type system with `omitzero` semantics from Go 1.24 `encoding/json`. All responses are strongly typed structs with a `.JSON` metadata field for optional field inspection.

Module: [`github.com/G-Core/gcore-go`](https://pkg.go.dev/github.com/G-Core/gcore-go) · Source: [gcore-go](https://github.com/G-Core/gcore-go) on GitHub

## Requirements

Go 1.22 or higher.

## Install

```bash theme={null}
go get github.com/G-Core/gcore-go
```

To pin a specific version:

```bash theme={null}
go get -u 'github.com/G-Core/gcore-go@v0.48.0'
```

## Initialize the client

`gcore.NewClient()` returns a value type (`gcore.Client`), not a pointer. The client reads the API key from the `GCORE_API_KEY` environment variable by default:

```go theme={null}
package main

import (
    "context"
    "fmt"
    "os"

    "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cloud"
    "github.com/G-Core/gcore-go/option"
)

func main() {
    client := gcore.NewClient(
        option.WithAPIKey(os.Getenv("GCORE_API_KEY")),
    )
}
```

## First call

List all instances in a project and region:

```go theme={null}
projectID, _ := strconv.ParseInt(os.Getenv("PROJECT_ID"), 10, 64)
regionID, _  := strconv.ParseInt(os.Getenv("REGION_ID"), 10, 64)

page, err := client.Cloud.Instances.List(context.TODO(), cloud.InstanceListParams{
    ProjectID: gcore.Int(projectID),
    RegionID:  gcore.Int(regionID),
})
if err != nil {
    panic(err)
}
for _, inst := range page.Results {
    fmt.Println(inst.ID, inst.Name)
}
```

## Request parameters

Required primitive fields carry the tag `` `api:"required"` `` and are always serialized, even when zero. Optional fields are wrapped in `param.Opt[T]` and set using the provided constructors:

```go theme={null}
params := cloud.InstanceNewParams{
    ProjectID: projectID,                   // required int64 - always serialized
    RegionID:  regionID,                    // required int64 - always serialized
    Flavor:    "g2-standard-2-4",           // required string
    Name:      gcore.String("my-vm"),       // optional - use gcore.String(), gcore.Int(), etc.
}
```

To send `null` for an optional field instead of omitting it:

```go theme={null}
params.Name = param.Null[string]()
```

<Warning>
  Flavor IDs are region-specific. Run <code>client.Cloud.Instances.Flavors.List(ctx, params)</code> to see what flavors are available in a given region before creating an instance.
</Warning>

## Task polling

Cloud API write operations return a task ID. Use `NewAndPoll` methods where available - they submit the request and block until the resource is ready:

```go theme={null}
projectID, _ := strconv.ParseInt(os.Getenv("PROJECT_ID"), 10, 64)
regionID, _  := strconv.ParseInt(os.Getenv("REGION_ID"), 10, 64)
imageID := os.Getenv("IMAGE_ID")

instance, err := client.Cloud.Instances.NewAndPoll(context.TODO(), cloud.InstanceNewParams{
    ProjectID: projectID,
    RegionID:  regionID,
    Flavor:    "g2-standard-2-4",
    Name:      gcore.String("my-vm"),
    Interfaces: []cloud.InstanceNewParamsInterface{
        {Type: cloud.InstanceNewParamsInterfaceTypeExternal},
    },
    Volumes: []cloud.InstanceNewParamsVolume{{
        Source:    cloud.InstanceNewParamsVolumeSourceImage,
        ImageID:   gcore.String(imageID),
        Size:      gcore.Int(20),
        BootIndex: gcore.Int(0),
    }},
})
if err != nil {
    panic(err)
}
fmt.Println(instance.ID)
```

When `NewAndPoll` is not available for a resource, poll with `client.Cloud.Tasks.Poll` directly:

```go theme={null}
taskList, err := client.Cloud.SomeResource.New(context.TODO(), params)
if err != nil {
    panic(err)
}

task, err := client.Cloud.Tasks.Poll(context.TODO(), taskList.Tasks[0])
if err != nil {
    panic(err)
}

// task.CreatedResources is a typed struct
fmt.Println(task.CreatedResources.Instances[0])
```

<Warning>
  `task.CreatedResources` is a typed struct. Access fields as `task.CreatedResources.Instances[0]`, not as a map. The `client.Cloud.Tasks.Get(ctx, taskID)` method takes only the task ID string - no project or region parameters.
</Warning>

## Pagination

Use `ListAutoPaging()` to iterate across all pages automatically:

```go theme={null}
iter := client.Cloud.Projects.ListAutoPaging(context.TODO(), cloud.ProjectListParams{
    Limit: gcore.Int(10),
})
for iter.Next() {
    project := iter.Current()
    fmt.Printf("%+v\n", project)
}
if err := iter.Err(); err != nil {
    panic(err)
}
```

For manual page control:

```go theme={null}
page, err := client.Cloud.Projects.List(context.TODO(), cloud.ProjectListParams{
    Limit: gcore.Int(10),
})
for page != nil {
    for _, project := range page.Results {
        fmt.Println(project.ID, project.Name)
    }
    page, err = page.GetNextPage()
}
if err != nil {
    panic(err)
}
```

## Error handling

Use `errors.As` to inspect API errors:

```go theme={null}
import "errors"

_, err := client.Cloud.Projects.New(context.TODO(), cloud.ProjectNewParams{
    Name: "my-project",
})
if err != nil {
    var apierr *gcore.Error
    if errors.As(err, &apierr) {
        fmt.Println(string(apierr.DumpRequest(true)))
        fmt.Println(string(apierr.DumpResponse(true)))
    }
    panic(err)
}
```

## Retries and timeouts

The client retries connection errors, 408, 409, 429, and 5xx errors twice by default. Requests have no default timeout - use `context` to set one:

```go theme={null}
// Set a 5-minute budget for the request including all retries
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()

client.Cloud.Projects.New(
    ctx,
    cloud.ProjectNewParams{Name: "my-project"},
    option.WithRequestTimeout(20*time.Second), // per-retry timeout
)
```

Disable or configure retries:

```go theme={null}
// Globally
client := gcore.NewClient(option.WithMaxRetries(0))

// Per request
client.Cloud.Projects.New(ctx, params, option.WithMaxRetries(5))
```

## Middleware

Apply custom logic to all requests using `option.WithMiddleware`:

```go theme={null}
func Logger(req *http.Request, next option.MiddlewareNext) (*http.Response, error) {
    start := time.Now()
    res, err := next(req)
    fmt.Printf("%s %s %v\n", req.Method, req.URL, time.Since(start))
    return res, err
}

client := gcore.NewClient(
    option.WithAPIKey(os.Getenv("GCORE_API_KEY")),
    option.WithMiddleware(Logger),
)
```

When multiple middleware functions are provided, they run left to right. Client-level middleware runs before per-request middleware.

## Accessing raw response data

Use `option.WithResponseInto()` to capture the raw HTTP response alongside the parsed result:

```go theme={null}
var response *http.Response
project, err := client.Cloud.Projects.New(
    context.TODO(),
    cloud.ProjectNewParams{Name: "my-project"},
    option.WithResponseInto(&response),
)
fmt.Printf("Status: %d\n", response.StatusCode)
fmt.Printf("Headers: %+v\n", response.Header)
```
