Skip to main content

Overview

The CDP Go SDK provides a client for interacting with the Coinbase Developer Platform API. The client handles JWT-based authentication, request signing, and automatic header management.

Installation

Install the SDK using Go modules:
go get github.com/coinbase/cdp-sdk/go

Package Import

import (
    "github.com/coinbase/cdp-sdk/go"
    "github.com/coinbase/cdp-sdk/go/openapi"
)

ClientOptions

Configuration options for creating a CDP client:
type ClientOptions struct {
    // API key ID
    APIKeyID string
    
    // API key secret (EC PEM or Ed25519 base64)
    APIKeySecret string
    
    // Wallet secret for signing transactions
    WalletSecret string
    
    // Enable debug logging
    Debugging bool
    
    // Base URL (defaults to production)
    BasePath string
    
    // JWT expiration time in seconds (defaults to 120)
    ExpiresIn int64
    
    // Host override for internal use
    HostOverride string
}

Field Descriptions

APIKeyID
string
required
Your CDP API key ID
APIKeySecret
string
required
Your CDP API key secret. Supports EC PEM keys and Ed25519 base64-encoded keys
WalletSecret
string
Wallet secret for signing transactions (base64-encoded EC DER private key)
Debugging
bool
default:"false"
Enable debug logging for requests and responses
BasePath
string
default:"https://api.cdp.coinbase.com/platform"
Base URL for the CDP API
ExpiresIn
int64
default:"120"
JWT expiration time in seconds
HostOverride
string
Override the host used for request routing (internal use only)

Creating a Client

Basic Client Creation

Create a new CDP client with API credentials:
package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/coinbase/cdp-sdk/go"
)

func main() {
    // Create client options
    options := cdp.ClientOptions{
        APIKeyID:     "your-api-key-id",
        APIKeySecret: "your-api-key-secret",
        WalletSecret: "your-wallet-secret",
    }
    
    // Create client
    client, err := cdp.NewClient(options)
    if err != nil {
        log.Fatalf("Failed to create client: %v", err)
    }
    
    // Use the client
    ctx := context.Background()
    resp, err := client.ListEvmAccountsWithResponse(ctx, &openapi.ListEvmAccountsParams{})
    if err != nil {
        log.Fatalf("Request failed: %v", err)
    }
    
    fmt.Printf("Status: %d\n", resp.StatusCode())
}

Client from Environment Variables

Load credentials from environment variables:
package main

import (
    "os"
    "log"
    
    "github.com/coinbase/cdp-sdk/go"
)

func main() {
    options := cdp.ClientOptions{
        APIKeyID:     os.Getenv("CDP_API_KEY_ID"),
        APIKeySecret: os.Getenv("CDP_API_KEY_SECRET"),
        WalletSecret: os.Getenv("CDP_WALLET_SECRET"),
    }
    
    client, err := cdp.NewClient(options)
    if err != nil {
        log.Fatalf("Failed to create client: %v", err)
    }
    
    // Use client...
}

Client with Custom Configuration

Configure additional options:
options := cdp.ClientOptions{
    APIKeyID:     "your-api-key-id",
    APIKeySecret: "your-api-key-secret",
    WalletSecret: "your-wallet-secret",
    Debugging:    true,
    ExpiresIn:    300, // 5 minutes
    BasePath:     "https://api.cdp.coinbase.com/platform",
}

client, err := cdp.NewClient(options)

Making API Requests

The client provides methods for all CDP API operations:

List EVM Accounts

ctx := context.Background()

params := &openapi.ListEvmAccountsParams{
    PageSize: openapi.NewOptional(10),
}

resp, err := client.ListEvmAccountsWithResponse(ctx, params)
if err != nil {
    log.Fatalf("Request failed: %v", err)
}

if resp.JSON200 != nil {
    for _, account := range resp.JSON200.Accounts {
        fmt.Printf("Account: %s\n", account.Address)
    }
}

Create EVM Account

ctx := context.Background()

body := openapi.CreateEvmAccountJSONRequestBody{
    Name: openapi.NewOptional("my-account"),
}

headers := openapi.CreateEvmAccountParams{
    XWalletAuth:      "", // Automatically set by client
    XIdempotencyKey: "unique-request-id",
}

resp, err := client.CreateEvmAccountWithResponse(ctx, &headers, body)
if err != nil {
    log.Fatalf("Request failed: %v", err)
}

