> For the complete documentation index, see [llms.txt](https://docs.nerovasystems.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nerovasystems.com/sdks/available-sdks/go.md).

# Use the Go SDK

Call the Nerova API from Go with the official nerova-sdk-go module: a typed client built from the OpenAPI contract the server publishes.

Call the Nerova API from Go with `github.com/nerova-systems/nerova-sdk-go`: a typed client built from the OpenAPI contract the server publishes. Every path, parameter, and model in the client exists because the contract says so.

## Prerequisites

{% hint style="info" %}

* Go 1.25 or later.
* A Live API key (`nrv_live_`) from the [Quickstart](https://docs.nerovasystems.com/getting-started/quickstart).
* **The SDK is published as the Go module `github.com/nerova-systems/nerova-sdk-go`** **`v0.3.0-preview.2`**, a preview release: the API surface may change before 1.0.
  {% endhint %}

## 1. Install the SDK

Add the preview module:

```bash
go get github.com/nerova-systems/nerova-sdk-go@v0.3.0-preview.2
```

Pin the exact version. Go treats pre-releases as unstable and only picks one for `@latest` while no stable release exists. The install brings in the HTTP request adapter and serialization libraries (`github.com/microsoft/kiota-abstractions-go`, `github.com/microsoft/kiota-http-go`, and the serializers) as regular dependencies. The client lives in the `generated` package (`github.com/nerova-systems/nerova-sdk-go/generated`) and its request and response types in `generated/models`. This is a server-side client: keep your API key out of browsers and mobile apps.

### Version numbers

The Go SDK shares one version line with `@nerova/sdk` and `Nerova.Sdk`. Go tags are semver, so the line is used unchanged: `0.3.0-preview.2` on npm and NuGet is the tag `v0.3.0-preview.2`, and `0.3.0-preview.3` will be `v0.3.0-preview.3`. A stable release is `v0.3.0`. `v0.3.0-preview.1` is retracted in favor of `v0.3.0-preview.2`.

## 2. Construct the client

```go
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/microsoft/kiota-abstractions-go/authentication"
    httpadapter "github.com/microsoft/kiota-http-go"

    "github.com/nerova-systems/nerova-sdk-go/generated"
)

func main() {
    value := os.Getenv("NEROVA_API_KEY")
    if value == "" {
        log.Fatal("NEROVA_API_KEY is required")
    }

    authenticationProvider, err := authentication.NewApiKeyAuthenticationProvider(
        "Bearer "+value, "Authorization", authentication.HEADER_KEYLOCATION,
    )
    if err != nil {
        log.Fatal(err)
    }
    requestAdapter, err := httpadapter.NewNetHttpRequestAdapter(authenticationProvider)
    if err != nil {
        log.Fatal(err)
    }
    client := generated.NewNerovaPartnerClient(requestAdapter)
    ctx := context.Background()
```

The remaining steps continue inside `main`. Two things to know:

* **Read the key from the environment.** Never hard-code it; the value is shown once at creation and cannot be retrieved again.
* **No base URL needed.** The client defaults to the single public host `https://api.nerovasystems.com`. Every key is a Live key (`nrv_live_`); there is no separate test host. See [Authentication](https://docs.nerovasystems.com/getting-started/authentication#api-keys).

The client mirrors the URL structure of the API: `client.Api().V1().Status()`, `.Context()`, `.Tenants()`, and `.Tenants().ByTenantId(id)` for everything under one tenant (activation, capabilities, conversations, work, and the rest). Every call takes a `context.Context` and returns the result and an `error`.

## 3. Make your first calls

```go
status, err := client.Api().V1().Status().Get(ctx, nil)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("API %s (%s)\n", *status.GetApiVersion(), status.GetEnvironment())

tenants, err := client.Api().V1().Tenants().Get(ctx, nil)
if err != nil {
    log.Fatal(err)
}
for _, tenant := range tenants {
    fmt.Printf("%s: %s (%s)\n", *tenant.GetId(), *tenant.GetDisplayName(), tenant.GetProvisioningState())
}
```

`GET /api/v1/tenants` returns a plain list of the tenants your key can see: `id`, `externalReference`, `displayName`, `provisioningState`, `lifecycleState`, `pendingStep`, `lastErrorCode`, and `version`. Go exposes each wire property as a `GetX()` and `SetX()` method pair, and optional values are pointers.

## 4. Read a tenant's activation manifest

Take a tenant from the list above (or create one in step 5) and read its manifest:

```go
tenantId := *tenants[0].GetId()

manifest, err := client.Api().V1().Tenants().ByTenantId(tenantId).Activation().Manifest().Get(ctx, nil)
if err != nil {
    log.Fatal(err)
}

fmt.Println("what still blocks activation:")
for _, reason := range manifest.GetBlockingReasons() {
    fmt.Printf("%s: %s\n", *reason.GetCode(), *reason.GetDetail())
}
```

The activation manifest is the heart of onboarding: it tells you exactly what still blocks a tenant from going live. The full walkthrough is [Provision and activate tenants](https://docs.nerovasystems.com/guides/partner-playbook).

## 5. Create a tenant

Mutations take an `Idempotency-Key` header, a caller-owned value that makes retries safe. Derive it from your own command identity as described in [Handle errors and retries](https://docs.nerovasystems.com/guides/error-handling#make-writes-safe-with-idempotency-keys):

```go
headers := abstractions.NewRequestHeaders()
headers.Add("Idempotency-Key", "provision-tenant-your-crm-id-123")
configuration := &abstractions.RequestConfiguration[abstractions.DefaultQueryParameters]{Headers: headers}

displayName, externalReference := "Demo Salon", "your-crm-id-123"
body := models.NewCreateTenantV1Request()
body.SetDisplayName(&displayName)
body.SetExternalReference(&externalReference)

created, err := client.Api().V1().Tenants().Post(ctx, body, configuration)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("tenant %s: %s\n", *created.GetId(), created.GetProvisioningState())
```

Here `abstractions` is `github.com/microsoft/kiota-abstractions-go` and `models` is `github.com/nerova-systems/nerova-sdk-go/generated/models`. Replaying the same request with the same key returns the original result instead of creating a duplicate.

## 6. Handle errors

Failed calls return the parsed [RFC 9457 problem document](https://docs.nerovasystems.com/api/conventions#errors) as `*models.ProblemDetails`, an error that also carries `ResponseStatusCode`. The stable `code` and the `correlationId` arrive in `GetAdditionalData()`:

```go
_, err = client.Api().V1().Tenants().ByTenantId(tenantId).Conversations().Get(ctx, nil)

var problem *models.ProblemDetails
if errors.As(err, &problem) {
    code := problem.GetAdditionalData()["code"]
    correlationId := problem.GetAdditionalData()["correlationId"]

    // Branch on stable fields, never on message text.
    switch {
    case problem.ResponseStatusCode == 429:
        // schedule a bounded retry
    case code == "partner.merchant_not_available":
        // this tenant is not granted to your key
    default:
        fmt.Printf("Nerova call failed: %v (correlation %v)\n", code, correlationId)
    }
}
```

Quote the `correlationId` in [support reports](https://docs.nerovasystems.com/resources/support). The client performs no automatic retries, so retry and conflict policy stays in your hands, following [Handle errors and retries](https://docs.nerovasystems.com/guides/error-handling).

## 7. Read runtime state

Runtime surfaces (conversations, work ledger, notifications, incidents) read live merchant state for tenants your key is granted; other tenants return `partner.merchant_not_available`. Cursor-paginated endpoints all follow the same shape: pass `Limit` and `Cursor`, read `GetItems()` and `GetNextCursor()`:

```go
var cursor *string
for {
    limit := int32(50)
    configuration := &abstractions.RequestConfiguration[api.V1TenantsItemWorkRequestBuilderGetQueryParameters]{
        QueryParameters: &api.V1TenantsItemWorkRequestBuilderGetQueryParameters{Cursor: cursor, Limit: &limit},
    }
    page, err := client.Api().V1().Tenants().ByTenantId(tenantId).Work().Get(ctx, configuration)
    if err != nil {
        log.Fatal(err)
    }

    for _, item := range page.GetItems() {
        process(item)
    }

    cursor = page.GetNextCursor()
    if cursor == nil || *cursor == "" {
        break
    }
}
```

Here `api` is `github.com/nerova-systems/nerova-sdk-go/generated/api`. Follow `GetNextCursor()` until the server stops returning one.

## Keep the client current

The client is built from the published contract. When the contract grows, a new module version is tagged. Update by bumping the pinned version:

```bash
go get github.com/nerova-systems/nerova-sdk-go@v0.3.0-preview.2
```

Newly published operations appear as new request builders. Clients must ignore unknown response fields: [additive change is allowed](https://docs.nerovasystems.com/api/conventions#versioning).

## Next steps

* The pipeline these calls implement: [Provision and activate tenants](https://docs.nerovasystems.com/guides/partner-playbook).
* Retry and conflict policy to wrap around the client: [Handle errors and retries](https://docs.nerovasystems.com/guides/error-handling).
* Prefer another language? [Use the TypeScript SDK](/sdks/available-sdks/typescript.md), [Use the .NET SDK](/sdks/available-sdks/dotnet.md), [Use the Python SDK](/sdks/available-sdks/python.md), or [Use the PHP SDK](/sdks/available-sdks/php.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.nerovasystems.com/sdks/available-sdks/go.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
