Skip to main content
Audact
See the offer

Go SDK

Standard-library Go client for the Audact API. Covers calls, numbers, evidence, webhooks and more with typed errors and context.Context support.

Hand-written, standard-library-only Go client for the Audact API. It covers the Audact API, with typed errors and context.Context on every call.

Install

The Go SDK is not published yet. Installation instructions will appear here when it is.

Requires Go 1.24 or newer. The module has no third-party dependencies.

Quickstart

go

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	audact "github.com/audactai/audact-go-sdk"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	c, err := audact.NewClient("") // reads AUDACT_API_KEY
	if err != nil {
		log.Fatal(err)
	}
	agents, err := c.Agents.List(ctx, &audact.ListAgentsParams{Limit: 10})
	if err != nil {
		log.Fatal(err)
	}
	for _, a := range agents.Agents {
		fmt.Println(a.AgentID, a.Name)
	}
}

A fuller example lives in examples/quickstart.

Base URL

The default is https://api.audact.ai. Resolution order:

  1. audact.WithBaseURL("https://...")
  2. the AUDACT_BASE_URL environment variable
  3. audact.DefaultBaseURL

A trailing / and a trailing /v1 are stripped; every request path is prefixed with /v1.

Authentication

KindHow to set itHeader
Tenant API keyNewClient(key) or AUDACT_API_KEYAuthorization: Bearer <key>
Org tokenaudact.WithOrgToken(t), or c.Org.Login / Signup (stored automatically). c.Org.Refresh reads the refresh cookie, so it needs an http.Client with a cookie jar (WithHTTPClient)Authorization: Bearer <token>

NewClient does not fail for a missing key because some operations are public. It returns an error only for an invalid base URL or a nil option. If a needed credential is empty the header is omitted and the server's 401 surfaces as audact.ErrUnauthorized.

Errors

Non-2xx responses return *audact.APIError, which carries StatusCode, Code, Message, Hint, Details and RequestID.

go

_, err := c.Calls.Get(ctx, "call_123")
var apiErr *audact.APIError
switch {
case errors.Is(err, audact.ErrNotFound):
	fmt.Println("no such call")
case errors.As(err, &apiErr):
	fmt.Println(apiErr.StatusCode, apiErr.Code, "request_id:", apiErr.RequestID)
case err != nil:
	log.Fatal(err) // transport error, wrapped with %w
}

Sentinels: ErrUnauthorized (401), ErrForbidden (403), ErrNotFound (404), ErrConflict (409), ErrRateLimited (429). A 429 returns *audact.RateLimitError; use RetryAfter for the server's requested delay:

go

var rl *audact.RateLimitError
if errors.As(err, &rl) {
	time.Sleep(rl.RetryAfter)
}

Retries and idempotency

The SDK never retries on its own. Writes that create evidence or other permanent records accept an idempotency key: pass the same key when you retry and the server replays the first response instead of acting twice. An empty key sends no Idempotency-Key header.

go

m, err := c.Evidence.GenerateC2PAManifest(ctx, callID, "c2pa-"+callID)

Methods with an idempotency key include Evidence.PostEvent, Evidence.ConfirmDelivery, Evidence.ReconcileTranscript, and Evidence.GenerateC2PAManifest. C2PA manifests and evidence events are append-only, so a retry without a key stores a duplicate permanently.

Context and timeouts

Every method takes a context.Context first; cancellation and deadlines are honored, and errors.Is(err, context.DeadlineExceeded) works. The default HTTP client has a 30 s timeout. Supply your own with WithHTTPClient:

go

c, err := audact.NewClient("", audact.WithHTTPClient(&http.Client{Timeout: 10 * time.Second}))

WithUserAgent("myapp/1.0") appends to the default audact-go/0.3.0 agent.

Streaming

c.LLMProxy.Stream returns a *Stream over server-sent events. The proxy validates the reply one sentence at a time: Current() is the sentence text, and Chunk().AudactValidation carries its verdict (MODIFY means the text was rewritten; a BLOCK chunk carries the fallback line and ends the stream). Tool-call deltas arrive as chunks with no AudactValidation.

go

st, err := c.LLMProxy.Stream(ctx, nil, &audact.ChatCompletionRequest{
	Messages: []audact.ChatMessage{{Role: "user", Content: "Hello"}},
})
if err != nil {
	log.Fatal(err)
}
defer st.Close()
for st.Next() {
	if v := st.Chunk().AudactValidation; v != nil && v.Verdict == "BLOCK" {
		log.Println("reply blocked by compliance check")
	}
	fmt.Print(st.Current())
}
if err := st.Err(); err != nil {
	log.Fatal(err)
}

PII helpers

audact.NormalizeIdentifier(typ, value) canonicalises a name, email or phone identifier, and audact.ClientHash(typ, value) computes the client-side hash. Both match the TypeScript and Python SDKs on the shared test vectors.

go

h, err := audact.ClientHash("email", "Jane@Example.com")

Services

AccessorArea
c.AgentsAgents and voices
c.CallsCall records, SIP call control, transfers, routes
c.NumbersPhone numbers, KYC, BYO connections
c.WebhooksWebhooks and deliveries
c.ToolsAgent tools
c.IntegrationsThird-party integrations
c.KnowledgeBasesKnowledge bases (RAG): sources, agent links, crawl exclusions, retrieval tests
c.EvidenceEvidence chains, receipts, compliance events, C2PA content credentials
c.PIIPII shredding, identities, exemptions
c.ValidatorValidation and scoring
c.LLMProxyLLM proxy (including streaming)
c.TenantsTenants, keys, configurations
c.OrgOrganization accounts
c.AggregationAggregation proofs and metachain
c.PolicyPolicy evaluation and calling hours
c.AudioAudio validation and reconciliation
c.AuthAPI key exchange and refresh

License

MIT

Source updated: October 19, 2026