---
title: "Go"
description: "The official INBIO SDK for Go — context-first, zero dependencies."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.in.bio/llms.txt
> Use this file to discover all available pages before exploring further.

# Go

Context-first API, functional options, range-over-func iteration, zero
non-stdlib dependencies. Go ≥ 1.23.

```bash
go get github.com/getinbio/inbio-go
```

## Shorten a URL (no account)

```go
import "github.com/getinbio/inbio-go"

link, err := inbio.Shorten(ctx, "https://example.com/very/long/url")
fmt.Println(link.ShortURL) // https://in.bio/a8K2p
```

## Authenticated client

Pass a token or set `INBIO_API_TOKEN` in the environment:

```go
client := inbio.NewClient() // reads INBIO_API_TOKEN
// or: inbio.NewClient(inbio.WithToken("..."), inbio.WithTimeout(10*time.Second))

created, err := client.Links.Create(ctx, &inbio.CreateLinkParams{
DestinationURL: "https://example.com/sale",
Slug:           inbio.String("spring-sale"),
Tags:           []string{"marketing"},
UTM:            &inbio.UTM{Source: "newsletter", Medium: "email"},
})
```

## Everything else

```go
// List with filters, or iterate every page automatically
page, err := client.Links.List(ctx, &inbio.ListOptions{Status: "active", PerPage: 50})
for link, err := range client.Links.Iter(ctx, &inbio.ListOptions{Tag: "marketing"}) {
if err != nil { break }
fmt.Println(link.Slug, link.TotalClicks)
}

// Update, toggle, delete
client.Links.Update(ctx, 42, &inbio.UpdateLinkParams{Title: inbio.String("Renamed")})
client.Links.Disable(ctx, 42)
client.Links.Enable(ctx, 42)
client.Links.Delete(ctx, 42)

// QR code bytes → file
qr, err := client.Links.QR(ctx, 42, &inbio.QROptions{Format: "png", Size: 1024})
os.WriteFile("qr.png", qr.Data, 0o644)

// Analytics, folders, tags, usage
stats, err := client.Links.Analytics(ctx, 42, &inbio.AnalyticsOptions{From: "2026-06-01"})
folders, err := client.Folders.List(ctx)
tags, err := client.Tags.List(ctx)
usage, err := client.Account.Usage(ctx)
```

## Errors

```go
_, err := client.Links.Create(ctx, params)

var vErr *inbio.ValidationError
if errors.As(err, &vErr) {
fmt.Println(vErr.Errors) // per-field messages
}
var rlErr *inbio.RateLimitError
if errors.As(err, &rlErr) {
fmt.Println(rlErr.RetryAfter)
}
```

`AuthenticationError` (401), `AccessError` (403, plan or scope),
`NotFoundError`, `ValidationError`, `EntitlementError`, `StateConflictError`
(409), `RateLimitError` (429), `ServerError` — every typed error also unwraps
to the base `*inbio.Error`. GETs and `Retry-After` 429s are retried
automatically with backoff.

## Webhooks

```go
event, err := client.Webhooks.Verify(rawBody, r.Header.Get("X-Inbio-Signature"), secret, 0)
if err != nil {
http.Error(w, "bad signature", http.StatusBadRequest)
return
}
if event.Event == "link.clicked" {
link, _ := event.Link()
// ...
}
```

Signatures are checked with a constant-time comparison and a 5-minute
replay-protection window (pass `0` for the default tolerance). See
[Webhooks](/api/webhooks) for the payload format.

Source: https://docs.in.bio/sdks/go/index.mdx
