Go SDK
Go SDK
The github.com/verbitas/sdk-go module is the official Go client for the Verbitas API.
- Module:
github.com/verbitas/sdk-go - Go: 1.23+
- License: MIT
Installation
go get github.com/verbitas/sdk-goConfiguration
package main
import ( verbitas "github.com/verbitas/sdk-go")
func main() { // From environment variable VERBITAS_API_KEY (recommended) client := verbitas.NewClient("")
// Explicit key client := verbitas.NewClient("vb_live_01j...")
// With options client := verbitas.NewClientWithOptions(verbitas.ClientOptions{ APIKey: os.Getenv("VERBITAS_API_KEY"), BaseURL: "https://api.verbitas.io", Timeout: 60 * time.Second, MaxRetries: 3, })}Signing
package main
import ( "context" "fmt" verbitas "github.com/verbitas/sdk-go")
func main() { client := verbitas.NewClient("")
result, err := client.Sign(context.Background(), "output.png", &verbitas.SignOptions{ Recipe: "image-genai-v1", Metadata: map[string]string{ "generator": "stable-diffusion-xl", "model": "sdxl-1.0", }, }) if err != nil { // see error handling section panic(err) }
fmt.Println(result.AssetID) // "a_01j..." fmt.Println(result.VerifierURL) // "https://v.verbitas.io/v/a_01j..." fmt.Println(result.ManifestURI) // "https://m.verbitas.io/manifests/..."}Sign from io.Reader
f, err := os.Open("output.png")if err != nil { panic(err)}defer f.Close()
result, err := client.SignReader(context.Background(), f, &verbitas.SignReaderOptions{ Recipe: "image-genai-v1", Filename: "output.png",})Large files (async)
Large files return a job ID. Use WaitForJob to poll:
job, err := client.SignAsync(context.Background(), "large_video.mp4", &verbitas.SignOptions{ Recipe: "video-genai-v1",})if err != nil { panic(err)}
result, err := client.WaitForJob(context.Background(), job.JobID, &verbitas.WaitOptions{ Timeout: 5 * time.Minute, PollInterval: 2 * time.Second,})Or use Sign which handles async transparently:
// Sign handles polling automatically for large filesresult, err := client.Sign(context.Background(), "large_video.mp4", &verbitas.SignOptions{ Recipe: "video-genai-v1", WaitSync: true, // block until done (default true)})Verifying
// By file pathresult, err := client.Verify(context.Background(), &verbitas.VerifyOptions{ FilePath: "received_image.jpg",})
// By asset IDresult, err := client.Verify(context.Background(), &verbitas.VerifyOptions{ AssetID: "a_01j...",})
// By manifest URIresult, err := client.Verify(context.Background(), &verbitas.VerifyOptions{ ManifestURI: "https://m.verbitas.io/manifests/a_01j.../manifest.c2pa",})
if err != nil { panic(err)}
fmt.Println(result.Status) // "verified_manifest_and_watermark_match"fmt.Println(result.Confidence) // 0.97Status constants
switch result.Status {case verbitas.StatusVerifiedManifestAndWatermarkMatch, verbitas.StatusVerifiedManifestIntact: // proceedcase verbitas.StatusManifestTampered: return fmt.Errorf("asset tampered: %s", result.DeveloperExplanation)case verbatas.StatusNoProvenance: // no record found}Lookup
result, err := client.Lookup(context.Background(), &verbitas.LookupOptions{ FilePath: "cropped_image.jpg",})if err != nil { panic(err)}
for _, match := range result.Matches { fmt.Printf("%s %s %.2f\n", match.AssetID, match.MatchType, match.Confidence)}Recipes
// Listrecipes, err := client.Recipes.List(context.Background())
// Getrecipe, err := client.Recipes.Get(context.Background(), "image-genai-v1")
// Create (requires admin key)yamlBytes, _ := os.ReadFile("my-recipe-v1.yaml")created, err := client.Recipes.Create(context.Background(), string(yamlBytes))Context support
All methods accept context.Context as the first argument. Use this for cancellation and deadlines:
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)defer cancel()
result, err := client.Sign(ctx, "output.png", &verbitas.SignOptions{ Recipe: "image-genai-v1",})Error handling
import ( "errors" verbitas "github.com/verbitas/sdk-go")
result, err := client.Sign(ctx, "image.png", &verbitas.SignOptions{Recipe: "image-genai-v1"})if err != nil { var apiErr *verbitas.APIError if errors.As(err, &apiErr) { switch apiErr.Code { case "verbitas.auth.invalid_key": log.Printf("invalid API key") case "verbitas.billing.quota_exceeded": log.Printf("monthly quota exceeded") case "verbitas.ratelimit.exceeded": log.Printf("rate limited; retry after %s", apiErr.RetryAfter) default: log.Printf("API error %s: %s (request_id=%s)", apiErr.Code, apiErr.Detail, apiErr.RequestID) } return } // network error, timeout, etc. log.Printf("error: %v", err)}Retries
The client automatically retries on 429 and 5xx responses with exponential backoff. The default is 3 retries. Configure with ClientOptions.MaxRetries.
Idempotency keys are generated automatically for each sign call. To provide your own:
result, err := client.Sign(ctx, "output.png", &verbitas.SignOptions{ Recipe: "image-genai-v1", IdempotencyKey: "01926e7a-f2b3-7abc-8def-0123456789ab",})Environment variables
| Variable | Description |
|---|---|
VERBITAS_API_KEY | API key |
VERBITAS_BASE_URL | Override base URL |