Error handling
Every method returns (result, error) where error is nil or a
*ekyc.Error. Use errors.As to extract:
result, err := client.Liveness.Check(ctx, req)
if err != nil {
var ekycErr *ekyc.Error
if errors.As(err, &ekycErr) {
switch ekycErr.Code {
case ekyc.ErrCodeRateLimited:
time.Sleep(ekycErr.RetryAfter)
case ekyc.ErrCodeInvalidCredentials:
log.Fatal("API key revoked or wrong; check config")
}
}
return err
}
Error fields
type Error struct {
Code string // wire `error.type`
StatusCode int // HTTP status
Message string
RequestID string // surface in support tickets
Param string // for validation_failed
DocURL string // populated from `error.doc_url`
RetryAfter time.Duration // for rate_limited
// unexported `cause error` accessible via errors.Unwrap
}
Sentinel constants
ekyc.ErrCode* exposes the strings:
ekyc.ErrCodeTokenExpired
ekyc.ErrCodeInvalidToken
ekyc.ErrCodeInvalidCredentials
ekyc.ErrCodeRateLimited
ekyc.ErrCodeValidationFailed
ekyc.ErrCodePaymentRequired
ekyc.ErrCodePayloadTooLarge
ekyc.ErrCodeNotFound
ekyc.ErrCodeInternalError
ekyc.ErrCodeNetworkError
See Errors and retries for the full taxonomy.
Network errors
Transport-level failures (DNS, connection refused, timeout) surface
as Code == ErrCodeNetworkError. The SDK retries them automatically
(up to 3 attempts with exponential backoff) before returning. If you
see network_error, you've already exhausted the retry budget.
var ekycErr *ekyc.Error
if errors.As(err, &ekycErr) && ekycErr.Code == ekyc.ErrCodeNetworkError {
if cause := errors.Unwrap(err); cause != nil {
log.Printf("network failure: %v", cause)
}
}
What 401 means in Go
The Go SDK does NOT auto-refresh on 401 (unlike Flutter). Reasons:
- The
dv_sk_*is your credential. If it's wrong, retrying with the same key won't help. - Your server controls the key lifecycle; the SDK has nothing to refresh against.
If you see 401 invalid_credentials, the right answer is "fix your
config", not "retry".