Skip to content

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

Terminal window
go get github.com/Namadgi/biometry-go

Requires 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

OptionDescription
WithBaseURL(url)Override the default API base URL
WithHTTPClient(hc)Use a custom *http.Client for timeouts or transport
WithUserAgent(ua)Override the default User-Agent

Per-request options (request-metadata headers)

OptionDescription
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

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 session
sessionID, err := client.Sessions.Start(ctx)
if err != nil {
log.Fatal(err)
}
userID := "user-123"
// 2. Approve consent
err = client.Consents.Approve(ctx, "consent-id", userID)
// 3. Document authentication
docFile, _ := os.Open("passport.jpg")
defer docFile.Close()
docResp, err := client.DocAuth.Check(ctx, biometry.DocAuthInput{
Document: docFile,
FileName: "passport.jpg",
SessionID: sessionID,
Provider: "inhouse",
})
if err != nil {
log.Fatal(err)
}
var docInfo biometry.DocAuthInfo
if 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 document
docPhoto, _ := os.Open("passport.jpg")
defer docPhoto.Close()
_, err = client.Enrollment.Face(ctx, biometry.EnrollFaceInput{
UserID: userID,
Face: docPhoto,
FileName: "passport.jpg",
IsDocument: true,
})
// 5. Liveness on the live video
videoFile, _ := os.Open("selfie.mp4")
defer videoFile.Close()
livenessResp, err := client.Verification.Liveness(ctx, biometry.LivenessInput{
UserID: userID,
Video: videoFile,
FileName: "selfie.mp4",
Phrase: "one two three four five",
SessionID: sessionID,
})
if err != nil {
log.Fatal(err)
}
if livenessResp.Decision != nil {
fmt.Printf("Decision: %s\n", livenessResp.Decision.Status)
}
// 6. Face match — document vs video (reuses the session video from step 5)
matchPhoto, _ := os.Open("passport.jpg")
defer matchPhoto.Close()
matchResp, err := client.FaceMatch.Match(ctx, biometry.FaceMatchInput{
UserID: userID,
ReferenceImage: matchPhoto,
ReferenceName: "passport.jpg",
UseSessionVideo: true,
SessionID: sessionID,
})
if matchResp.Decision != nil {
fmt.Printf("Match decision: %s\n", matchResp.Decision.Status)
}
// 7. End session
if err := client.Sessions.End(ctx, sessionID, nil); err != nil {
log.Printf("Failed to end session: %v", err)
}

Services Reference

Sessions

// Start a new session
sessionID, 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",
})

Verification (Liveness / Face / Voice)

The v1 Video.Process call is split into Verification.Liveness, Verification.FaceVerify, and Verification.VoiceVerify.

// Liveness (face liveness, active speaker, visual speech)
resp, err := client.Verification.Liveness(ctx, biometry.LivenessInput{
UserID: "user-123",
Video: videoReader, // io.Reader
FileName: "video.mp4",
Phrase: "one two three four five",
Vocabulary: "", // optional
Trigger: "", // optional
SessionID: sessionID, // optional
})
// resp.Decision (Status/Score/Reasons) available when a scoring system applies
// resp.Decode(&yourStruct) to parse the data field
// Verify against an enrolled template
resp, err = client.Verification.FaceVerify(ctx, biometry.VerifyInput{
UserID: "user-123", Media: videoReader, FileName: "video.mp4",
Phrase: "one two three four five", SessionID: sessionID,
})
// client.Verification.VoiceVerify(ctx, biometry.VerifyInput{...}) likewise

Enrollment

// Face enrollment
resp, err := client.Enrollment.Face(ctx, biometry.EnrollFaceInput{
UserID: "user-123",
Face: faceReader,
FileName: "photo.jpg",
IsDocument: false,
})
// Voice enrollment (single file + phrase)
resp, err := client.Enrollment.Voice(ctx, biometry.EnrollVoiceInput{
UserID: "user-123",
Voice: voiceReader,
FileName: "voice.wav",
Phrase: "one two three four five",
})

Face Match

// Standard — upload reference image and live video
resp, err := client.FaceMatch.Match(ctx, biometry.FaceMatchInput{
UserID: "user-123",
ReferenceImage: imageReader,
ReferenceName: "photo.jpg",
Video: videoReader,
VideoName: "video.mp4",
})
// Reuse the video captured earlier in the session
resp, err = client.FaceMatch.Match(ctx, biometry.FaceMatchInput{
UserID: "user-123",
ReferenceImage: imageReader,
ReferenceName: "photo.jpg",
UseSessionVideo: true,
SessionID: sessionID,
})

Document Authentication

resp, err := client.DocAuth.Check(ctx, biometry.DocAuthInput{
Document: docReader,
FileName: "passport.jpg",
SessionID: sessionID,
Provider: "inhouse", // or "idscan"
})
var info biometry.DocAuthInfo
resp.Decode(&info)
// info.FirstName, info.LastName, info.DocumentCategory, info.CountryCode, etc.

Transactions

// List with filters
txns, err := client.Transactions.List(ctx, biometry.TransactionListRequest{
Page: 1,
PageSize: 20,
Decision: "approved",
})
// Count
count, err := client.Transactions.Count(ctx, biometry.TransactionListRequest{
FromDate: "2025-01-01",
ToDate: "2025-12-31",
})
// Get by session
txns, err := client.Transactions.GetBySession(ctx, sessionID)
// Update tags
err := client.Transactions.UpdateTags(ctx, txnID, []string{"vip", "verified"})
// Flag as fraudulent
err := client.Transactions.Flag(ctx, txnID, "fraudulent")

API Keys

// Get current key info
info, err := client.APIKeys.Info(ctx)
// Mint a new key
newKey, err := client.APIKeys.Mint(ctx)
// Revoke a key
err := client.APIKeys.Revoke(ctx, "key-id-to-revoke")

Consents

// Approve a consent for a user
err := client.Consents.Approve(ctx, "consent-id", "user-123")
// List a user's consent approvals
approvals, err := client.Consents.MyApprovals(ctx, "user-123")

Deepfake / Anti-Video Forgery

// Submit a video for deepfake analysis
check, err := client.Deepfake.Submit(ctx, biometry.DeepfakeInput{
UserID: "user-123",
Video: videoReader,
FileName: "video.mp4",
})
// Poll the check status
status, err := client.Deepfake.Status(ctx, check.ID)
// status.Status: pending | processing | completed | failed

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 predicates
if biometry.IsNotFound(err) { ... }
if biometry.IsForbidden(err) { ... }
if biometry.IsUnauthorized(err) { ... }

Response Envelope

Verification, face-match, doc-auth, and enrollment endpoints return a *biometry.Response — the API v2 success envelope:

type Response struct {
Data json.RawMessage // the main result
Decision *Decision // scoring decision (nil when no scoring system applies)
Meta Meta // { RequestID, Message }
Header http.Header // raw HTTP response headers
}
type Decision struct {
Status string // "pass" | "fail" | "refer"
Score *float64
Reasons []string
}
// Decode the Data field into a typed struct:
var result MyStruct
resp.Decode(&result)

Response Headers

The *Response exposes the request ID (from the envelope meta, falling back to the header) and the raw Header field:

resp, err := client.Verification.Liveness(ctx, input)
fmt.Println("Request ID:", resp.RequestID()) // meta.request_id / X-Request-Id
// Raw header access for any other header
fmt.Println(resp.Header.Get("X-Custom-Header"))
AccessorSourceDescription
resp.RequestID()meta.request_id / X-Request-IdUnique request ID for tracking and support
resp.Meta.Messagemeta.messageHuman-readable status message
resp.DecisiondecisionScoring decision (Status/Score/Reasons), when a scoring system applies

DocAuth with MRZ validation

Select the MRZ extraction provider via MRZProvider on the input:

resp, err := client.DocAuth.Check(ctx, biometry.DocAuthInput{
Document: docFile,
FileName: "passport.jpg",
SessionID: sessionID,
Provider: "inhouse",
MRZProvider: "inhouse",
})
var info biometry.DocAuthInfo
resp.Decode(&info)
fmt.Println("Request ID:", resp.RequestID())