← Blog

Claude API Go SDK Example: Build a Client in Golang

2026-10-13 · 4 min read · SubToAPI Team

If you're searching for a "Claude API Golang SDK," here's the short answer: Anthropic does not publish an official Go SDK. They maintain official SDKs for Python and TypeScript/JavaScript, and a handful of community-maintained Go packages exist, but none of them are first-party or guaranteed to track new features on day one.

The good news is that you don't actually need an SDK to use Claude from Go. The Messages API is a plain JSON-over-HTTPS endpoint, and Go's standard net/http package handles it in about 40 lines of code. Below is a working example, plus how to handle streaming and tool use, and a note on using Claude through SubToAPI if you want a REST endpoint with API keys and usage metadata without wiring up Anthropic auth yourself.

A Minimal Go Client for the Messages API

This example sends a single message to Claude and prints the text response:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

type message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type request struct {
	Model     string    `json:"model"`
	MaxTokens int       `json:"max_tokens"`
	Messages  []message `json:"messages"`
}

type contentBlock struct {
	Type string `json:"type"`
	Text string `json:"text"`
}

type response struct {
	Content []contentBlock `json:"content"`
}

func main() {
	reqBody := request{
		Model:     "claude-3-5-sonnet-20241022",
		MaxTokens: 1024,
		Messages: []message{
			{Role: "user", Content: "Explain goroutines in two sentences."},
		},
	}

	payload, _ := json.Marshal(reqBody)

	req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", bytes.NewBuffer(payload))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-api-key", os.Getenv("ANTHROPIC_API_KEY"))
	req.Header.Set("anthropic-version", "2023-06-01")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result response
	json.Unmarshal(body, &result)

	for _, block := range result.Content {
		if block.Type == "text" {
			fmt.Println(block.Text)
		}
	}
}

This is effectively what an SDK's Messages.Create() call does under the hood: build a struct, marshal it to JSON, set headers, and parse the response. Once you have this pattern, you can reuse it across every project without depending on a third-party package's release cycle.

Handling Errors and Retries

Production code needs to check the HTTP status code and handle rate limits (429) and server errors (5xx) with backoff:

if resp.StatusCode != http.StatusOK {
	var apiErr struct {
		Error struct {
			Type    string `json:"type"`
			Message string `json:"message"`
		} `json:"error"`
	}
	json.Unmarshal(body, &apiErr)
	fmt.Printf("API error (%d): %s - %s\n", resp.StatusCode, apiErr.Error.Type, apiErr.Error.Message)
	return
}

Wrap the whole call in a retry loop with exponential backoff for 429 and 503 responses — this is the part most hand-rolled Go clients get wrong, since Claude's rate limits apply per-model and per-organization.

Streaming Responses in Go

Claude streams responses as Server-Sent Events. In Go, you read the response body line by line and parse data: lines as JSON events:

req.Header.Set("Accept", "text/event-stream")
reqBody.Stream := true // add Stream bool `json:"stream"` to the struct

resp, _ := client.Do(req)
defer resp.Body.Close()

scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
	line := scanner.Text()
	if strings.HasPrefix(line, "data: ") {
		data := strings.TrimPrefix(line, "data: ")
		var event map[string]interface{}
		json.Unmarshal([]byte(data), &event)
		if delta, ok := event["delta"].(map[string]interface{}); ok {
			if text, ok := delta["text"].(string); ok {
				fmt.Print(text)
			}
		}
	}
}

This is the same event structure Anthropic's Python and TypeScript SDKs parse internally — you're just doing it manually with bufio.Scanner.

Tool Use from Go

Tool calling works the same way: you send a tools array describing JSON schemas, and Claude returns tool_use content blocks with structured arguments instead of (or alongside) text. In Go you'd define the tool as a Go struct marshaled to JSON, then switch on block.Type == "tool_use" to extract block.Input and dispatch to your actual function. There's no magic here — it's the same request/response loop as above, just with an extra field in the payload and an extra case in your parsing switch.

A Simpler Alternative: Skip the Auth Plumbing

Writing your own Go client is a reasonable choice if you want zero dependencies. But if you're building something for a team — multiple services, multiple environments, or non-engineers who need usage visibility — raw API keys scattered across config files get messy fast.

SubToAPI turns your existing Claude access into a standard HTTPS API with its own sub_live_... keys, so your Go code talks to one stable endpoint regardless of which underlying Claude plan or account is behind it:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Explain goroutines in two sentences."}]
  }'

From your Go client, this means swapping two header values (Authorization: Bearer instead of x-api-key) and pointing at api.subtoapi.app instead of api.anthropic.com. You get streaming, tool use, and per-key usage metadata out of the box, plus team seats if you have more than one developer calling Claude. See the quickstart, the messages reference, streaming, and tool use docs. Plans start at €9 for Solo, €19/seat for Team, and €49/seat for Scale — check pricing or start a trial at signup.

questions

Is there an official Anthropic Go SDK? No. Anthropic currently ships official SDKs for Python and TypeScript/JavaScript only. Go developers either call the HTTP API directly with net/http or use a community-maintained package, which may lag behind new API features.

Can I use Claude's streaming API in Go without an SDK? Yes. The Messages API streams standard Server-Sent Events over HTTP, which you can read with bufio.Scanner on the response body and parse each data: line as JSON — no special library required.

What's the fastest way to add Claude to a Go backend without managing API keys directly? Route your Go HTTP client at a managed endpoint like SubToAPI, which issues its own API keys and handles usage tracking and team access, so your code only needs a bearer token and a base URL change.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →