gosumsub

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2026 License: MIT Imports: 21 Imported by: 0

README

gosumsub

gosumsub is a lightweight and idiomatic Go SDK for integrating with the Sumsub API.

It is designed for simplicity, correctness, and ease of integration in production systems.

Go Version License

Features

  • Simple & Idiomatic API Clean, readable interfaces that follow Go best practices.

  • Built-in Request Signing Secure HMAC-SHA256 request signing handled internally.

  • Context Support Full support for context.Context for cancellation and timeouts.

  • Zero External Dependencies Uses only the Go standard library.

Installation

go get github.com/andyle182810/gosumsub

Quick Start

client, err := gosumsub.NewClient(
    "https://api.sumsub.com",
    appToken,
    secretKey,
    gosumsub.WithDebug(true),
)
if err != nil {
    log.Fatal(err)
}

// Check API health
err = client.GetAPIHealthStatus(context.Background())
if err != nil {
    log.Fatal(err)
}

// Generate Web SDK link for KYC verification
resp, err := client.GenerateExternalWebSDKLink(
    context.Background(),
    &gosumsub.GenerateExternalWebSDKLinkRequest{
        LevelName: "basic-kyc-level",
        UserID:    "user-123",
        TTLInSecs: 3600,
        ApplicantIdentifiers: &gosumsub.ApplicantIdentifiers{
            Email: "[email protected]",
        },
    },
)
if err != nil {
    log.Fatal(err)
}

fmt.Println("Web SDK URL:", resp.URL)

Testing

Integration tests automatically skip when required credentials are missing.

Required environment variables:

SUMSUB_LEVEL_NAME=idv-and-phone-verification
SUMSUB_APP_TOKEN=your_app_token
SUMSUB_API_SECRET=your_api_secret
SUMSUB_WEBHOOK_SECRET=your_webhook_secret
SUMSUB_TEST_APPLICANT_ID=your_test_applicant_id
SUMSUB_TEST_INSPECTION_ID=your_test_inspection_id
SUMSUB_TEST_IMAGE_ID=your_test_image_id

Run tests:

go test ./...

Support

For bugs, questions, or feature requests:

License

gosumsub is licensed under the MIT License. See the LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	HeaderDigestAlg = "X-Payload-Digest-Alg"
	HeaderDigest    = "X-Payload-Digest"
)
View Source
const (
	AlgoHMACSHA1   = "HMAC_SHA1_HEX"
	AlgoHMACSHA256 = "HMAC_SHA256_HEX"
	AlgoHMACSHA512 = "HMAC_SHA512_HEX"
)
View Source
const (
	WebhookTypeApplicantReviewed            = "applicantReviewed"
	WebhookTypeApplicantPending             = "applicantPending"
	WebhookTypeApplicantCreated             = "applicantCreated"
	WebhookTypeApplicantOnHold              = "applicantOnHold"
	WebhookTypeApplicantPersonalInfoChanged = "applicantPersonalInfoChanged"
	WebhookTypeApplicantPrechecked          = "applicantPrechecked"
	WebhookTypeApplicantDeleted             = "applicantDeleted"
	WebhookTypeApplicantLevelChanged        = "applicantLevelChanged"
	WebhookTypeApplicantReset               = "applicantReset"
	WebhookTypeApplicantActionPending       = "applicantActionPending"
	WebhookTypeApplicantActionReviewed      = "applicantActionReviewed"
	WebhookTypeApplicantActionOnHold        = "applicantActionOnHold"
	WebhookTypeApplicantWorkflowCompleted   = "applicantWorkflowCompleted"
	WebhookTypeVideoIdentStatusChanged      = "videoIdentStatusChanged"
)
View Source
const (
	ReviewAnswerGreen = "GREEN"
	ReviewAnswerRed   = "RED"
)
View Source
const UserAgent = "sumsub-go-sdk"

Variables

View Source
var (
	// Client initialization errors.
	ErrEmptyBaseURL = errors.New("base URL cannot be empty")
	ErrEmptyToken   = errors.New("token cannot be empty")
	ErrEmptySecret  = errors.New("secret cannot be empty")

	// Request lifecycle errors.
	ErrNilRequest    = errors.New("request is nil")
	ErrRequestEncode = errors.New("failed to encode request body")
	ErrRequestSign   = errors.New("failed to sign request")

	// HTTP / transport errors.
	ErrHTTPFailure      = errors.New("http request failed")
	ErrUnexpectedStatus = errors.New("unexpected http status code")
)
View Source
var (
	ErrTooManyQueryParams = errors.New("allowedQueryParams exceeds maximum of 4")
	ErrLevelNameRequired  = errors.New("levelName is required")
)
View Source
var (
	ErrInspectionIDRequired = errors.New("inspectionId is required")
	ErrImageIDRequired      = errors.New("imageId is required")
)
View Source
var (
	ErrEmptyDigest       = errors.New("empty digest")
	ErrEmptySecretKey    = errors.New("empty secret key")
	ErrMalformedDigest   = errors.New("malformed digest")
	ErrDigestMismatch    = errors.New("digest mismatch")
	ErrUnsupportedAlgo   = errors.New("unsupported algorithm")
	ErrEmptyPayload      = errors.New("empty payload")
	ErrMissingDigestAlgo = errors.New("missing digest algorithm header")
	ErrMissingDigest     = errors.New("missing digest header")
	ErrHMACWrite         = errors.New("failed to write payload to hmac")
)
View Source
var ErrApplicantIDRequired = errors.New("applicantId is required")

Functions

func EchoWebhookMiddleware

func EchoWebhookMiddleware(secretKey string) func(next echo.HandlerFunc) echo.HandlerFunc

func VerifyWebhookDigest

func VerifyWebhookDigest(payload []byte, secretKey, algo, digestHex string) error

func VerifyWebhookRequest

func VerifyWebhookRequest(request *http.Request, secretKey string) error

func VerifyWebhookRequestWithBody

func VerifyWebhookRequestWithBody(request *http.Request, secretKey string) ([]byte, error)

func WebhookMiddleware

func WebhookMiddleware(secretKey string) func(http.Handler) http.Handler

Types

type APIError

type APIError struct {
	Description   string `json:"description"`
	Code          int    `json:"code"`
	CorrelationID string `json:"correlationId"`
	ErrorCode     int    `json:"errorCode"`
	ErrorName     string `json:"errorName"`
}

func (*APIError) Error

func (e *APIError) Error() string

type Address

type Address struct {
	SubStreet        string `json:"subStreet,omitempty"`
	SubStreetEn      string `json:"subStreetEn,omitempty"`
	Street           string `json:"street,omitempty"`
	StreetEn         string `json:"streetEn,omitempty"`
	State            string `json:"state,omitempty"`
	StateEn          string `json:"stateEn,omitempty"`
	Town             string `json:"town,omitempty"`
	TownEn           string `json:"townEn,omitempty"`
	PostCode         string `json:"postCode,omitempty"`
	FormattedAddress string `json:"formattedAddress,omitempty"`
}

type Agreement

type Agreement struct {
	Items      []AgreementItem `json:"items,omitempty"`
	CreatedAt  string          `json:"createdAt,omitempty"`
	AcceptedAt string          `json:"acceptedAt,omitempty"`
	Source     string          `json:"source,omitempty"`
	RecordIDs  []string        `json:"recordIds,omitempty"`
}

type AgreementItem

type AgreementItem struct {
	ID         string   `json:"id,omitempty"`
	AcceptedAt string   `json:"acceptedAt,omitempty"`
	Source     string   `json:"source,omitempty"`
	Type       string   `json:"type,omitempty"`
	RecordIDs  []string `json:"recordIds,omitempty"`
}

type ApplicantData

type ApplicantData struct {
	ID                string          `json:"id,omitempty"`
	CreatedAt         string          `json:"createdAt,omitempty"`
	Key               string          `json:"key,omitempty"`
	ClientID          string          `json:"clientId,omitempty"`
	InspectionID      string          `json:"inspectionId,omitempty"`
	ExternalUserID    string          `json:"externalUserId,omitempty"`
	Info              *ApplicantInfo  `json:"info,omitempty"`
	FixedInfo         *FixedInfo      `json:"fixedInfo,omitempty"`
	Email             string          `json:"email,omitempty"`
	Phone             string          `json:"phone,omitempty"`
	PhoneCountry      string          `json:"phoneCountry,omitempty"`
	ApplicantPlatform string          `json:"applicantPlatform,omitempty"`
	Agreement         *Agreement      `json:"agreement,omitempty"`
	RequiredIDDocs    *RequiredIDDocs `json:"requiredIdDocs,omitempty"`
	Review            *Review         `json:"review,omitempty"`
	Lang              string          `json:"lang,omitempty"`
	Type              string          `json:"type,omitempty"`
	Notes             []string        `json:"notes,omitempty"`
}

type ApplicantIdentifiers

type ApplicantIdentifiers struct {
	Email string `json:"email,omitempty"`
	Phone string `json:"phone,omitempty"`
}

type ApplicantInfo

type ApplicantInfo struct {
	FirstName   string  `json:"firstName,omitempty"`
	FirstNameEn string  `json:"firstNameEn,omitempty"`
	LastName    string  `json:"lastName,omitempty"`
	LastNameEn  string  `json:"lastNameEn,omitempty"`
	Dob         string  `json:"dob,omitempty"`
	Country     string  `json:"country,omitempty"`
	IDDocs      []IDDoc `json:"idDocs,omitempty"`
}

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(baseURL, token, secret string, opts ...Option) (*Client, error)

func (*Client) GetAPIHealthStatus

func (c *Client) GetAPIHealthStatus(ctx context.Context) error

func (*Client) GetApplicantData

func (c *Client) GetApplicantData(ctx context.Context, applicantID string) (*ApplicantData, error)

func (*Client) GetDocumentImage

func (c *Client) GetDocumentImage(ctx context.Context, inspectionID, imageID string) (*GetDocumentImageResponse, error)

func (*Client) GetInformationDocumentImages

func (c *Client) GetInformationDocumentImages(ctx context.Context, applicantID string) (*DocumentImagesResponse, error)

type ClockFunc

type ClockFunc func() time.Time

type DocSet

type DocSet struct {
	IDDocSetType            string                   `json:"idDocSetType,omitempty"`
	Types                   []string                 `json:"types,omitempty"`
	VideoRequired           string                   `json:"videoRequired,omitempty"`
	CaptureMode             string                   `json:"captureMode,omitempty"`
	UploaderMode            string                   `json:"uploaderMode,omitempty"`
	NfcVerificationSettings *NfcVerificationSettings `json:"nfcVerificationSettings,omitempty"`
	Fields                  []DocSetField            `json:"fields,omitempty"`
}

type DocSetField

type DocSetField struct {
	Name               string `json:"name,omitempty"`
	Required           bool   `json:"required,omitempty"`
	Prefill            any    `json:"prefill,omitempty"`
	ImmutableIfPresent bool   `json:"immutableIfPresent,omitempty"`
}

type DocumentImageItem

type DocumentImageItem struct {
	ID           string        `json:"id,omitempty"`
	PreviewID    string        `json:"previewId,omitempty"`
	AddedDate    string        `json:"addedDate,omitempty"`
	FileMetadata *FileMetadata `json:"fileMetadata,omitempty"`
	IDDocDef     *IDDocDef     `json:"idDocDef,omitempty"`
	ReviewResult *ReviewResult `json:"reviewResult,omitempty"`
	Deactivated  bool          `json:"deactivated,omitempty"`
	AttemptID    string        `json:"attemptId,omitempty"`
	Source       string        `json:"source,omitempty"`
}

type DocumentImagesResponse

type DocumentImagesResponse struct {
	Items      []DocumentImageItem `json:"items,omitempty"`
	TotalItems int                 `json:"totalItems,omitempty"`
}

type FileMetadata

type FileMetadata struct {
	FileName   string      `json:"fileName,omitempty"`
	FileType   string      `json:"fileType,omitempty"`
	FileSize   int         `json:"fileSize,omitempty"`
	Resolution *Resolution `json:"resolution,omitempty"`
}

type FixedInfo

type FixedInfo struct {
	Gender      string    `json:"gender,omitempty"`
	Nationality string    `json:"nationality,omitempty"`
	Addresses   []Address `json:"addresses,omitempty"`
}

type GenerateExternalWebSDKLinkRequest

