For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
DocsAPI Reference
  • Fundamentals
    • Home
    • Why Skyflow?
    • Get started with Skyflow
    • Explore what Skyflow can do
    • Authenticate
    • Accounts and environments
    • Deployment models
    • Security best practices
    • Compliance and certifications
    • Get data into Skyflow
    • Platform FAQs
  • Governance
    • Overview
  • Tokenization
    • Overview
  • Connections
    • Overview
  • Processing
  • AI and data sanitization
    • Overview
  • SDKs
    • Overview
      • Go: Migrate from V1 to V2
      • Python: Migrate from V1 to V2
      • Node.js: Migrate from V1 to V2
      • Java: Migrate from V1 to V2
  • Elements
    • Collect and reveal data with Skyflow Elements
LogoLogo
Login
Login
On this page
  • Authentication
  • Initialize the client
  • Insert records
  • Other operations at a glance
  • Request options
  • Error handling
  • v2.1+ updates
  • Get help
SDKsOverview

Go SDK: Migrate from V1 to V2

Was this page helpful?
Previous

Python SDK: Migrate from V1 to V2

Next
Built with

Skyflow Go SDK v2 introduces a new authentication model, multi-vault support via a functional options pattern, native Go data structures, and richer error diagnostics. This guide walks through the key changes with before-and-after code examples, focuses on Insert end-to-end, then shows how the same pattern applies to other operations. A final section covers the v2.1+ field name normalization, which is backward compatible.

Authentication

V1 required a token provider function. V2 lets you choose from five credential types.

V1:

1var bearerToken = ""
2
3func GetSkyflowBearerToken() (string, error) {
4 filePath := "<file_path>"
5 if saUtil.IsExpired(bearerToken) {
6 newToken, err := saUtil.GenerateBearerToken(filePath)
7 if err != nil {
8 return "", err
9 }
10 bearerToken = newToken.AccessToken
11 return bearerToken, nil
12 }
13 return bearerToken, nil
14}

V2:

1// Option 1: API key (recommended)
2skyflowCredentials := common.Credentials{ApiKey: "<YOUR_API_KEY>"}
3
4// Option 2: Environment variable — set SKYFLOW_CREDENTIALS in your environment
5
6// Option 3: Credentials file
7skyflowCredentials := common.Credentials{Path: "<YOUR_CREDENTIALS_FILE_PATH>"}
8
9// Option 4: Stringified JSON
10skyflowCredentials := common.Credentials{CredentialsString: "<YOUR_CREDENTIALS_STRING>"}
11
12// Option 5: Bearer token
13skyflowCredentials := common.Credentials{Token: "<BEARER_TOKEN>"}

Use only one authentication method per credentials object.

Initialize the client

V2 uses a functional options pattern for client construction and supports multiple vault configurations per client instance. Log levels are now per-instance instead of global.

V1:

1import (
2 Skyflow "github.com/skyflowapi/skyflow-go/skyflow/client"
3 "github.com/skyflowapi/skyflow-go/skyflow/common"
4)
5
6configuration := common.Configuration{
7 VaultID: "<vault_id>",
8 VaultURL: "<vault_url>",
9 TokenProvider: GetToken,
10}
11skyflowClient := Skyflow.Init(configuration)

V2 (single vault):

1import (
2 "context"
3 "fmt"
4
5 "github.com/skyflowapi/skyflow-go/v2/client"
6 "github.com/skyflowapi/skyflow-go/v2/utils/common"
7 "github.com/skyflowapi/skyflow-go/v2/utils/logger"
8)
9
10creds := common.Credentials{Path: "<YOUR_CREDENTIALS_FILE_PATH>"}
11
12vaultConfig := common.VaultConfig{
13 VaultId: "<VAULT_ID>",
14 ClusterId: "<CLUSTER_ID>",
15 Env: common.PROD,
16 Credentials: creds,
17}
18
19skyflowClient, err := client.NewSkyflow(
20 client.WithVaults(vaultConfig),
21 client.WithLogLevel(logger.INFO),
22)
23if err != nil {
24 fmt.Println(err)
25 return
26}

V2 (multiple vaults):

1primaryConfig := common.VaultConfig{
2 VaultId: "<PRIMARY_VAULT_ID>",
3 ClusterId: "<PRIMARY_CLUSTER_ID>",
4 Env: common.PROD,
5 Credentials: primaryCreds,
6}
7
8secondaryConfig := common.VaultConfig{
9 VaultId: "<SECONDARY_VAULT_ID>",
10 ClusterId: "<SECONDARY_CLUSTER_ID>",
11 Env: common.PROD,
12 Credentials: secondaryCreds,
13}
14
15skyflowClient, err := client.NewSkyflow(
16 client.WithVaults(primaryConfig, secondaryConfig),
17 client.WithLogLevel(logger.INFO),
18)
19if err != nil {
20 fmt.Println(err)
21 return
22}

Key changes:

  • VaultURL is replaced by ClusterId (derived from your vault URL).
  • Env is now required. Supported values: common.DEV, common.SANDBOX, common.PROD.
  • Log level is set per client instance.
  • A single client can manage multiple vault configurations.

Insert records

V2 replaces third-party JSON objects with native Go maps and slices. Requests use the typed common.InsertRequest struct.

V1:

1var records = make(map[string]interface{})
2var record = make(map[string]interface{})
3record["table"] = "<your_table_name>"
4fields := map[string]interface{}{"<field_name>": "<field_value>"}
5record["fields"] = fields
6records["records"] = []interface{}{record}
7
8options := common.InsertOptions{
9 Tokens: true,
10 ContinueOnError: true,
11}
12res, err := skyflowClient.Insert(records, options)

V2:

1service, err := skyflowClient.Vault("<VAULT_ID>")
2if err != nil {
3 fmt.Println(err)
4 return
5}
6
7ctx := context.TODO()
8
9values := []map[string]interface{}{
10 {"<COLUMN_NAME>": "<COLUMN_VALUE>"},
11}
12
13insert, err := service.Insert(ctx, common.InsertRequest{
14 Table: "<TABLE_NAME>",
15 Values: values,
16}, common.InsertOptions{
17 ContinueOnError: false,
18 ReturnTokens: true,
19})
20if err != nil {
21 fmt.Println("Error occurred ", *err)
22 return
23}
24fmt.Println("RESPONSE:", insert)

V1 response:

1{
2 "Records": [
3 {
4 "table": "cards",
5 "fields": {
6 "skyflow_id": "16419435-aa63-4823-aae7-19c6a2d6a19f",
7 "cardNumber": "f3907186-e7e2-466f-91e5-48e12c2bcbc1"
8 }
9 }
10 ]
11}

V2 response:

1{
2 "InsertedFields": [
3 {
4 "skyflow_id": "9fac9201-7b8a-4446-93f8-5244e1213bd1",
5 "card_number": "5484-7829-1702-9110",
6 "request_index": "0"
7 }
8 ],
9 "Errors": []
10}

Other operations at a glance

Every vault operation in v2 follows the same pattern: pass a typed request struct and options to the corresponding method on the vault service. The snippets below show v2 request construction.

Get:

1get, err := service.Get(ctx, common.GetRequest{
2 Table: "<TABLE_NAME>",
3 Ids: []string{"<SKYFLOW_ID_1>", "<SKYFLOW_ID_2>"},
4}, common.GetOptions{ReturnTokens: true})
5if err != nil {
6 fmt.Println("Error occurred ", *err)
7 return
8}
9fmt.Println(get)

Update:

1update, err := service.Update(ctx, common.UpdateRequest{
2 Table: "<TABLE_NAME>",
3 Data: map[string]interface{}{
4 "skyflow_id": "<SKYFLOW_ID>",
5 "card_number": "<NEW_VALUE>",
6 },
7}, common.UpdateOptions{ReturnTokens: true})
8if err != nil {
9 fmt.Println("Error occurred ", *err)
10 return
11}
12fmt.Println(update)

Delete:

1del, err := service.Delete(ctx, common.DeleteRequest{
2 Table: "<TABLE_NAME>",
3 Ids: []string{"<SKYFLOW_ID_1>", "<SKYFLOW_ID_2>"},
4})
5if err != nil {
6 fmt.Println("Error occurred ", *err)
7 return
8}
9fmt.Println(del)

Detokenize:

1detokenize, err := service.Detokenize(ctx, common.DetokenizeRequest{
2 Tokens: []string{"<TOKEN_1>", "<TOKEN_2>"},
3})
4if err != nil {
5 fmt.Println("Error occurred ", *err)
6 return
7}
8fmt.Println(detokenize)

Query:

1query, err := service.Query(ctx, common.QueryRequest{
2 Query: `SELECT * FROM <TABLE_NAME> WHERE skyflow_id = "<SKYFLOW_ID>"`,
3})
4if err != nil {
5 fmt.Println("Error occurred ", *err)
6 return
7}
8fmt.Println(query)

Request options

V2 replaces the v1 monolithic options struct with operation-specific options structs that you populate inline using Go’s idiomatic struct literal syntax.

V1:

1options := common.InsertOptions{
2 Tokens: true,
3 Upsert: upsertArray,
4 ContinueOnError: true,
5}

V2:

1options := common.InsertOptions{
2 ContinueOnError: false,
3 ReturnTokens: true,
4 TokenMode: common.DISABLE,
5 Upsert: "<UPSERT_COLUMN>",
6}

The same pattern applies to UpsertOptions, UpdateOptions, DeleteOptions, and GetOptions.

Error handling

V2 errors carry more context to help with debugging.

V1:

1{
2 "code": "<http_code>",
3 "description": "<description>"
4}

V2:

1{
2 "httpStatus": "<http_status>",
3 "grpcCode": "<grpc_code>",
4 "httpCode": "<http_code>",
5 "message": "<message>",
6 "requestId": "<request_id>",
7 "details": ["<details>"]
8}

Use the requestId field when contacting Skyflow Support — it uniquely identifies the request for faster diagnosis.

v2.1+ updates

v2.1.0 updates credential and response field names to follow camelCase conventions. Both old and new forms are permanently accepted.

Credential field names:

The credentials JSON file accepts both the legacy and new key names.

Legacy (still accepted)Preferred
clientIDclientId
keyIDkeyId
tokenURItokenUri

Response field names:

Response maps now use SkyflowId (PascalCase). The legacy keys are still present for backward compatibility but are deprecated.

Deprecated (still returned)Preferred
skyflow_idSkyflowId
request_indexRequestIndex

For the full list of changes, see the Go SDK releases on GitHub.

Get help

If you hit issues during migration, contact Skyflow Support and include the requestId from any failed call.