if resp.JSON201 != nil {
    fmt.Printf("Created account: %s\n", resp.JSON201.Address)
}

Get EVM Account

ctx := context.Background()

address := "0x1234567890123456789012345678901234567890"

resp, err := client.GetEvmAccountWithResponse(ctx, address)
if err != nil {
    log.Fatalf("Request failed: %v", err)
}

if resp.JSON200 != nil {
    fmt.Printf("Account: %+v\n", resp.JSON200)
}

Update EVM Account

ctx := context.Background()

address := "0x1234567890123456789012345678901234567890"

body := openapi.UpdateEvmAccountJSONRequestBody{
    Name: openapi.NewOptional("updated-name"),
}

resp, err := client.UpdateEvmAccountWithResponse(ctx, address, body)
if err != nil {
    log.Fatalf("Request failed: %v", err)
}

if resp.JSON200 != nil {
    fmt.Printf("Updated account: %+v\n", resp.JSON200)
}

Authentication

The client automatically handles authentication using JWT tokens:

API Key Authentication

  • All requests include an Authorization: Bearer <token> header
  • JWT is automatically generated with the request method, host, and path
  • Supports both EC (ES256) and Ed25519 (EdDSA) key formats

Wallet Authentication

  • POST and DELETE requests to /accounts and /spend-permissions include X-Wallet-Auth header
  • Wallet JWT includes a hash of the request body for integrity
  • Uses ES256 signing with the wallet secret

Error Handling

Handle errors and check response status codes:
ctx := context.Background()

resp, err := client.GetEvmAccountWithResponse(ctx, "0x...")
if err != nil {
    log.Fatalf("Request failed: %v", err)
}

switch resp.StatusCode() {
case 200:
    fmt.Printf("Success: %+v\n", resp.JSON200)
case 404:
    fmt.Println("Account not found")
case 401:
    fmt.Println("Authentication failed")
default:
    fmt.Printf("Unexpected status: %d\n", resp.StatusCode())
}

Context and Cancellation

Use context for timeout and cancellation:
import "time"

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

resp, err := client.ListEvmAccountsWithResponse(ctx, &openapi.ListEvmAccountsParams{})
if err != nil {
    log.Fatalf("Request failed: %v", err)
}

Pagination

Handle paginated responses:
ctx := context.Background()

var allAccounts []openapi.EvmAccount
var pageToken *string

for {
    params := &openapi.ListEvmAccountsParams{
        PageSize:  openapi.NewOptional(50),
        PageToken: pageToken,
    }
    
    resp, err := client.ListEvmAccountsWithResponse(ctx, params)
    if err != nil {
        log.Fatalf("Request failed: %v", err)
    }
    
    if resp.JSON200 != nil {
        allAccounts = append(allAccounts, resp.JSON200.Accounts...)
        
        if resp.JSON200.NextPageToken == nil {
            break
        }
        pageToken = resp.JSON200.NextPageToken
    } else {
        break
    }
}

fmt.Printf("Total accounts: %d\n", len(allAccounts))

Complete Example

Full example with error handling:
package main

import (
    "context"
    "fmt"
    "log"
    "os"
    
    "github.com/coinbase/cdp-sdk/go"
    "github.com/coinbase/cdp-sdk/go/openapi"
)

func main() {
    // Load credentials from environment
    options := cdp.ClientOptions{
        APIKeyID:     os.Getenv("CDP_API_KEY_ID"),
        APIKeySecret: os.Getenv("CDP_API_KEY_SECRET"),
        WalletSecret: os.Getenv("CDP_WALLET_SECRET"),
    }
    
    // Create client
    client, err := cdp.NewClient(options)
    if err != nil {
        log.Fatalf("Failed to create client: %v", err)
    }
    
    ctx := context.Background()
    
    // List accounts
    listResp, err := client.ListEvmAccountsWithResponse(ctx, &openapi.ListEvmAccountsParams{
        PageSize: openapi.NewOptional(10),
    })
    if err != nil {
        log.Fatalf("Failed to list accounts: %v", err)
    }
    
    if listResp.JSON200 != nil {
        fmt.Printf("Found %d accounts\n", len(listResp.JSON200.Accounts))
        for _, account := range listResp.JSON200.Accounts {
            fmt.Printf("  - %s\n", account.Address)
        }
    }
}

See Also

Build docs developers (and LLMs) love