Go Server SDK
Official Go server-side SDK — github.com/Captcha-La/captchala-go.
Three jobs the SDK handles for you:
- Validate — verify a
pt_pass token from the browser SDK. - Issue — mint a one-time
sct_server token to bind the upcoming challenge to a specific action / IP / UID. - 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-goStdlib 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 requestIf 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 browserDefaults-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
| Type | Fields |
|---|---|
ValidateResult | Valid, Error, UID, ChallengeID, Action, Offline, ClientOnly, Warning |
IssueResult | OK, Token, ExpiresIn, IssuedAt, Error, Message |
IssueOptions | BindingIP, TTL, MaxUses, BindUID |
ModerationItem | Type, Text, ImageURL (use TextItem() / ImageURLItem() helpers) |
ModerationResult | OK, Flagged, Categories, ContentType, Raw, Error, Message; method HasCategory(...names) |