Context-first API, functional options, range-over-func iteration, zero non-stdlib dependencies. Go ≥ 1.23.
go get github.com/getinbio/inbio-goShorten a URL (no account)
import "github.com/getinbio/inbio-go"
link, err := inbio.Shorten(ctx, "https://example.com/very/long/url")
fmt.Println(link.ShortURL) // https://in.bio/a8K2pAuthenticated client
Pass a token or set INBIO_API_TOKEN in the environment:
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
// 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
_, 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
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 for the payload format.