type GenerateExternalWebSDKLinkRequest struct {
	TTLInSecs            int64                 `json:"ttlInSecs,omitempty"`
	UserID               string                `json:"userId,omitempty"`
	LevelName            string                `json:"levelName"`
	ApplicantIdentifiers *ApplicantIdentifiers `json:"applicantIdentifiers,omitempty"`
	Redirect             *Redirect             `json:"redirect,omitempty"`
}

type GenerateExternalWebSDKLinkResponse

type GenerateExternalWebSDKLinkResponse struct {
	URL string `json:"url"`
}

type GetDocumentImageResponse

type GetDocumentImageResponse struct {
	Data     []byte `json:"data"`
	MimeType string `json:"mimeType"`
}

func (*GetDocumentImageResponse) GetBase64WithMime

func (r *GetDocumentImageResponse) GetBase64WithMime() string

type HTTPClient

type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

type IDDoc

type IDDoc struct {
	IDDocType   string `json:"idDocType,omitempty"`
	Country     string `json:"country,omitempty"`
	FirstName   string `json:"firstName,omitempty"`
	FirstNameEn string `json:"firstNameEn,omitempty"`
	LastName    string `json:"lastName,omitempty"`
	LastNameEn  string `json:"lastNameEn,omitempty"`
	IssuedDate  string `json:"issuedDate,omitempty"`
	ValidUntil  string `json:"validUntil,omitempty"`
	Number      string `json:"number,omitempty"`
	Dob         string `json:"dob,omitempty"`
	MrzLine1    string `json:"mrzLine1,omitempty"`
	MrzLine2    string `json:"mrzLine2,omitempty"`
	MrzLine3    string `json:"mrzLine3,omitempty"`
	Termless    bool   `json:"termless,omitempty"`
}

type IDDocDef

type IDDocDef struct {
	Country      string `json:"country,omitempty"`
	IDDocType    string `json:"idDocType,omitempty"`
	IDDocSubType string `json:"idDocSubType,omitempty"`
}

type Logger

type Logger interface {
	Info(msg string, args ...any)
	Error(msg string, args ...any)
	Debug(msg string, args ...any)
}

type NfcVerificationSettings

type NfcVerificationSettings struct {
	Mode string `json:"mode,omitempty"`
}

type Option

type Option func(*Client)

func WithClock

func WithClock(clock ClockFunc) Option

func WithDebug

func WithDebug(debug bool) Option

func WithHTTPClient

func WithHTTPClient(httpClient HTTPClient) Option

func WithLogger

func WithLogger(logger Logger) Option

func WithSigner

func WithSigner(signer Signer) Option

type Redirect

type Redirect struct {
	AllowedQueryParams []string `json:"allowedQueryParams,omitempty"`
	SuccessURL         string   `json:"successUrl,omitempty"`
	RejectURL          string   `json:"rejectUrl,omitempty"`
	SignKey            string   `json:"signKey,omitempty"`
}

type RequiredIDDocs

type RequiredIDDocs struct {
	DocSets []DocSet `json:"docSets,omitempty"`
}

type Resolution

type Resolution struct {
	Width  int `json:"width,omitempty"`
	Height int `json:"height,omitempty"`
}

type Review

type Review struct {
	ReviewID              string        `json:"reviewId,omitempty"`
	AttemptID             string        `json:"attemptId,omitempty"`
	AttemptCnt            int           `json:"attemptCnt,omitempty"`
	ElapsedSincePendingMs int64         `json:"elapsedSincePendingMs,omitempty"`
	ElapsedSinceQueuedMs  int64         `json:"elapsedSinceQueuedMs,omitempty"`
	Reprocessing          bool          `json:"reprocessing,omitempty"`
	LevelName             string        `json:"levelName,omitempty"`
	LevelAutoCheckMode    any           `json:"levelAutoCheckMode,omitempty"`
	CreateDate            string        `json:"createDate,omitempty"`
	ReviewDate            string        `json:"reviewDate,omitempty"`
	ReviewResult          *ReviewResult `json:"reviewResult,omitempty"`
	ReviewStatus          string        `json:"reviewStatus,omitempty"`
	Priority              int           `json:"priority,omitempty"`
}

type ReviewResult

type ReviewResult struct {
	ReviewAnswer string `json:"reviewAnswer,omitempty"`
}

type Signer

type Signer interface {
	Sign(timestamp time.Time, method, uri string, payload *[]byte) (string, error)
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL