EnfinitOSEnfinitOS
DevelopersOperator & brand
Production-ready scaffold

Brand SDK — Go

Idiomatic Go client — context propagation, typed errors, no third-party HTTP deps.

github.com/enfinitos/sdk-brand-goSubstrate ALLGo
Install

Get the SDK

go get github.com/enfinitos/sdk-brand-go

About this status badge

Typed, tested, documented, and grounded in the 2026 platform reality. Awaiting first customer-integration validation.

README

The developer-facing documentation in full

Rendered from packages/sdks/brand-go/README.md at build time — the same source the package ships with.

enfinitos-sdk-brand-go

EnfinitOS Brand/Advertiser SDK — a lightweight Go client that lets a brand (advertiser) query its own delivery proof, metering, and settlement records directly, without going through the operator's reporting plane. Read-only by design and scoped to campaigns the brand owns.

Go counterpart of @enfinitos/sdk-brand (TypeScript) and enfinitos_brand (Python). Same wire shape, idiomatic Go: context.Context first, stdlib net/http, zero third-party dependencies.

Who should use this

You are a brand (advertiser) and:

  • your data pipeline lives in Go (microservice, AR/finance batch job, Kubernetes controller, …);
  • you need to reconcile EnfinitOS invoices against your own impression logs or auditor analysis;
  • you want to file disputes backed by signed counter-evidence the operator is contractually bound to respond to.

If you are an operator, you want the operator-web SDK instead. If you are an auditor verifying signatures, you want enfinitos-sdk-auditor-go for the cryptographic primitives. The brand SDK pulls the data; the auditor SDK verifies it.

Authentication

Authorization: Bearer brk_…
X-Enfinitos-Brand: brand_acme

Brand API keys are issued by EnfinitOS to the brand's tenant admin via the brand portal. They are scoped read-only to records the brand owns. Disputes are the only write surface and are bound to the brand's own auditor-key signature, not the API key.

Installation

go get github.com/enfinitos/ar-campaign-os/packages/sdks/brand-go

Requires Go 1.21+. The SDK depends only on the Go standard library.

Getting started

package main

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

    brand "github.com/enfinitos/ar-campaign-os/packages/sdks/brand-go"
)

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

    client, err := brand.NewEnfinitOSBrandClient(brand.ClientOptions{
        APIBaseURL: "https://api.enfinitos.com",
        BrandID:    os.Getenv("ENFINITOS_BRAND_ID"),
        APIKey:     os.Getenv("ENFINITOS_BRAND_API_KEY"),
    })
    if err != nil {
        log.Fatal(err)
    }

    // 1. List active campaigns.
    page, err := client.Campaigns.List(ctx, brand.CampaignsListOptions{
        Status: brand.CampaignActive,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Brand has %d active campaigns\n", len(page.Items))

    // 2. For each, pull the signed proof pack + metering summary.
    for _, cmp := range page.Items {
        pack, err := client.Proof.Pack(ctx, cmp.CampaignID)
        if err != nil {
            log.Printf("proof pack %s: %v", cmp.CampaignID, err)
            continue
        }
        summary, err := client.Metering.Summary(ctx, cmp.CampaignID)
        if err != nil {
            log.Printf("metering summary %s: %v", cmp.CampaignID, err)
            continue
        }
        fmt.Println(cmp.Name, summary.Totals, len(pack.PackBytesB64))

        // 3. Hand the pack to the Auditor SDK to verify the
        //    signature + Merkle structure.
        //
        //    auditor "github.com/.../sdk-auditor-go"
        //    verdict, err := auditor.VerifyPack(pack)
    }
}

Module reference

NamespaceMethodsPurpose
client.CampaignsList, GetBrand-owned campaigns. Read-only.
client.ProofSummary, Pack, ChainSigned evidence (Merkle-rooted per-render ledger). Verify with Auditor SDK.
client.MeteringSummary, BreakdownBillable-unit rollups per campaign.
client.SettlementInvoices, Invoice, LineInvoices issued to the brand, with per-line proof-slice roots.
client.DisputesOpen, List, GetBrand-raised disputes, backed by signed evidence. The SDK's only write surface.

See types.go for the full set of typed contracts.

Error model

All non-2xx responses surface as *APIError:

type APIError struct {
    Code                  string         // "UNAUTHORIZED", "CAMPAIGN_NOT_FOUND", …
    Message               string
    HTTPStatus            int
    CorrelationID         string         // bind to platform logs
    Details               map[string]any
    ServerContractVersion *int
}

Use errors.As to recover:

var apiErr *brand.APIError
if errors.As(err, &apiErr) {
    if apiErr.IsRetryable() {
        // 408/429/5xx — back-off and retry
    }
    if apiErr.Code == "CAMPAIGN_NOT_FOUND" { ... }
}

var txErr *brand.TransportError
if errors.As(err, &txErr) {
    // DNS / reset / timeout — request never reached the platform.
    // Always safe to retry.
}

The SDK does not retry automatically. Brand-side systems typically sit behind their own retry middleware; a second layer of retries causes phantom-duplicate dispute filings. Opt in via apiErr.IsRetryable().

Context and deadlines

Every network method takes a context.Context as its first argument:

ctx, cancel := context.WithDeadline(ctx, deadline)
defer cancel()
campaigns, err := client.Campaigns.List(ctx, brand.CampaignsListOptions{})

The SDK's ClientOptions.Timeout applies if the caller's context has no deadline. Use the caller's context for tight per-call deadlines.

Cross-reference: Auditor SDK

The brand SDK returns evidence; the Auditor SDK verifies it. The two are deliberately separate packages so you can ship the verifier into an air-gapped environment (a regulator's lab, an internal compliance service) without also pulling in the HTTP client.

Brand SDK outputAuditor SDK function
SignedProofPackauditor.VerifyPack(pack)
ProofRecord + Merkle pathauditor.VerifyLeafInclusion(record, path, root)
InvoiceLine.ProofSliceRootauditor.VerifySlice(slice, root)
SignedEvidence (dispute)auditor.VerifyEvidence(evidence, publicKey)

Versioning

The SDK pins a wire-protocol contract version (ContractVersion). The platform echoes its own version in X-Contract-Version on every response; a brand-side monitoring system that wants to detect drift should compare the two. Minor additions (new optional fields, new metering units) do not bump the contract; non-additive changes do.

Status

Initial release. The brand SDK is API-stable; the underlying platform contracts are at contract version 1.

API reference

Hit the HTTP surface directly

The Brand SDK — Go is a thin client over the same governed HTTP API every other SDK calls. The full OpenAPI 3.1 reference lives on the docs site.

Sandbox

Run this SDK against a real tenant

The hosted sandbox is the fastest way to verify Brand SDK — Go against a real EnfinitOS tenant before committing to a pilot. Launching Q4 2026.