Go SDK
Biometry Go SDK
The official Go SDK for the Biometry platform. It provides a simple, idiomatic Go interface for biometric verification, document authentication, and transaction management — all authenticated via API keys.
Repository: github.com/Namadgi/biometry-go
Features
- Session Management: Start and end biometric verification sessions
- Video Processing: Submit videos for multi-service biometric verification
- Face & Voice Enrollment: Enroll users for face and voice recognition
- Face Matching: Compare faces from images and videos, with session video reuse
- Document Authentication: Verify document authenticity with MRZ validation
- Transaction Queries: List, count, filter, and tag transactions
- Anti-Video Forgery: Detect video manipulation attempts
- API Key Management: Mint, revoke, and inspect API keys
- Zero Dependencies: Uses only Go standard library (
net/http)
Installation
go get github.com/Namadgi/biometry-goRequires Go 1.26.1 or later.
Quick Start
Initialize the client
package main
import ( "context" "fmt" "log" "os"
"github.com/Namadgi/biometry-go")
func main() { client := biometry.NewClient( os.Getenv("BIOMETRY_API_KEY"), )
ctx := context.Background()
sessionID, err := client.Sessions.Start(ctx) if err != nil { log.Fatal(err) } fmt.Println("Session:", sessionID)}Client options
| Option | Description |
|---|---|
WithBaseURL(url) | Override the default API base URL |
WithHTTPClient(hc) | Use a custom *http.Client for timeouts or transport |
WithUserFullname(name) | Set the default X-User-Fullname header |
WithUserAgent(ua) | Override the default User-Agent |
Per-request options
| Option | Description |
|---|---|
WithFullname(name) | Override X-User-Fullname for a single call |
WithSessionID(id) | Set X-Session-ID for a single call |
WithActionTrigger(trigger) | Set X-Action-Trigger for a single call |
WithDeviceInfo(json) | Set X-Device-Info — JSON-encoded device metadata |
WithGeoLocation(json) | Set X-Geo-Location — JSON-encoded geo data (overrides IP lookup) |
WithRequestTags(tags) | Set X-Request-Tags — comma-separated labels |
WithClientApp(app) | Set X-Client-App — calling application name |
WithClientVersion(ver) | Set X-Client-Version — client version string |
WithInhouseDocAuth(bool) | Set X-Inhouse-Docauth — use in-house (true) or IDScan (false) |
WithMRZValidation(bool) | Set X-Inhouse-MRZ — enable MRZ validation for doc auth |
Full Verification Flow
A typical biometric onboarding session involves: starting a session, verifying a document, enrolling the face, processing a live video, matching the document photo against the video, and ending the session.
ctx := context.Background()
// 1. Start sessionsessionID, err := client.Sessions.Start(ctx)if err != nil { log.Fatal(err)}
// 2. Approve consent biometry.WithSessionID(sessionID))
// 3. Document authenticationdocFile, _ := os.Open("passport.jpg")defer docFile.Close()
docResp, err := client.DocAuth.Check(ctx, docFile, "passport.jpg", biometry.WithSessionID(sessionID))if err != nil { log.Fatal(err)}
var docInfo biometry.DocAuthInfoif err := docResp.Decode(&docInfo); err != nil { log.Fatal(err)}fmt.Printf("Name: %s %s, Country: %s\n", docInfo.FirstName, docInfo.LastName, docInfo.CountryCode)
// 4. Enroll face from documentdocPhoto, _ := os.Open("passport.jpg")defer docPhoto.Close()
_, err = client.Enrollment.Face(ctx, biometry.EnrollFaceInput{ Face: docPhoto, FileName: "passport.jpg", IsDocument: true,}, biometry.WithSessionID(sessionID))
// 5. Process live videovideoFile, _ := os.Open("selfie.mp4")defer videoFile.Close()
videoResp, err := client.Video.Process(ctx, biometry.ProcessVideoInput{ Video: videoFile, VideoName: "selfie.mp4", Phrase: "one two three four five",}, biometry.WithSessionID(sessionID))if err != nil { log.Fatal(err)}fmt.Printf("Score: %.2f, Decisions: %v\n", videoResp.Score, videoResp.DecisionReasons)
// 6. Face match — document vs video (reuses video from step 5)matchPhoto, _ := os.Open("passport.jpg")defer matchPhoto.Close()
matchResp, err := client.FaceMatch.MatchWithSessionVideo(ctx, matchPhoto, "passport.jpg", sessionID)fmt.Printf("Match score: %.2f\n", matchResp.Score)
// 7. End sessionif err := client.Sessions.End(ctx, sessionID, nil); err != nil { log.Printf("Failed to end session: %v", err)}Services Reference
Sessions
// Start a new sessionsessionID, err := client.Sessions.Start(ctx)
// End a session (optional phone number for telco fraud check)err := client.Sessions.End(ctx, sessionID, &biometry.EndSessionRequest{ PhoneNumber: "+61400000000",})Process Video
resp, err := client.Video.Process(ctx, biometry.ProcessVideoInput{ Video: videoReader, // io.Reader VideoName: "video.mp4", Phrase: "one two three four five", Vocabulary: "", // optional Trigger: "", // optional}, biometry.WithSessionID(sessionID))
// resp.Score, resp.DecisionReasons, resp.ScoringResult available// resp.Decode(&yourStruct) to parse the data fieldEnrollment
// Face enrollmentresp, err := client.Enrollment.Face(ctx, biometry.EnrollFaceInput{ Face: faceReader, FileName: "photo.jpg", IsDocument: false,}, biometry.WithSessionID(sessionID))
// Voice enrollment (multiple files)resp, err := client.Enrollment.Voice(ctx, biometry.EnrollVoiceInput{ Files: []biometry.VoiceFile{ {FileName: "voice1.wav", Content: reader1}, {FileName: "voice2.wav", Content: reader2}, }, Phrases: []string{"hello world", "test phrase"},}, biometry.WithSessionID(sessionID))Face Match
// Standard — upload both image and videoresp, err := client.FaceMatch.Match(ctx, imageReader, "photo.jpg", videoReader, "video.mp4", biometry.WithSessionID(sessionID))
// Preloaded — reuse video from a previous process-video callresp, err := client.FaceMatch.MatchWithSessionVideo(ctx, imageReader, "photo.jpg", sessionID)Document Authentication
resp, err := client.DocAuth.Check(ctx, docReader, "passport.jpg", biometry.WithSessionID(sessionID))
var info biometry.DocAuthInforesp.Decode(&info)// info.FirstName, info.LastName, info.DocumentType, info.CountryCode, etc.Transactions
// List with filterstxns, err := client.Transactions.List(ctx, biometry.TransactionListRequest{ Page: 1, PageSize: 20, Decision: "approved",})
// Countcount, err := client.Transactions.Count(ctx, biometry.TransactionListRequest{ FromDate: "2025-01-01", ToDate: "2025-12-31",})
// Get by sessiontxns, err := client.Transactions.GetBySession(ctx, sessionID)
// Update tagserr := client.Transactions.UpdateTags(ctx, txnID, []string{"vip", "verified"})
// Flag as fraudulenterr := client.Transactions.Flag(ctx, txnID, "fraudulent")API Keys
// Get current key infoinfo, err := client.APIKeys.Info(ctx)
// Mint a new keynewKey, err := client.APIKeys.Mint(ctx)
// Revoke a keyerr := client.APIKeys.Revoke(ctx, "key-id-to-revoke")Consents
// Approve consenterr := client.Consents.Approve(ctx, "consent-id", "user-id", biometry.WithSessionID(sessionID))
// Create or update a consentconsent, err := client.Consents.Create(ctx, biometry.ConsentInput{ UserID: "user-id",})
// Storage consenterr = client.Consents.StorageConsent(ctx, "consent-id", "user-id")Fraud
// Query fraud eventsevents, err := client.Fraud.QueryEvents(ctx, biometry.EventQuery{ UserID: "user-id",})
// Get user risk profilesprofile, err := client.Fraud.RiskProfile(ctx, "user-id")
// Review eventserr = client.Fraud.Review(ctx, "event-id", "approved")Webhooks
// Create a webhookhook, err := client.Webhooks.Create(ctx, biometry.WebhookInput{ URL: "https://example.com/webhook", Events: []string{"transaction.approved"},})
// Rotate secretnewSecret, err := client.Webhooks.RotateSecret(ctx, hook.ID)
// List deliveries and retrydeliveries, err := client.Webhooks.ListDeliveries(ctx, hook.ID)err = client.Webhooks.RetryDelivery(ctx, hook.ID, deliveries[0].ID)Anti-Video Forgery
// Start anti-forgery inference on a videoresp, err := client.AVF.StartInference(ctx, videoReader, "video.mp4")
// Check inference statusstatus, err := client.AVF.CheckStatus(ctx, resp.RequestID)Error Handling
All methods return *biometry.APIError for HTTP 4xx/5xx responses:
resp, err := client.Video.Process(ctx, input)if err != nil { var apiErr *biometry.APIError if errors.As(err, &apiErr) { fmt.Printf("HTTP %d: %s\n", apiErr.StatusCode, apiErr.Message) }}
// Convenience predicatesif biometry.IsNotFound(err) { ... }if biometry.IsForbidden(err) { ... }if biometry.IsUnauthorized(err) { ... }Response Envelope
Endpoints like Process Video, Face Match, DocAuth, and Enrollment return a *biometry.Response envelope that includes scoring data:
type Response struct { Data json.RawMessage // the main result ScoringResult json.RawMessage // scoring system output Score float64 // numeric score DecisionReasons []string // reasons for the decision Message string // status message Header http.Header // raw HTTP response headers}
// Decode the Data field into a typed struct:var result MyStructresp.Decode(&result)Response Headers
The *Response exposes HTTP response headers through convenience methods and the raw Header field:
resp, err := client.Video.Process(ctx, input, biometry.WithSessionID(sessionID))
// Convenience methodsfmt.Println("Request ID:", resp.RequestID()) // X-Request-Idfmt.Println("Auto enrolled:", resp.AutoEnrolled()) // X-Auto-Enroll == "true"fmt.Println("Services removed:", resp.RemovedServices()) // X-Removed-Services == "true"
// Raw header access for any other headerfmt.Println(resp.Header.Get("X-Custom-Header"))| Method | Header | Description |
|---|---|---|
resp.RequestID() | X-Request-Id | Unique request ID for tracking and support |
resp.AutoEnrolled() | X-Auto-Enroll | True if face/voice auto-enrollment was performed |
resp.RemovedServices() | X-Removed-Services | True if services were removed due to missing consent |
DocAuth with MRZ validation
resp, err := client.DocAuth.Check(ctx, docFile, "passport.jpg", biometry.WithSessionID(sessionID), biometry.WithInhouseDocAuth(true), biometry.WithMRZValidation(true),)
var info biometry.DocAuthInforesp.Decode(&info)fmt.Printf("MRZ valid: %v, Discrepancies: %v\n", info.MRZValidation.CheckDigitsValid, info.MRZValidation.Discrepancies)fmt.Println("Request ID:", resp.RequestID())