Skip to content

Go Server SDK

Official Go server-side SDK — github.com/Captcha-La/captchala-go.

Three jobs the SDK handles for you:

  1. Validate — verify a pt_ pass token from the browser SDK.
  2. Issue — mint a one-time sct_ server token to bind the upcoming challenge to a specific action / IP / UID.
  3. Moderate — multi-modal (text + image) content moderation against the same OpenAI-compatible pipeline the dashboard uses.

Install

bash
go get github.com/Captcha-La/captchala-go

Stdlib only. No external dependencies.

Validate (pt_ token)

go
import captchala "github.com/Captcha-La/captchala-go"

client := captchala.NewClient(appKey, appSecret)

result, err := client.Validate(passToken)
if err != nil || !result.Valid {
    http.Error(w, result.Error, http.StatusBadRequest)
    return
}
// proceed with the request

If the original server_token was issued with bind_uid, compare:

go
if result.UID != expectedUserID {
    http.Error(w, "user mismatch", http.StatusBadRequest)
    return
}

For IP-bound tokens, pass the user IP on the verify side:

go
result, err := client.ValidateWithClientIP(passToken, false, userIP)

Issue a server token

Recommended for high-value flows (login, register, payment): backend mints a one-time sct_ token, hands it to the browser, browser uses it as the serverToken prop. Single-use, action-scoped, optionally IP/UID-bound.

go
issue, err := client.IssueServerTokenWithOptions("login", captchala.IssueOptions{
    BindingIP: userIP,    // backend rejects token if a different IP redeems it
    TTL:       300,       // seconds
    MaxUses:   5,         // SDK retry budget
    BindUID:   userID,    // pair with ValidateResult.UID on verify
})
if err != nil || !issue.OK {
    http.Error(w, issue.Error, http.StatusBadRequest)
    return
}
// hand issue.Token to the browser

Defaults-only shortcut:

go
issue, err := client.IssueServerToken("login")

Moderate content

Multi-modal — accepts a slice of ModerationItem (text and/or image_url in OpenAI-compatible format):

go
result, err := client.ModerationCheck([]captchala.ModerationItem{
    captchala.TextItem(userComment),
    captchala.ImageURLItem(uploadedImageURL),
}, userID)

if err != nil || !result.OK {
    http.Error(w, result.Error, http.StatusBadRequest)
    return
}

if result.Flagged {
    if result.HasCategory("violence", "csam") {
        // hard block
    }
}

Plain-text shortcut:

go
result, err := client.ModerationText("user comment here", userID)

Categories are model-defined; iterate result.Categories defensively rather than hard-coding a fixed set.

Types

TypeFields
ValidateResultValid, Error, UID, ChallengeID, Action, Offline, ClientOnly, Warning
IssueResultOK, Token, ExpiresIn, IssuedAt, Error, Message
IssueOptionsBindingIP, TTL, MaxUses, BindUID
ModerationItemType, Text, ImageURL (use TextItem() / ImageURLItem() helpers)
ModerationResultOK, Flagged, Categories, ContentType, Raw, Error, Message; method HasCategory(...names)

MIT-licensed examples · CaptchaLa is operated independently