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 wired to the EnfinitOS platform endpoints that exist today. Vendor-side SDK integrations (Broadsign / VIOOH / DJI / Tizen / Alexa / Twilio / Stripe / etc.) land per-customer at pilot integration time — those bring the renderer/transport/exchange-specific code; the EnfinitOS half is ready.

README

The developer-facing documentation in full

The same README the SDK package ships with — rendered here at build time so what you read matches exactly what you install.

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/sdk-brand-go

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

Getting started

package main

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

    brand "github.com/enfinitos/sdk-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, published alongside the April 2027 platform launch.

Sandbox

Run this SDK against a real tenant

The browser demo at enfinitos.com/sandbox runs today against a shared synthetic tenant. The dedicated developer sandbox — your own persistent tenant, API keys, full HTTP-contract coverage — opens ahead of the April 2027 platform launch.