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:
audact.WithBaseURL("https://...")- the
AUDACT_BASE_URLenvironment variable audact.DefaultBaseURL
A trailing / and a trailing /v1 are stripped; every request path is
prefixed with /v1.
Authentication
| Kind | How to set it | Header |
|---|---|---|
| Tenant API key | NewClient(key) or AUDACT_API_KEY | Authorization: Bearer <key> |
| Org token | audact.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
| Accessor | Area |
|---|---|
c.Agents | Agents and voices |
c.Calls | Call records, SIP call control, transfers, routes |
c.Numbers | Phone numbers, KYC, BYO connections |
c.Webhooks | Webhooks and deliveries |
c.Tools | Agent tools |
c.Integrations | Third-party integrations |
c.KnowledgeBases | Knowledge bases (RAG): sources, agent links, crawl exclusions, retrieval tests |
c.Evidence | Evidence chains, receipts, compliance events, C2PA content credentials |
c.PII | PII shredding, identities, exemptions |
c.Validator | Validation and scoring |
c.LLMProxy | LLM proxy (including streaming) |
c.Tenants | Tenants, keys, configurations |
c.Org | Organization accounts |
c.Aggregation | Aggregation proofs and metachain |
c.Policy | Policy evaluation and calling hours |
c.Audio | Audio validation and reconciliation |
c.Auth | API key exchange and refresh |
License
MIT
