setu

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Apr 10, 2026 License: MIT Imports: 21 Imported by: 0

README

setu-client-go

Production-grade Go SDK for the Setu API Platform.
Go 1.25+ · Zero mandatory external deps (only x/time) · No lint issues


Products covered

Payments
Product Methods
UPI Flash — Dynamic QR CreateDQR, GetDQR
UPI Flash — Static QR CreateSQR, GetSQR
UPI Payment history GetLastPayment, GetPaymentHistory
UPI Collect (⚠️ NPCI deprecation pending) VerifyVPA, CreateCollect, GetCollect
UPI TPV (SEBI-mandated for capital markets) CreateTPV, GetTPV
UPI Mandates — Recurring CreateMandate (frequency: "monthly", etc.)
UPI Mandates — One-time CreateMandate (frequency: "one time")
UPI Mandates — SBMD CreateMandate (blockFunds: true, purpose: "76")
Mandate Operations UpdateMandate, RevokeMandate, GetMandateOperation
Pre-debit Notification PreDebitNotify, GetPreDebitNotification
Mandate Execution ExecuteMandate, GetMandateExecution
UPI Refunds CreateRefund, GetRefund
UPI Disputes GetDispute, AcceptDispute, RejectDispute
Merchant Onboarding (aggregator) CreateMerchant, GetMerchant, CheckVPAAvailability, CreateVPA
BBPS BillCollect Biller-side types + GetTransaction
BBPS BillPay FetchBill, PayBill
WhatsApp Collect SendReminder, GetReminderStatus
Data
Product Methods
Account Aggregator CreateConsent, GetConsent, RevokeConsent, CreateMultiConsent, GetLastFetchStatus, ListDataSessions, CreateDataSession, GetDataSession, FetchFIData
PAN Verification Verify
Bank Account Verification VerifySync, VerifyAsync, GetAsyncStatus
GSTIN Verification Verify
DigiLocker CreateSession, GetSession, GetDocument
Aadhaar eKYC Create, Get
Name Match Match (optimistic + pessimistic)
Aadhaar eSign Create, Get, Download
Webhooks (unified handler)

All event types from UPI, AA, and BBPS in one http.Handler:

  • payment.initiated/pending/success/failed
  • mandate.initiated/live/rejected/paused/revoked/updated
  • mandate_operation.create/update/revoke/execute/notify.*
  • refund.pending/successful
  • dispute_created/open/closed/in_review/won/lost
  • CONSENT_STATUS_UPDATE, SESSION_STATUS_UPDATE
  • BILL_SETTLEMENT_STATUS

Installation

go get github.com/iamkanishka/setu-client-go

Requires Go 1.25.0+.


Quick Start

package main

import (
    "context"
    "log"
    "github.com/iamkanishka/setu-client-go"
    "github.com/iamkanishka/setu-client-go/data/kyc/pan"
)

func main() {
    client, err := setu.New(
        setu.WithClientID("your-client-id"),
        setu.WithClientSecret("your-client-secret"),
        setu.WithEnvironment(setu.Sandbox),
        setu.WithProductInstanceID("your-product-instance-id"),
    )
    if err != nil { log.Fatal(err) }

    res, err := client.Data.KYC.PAN.Verify(context.Background(), &pan.VerifyRequest{
        PAN:     "ABCDE1234A",
        Consent: "Y",
        Reason:  "Customer identity verification during onboarding",
    })
    if err != nil { log.Fatal(err) }
    log.Printf("valid=%v name=%q", res.IsValid(), res.Data.FullName)
}

Configuration

client, err := setu.New(
    // Required
    setu.WithClientID("..."),
    setu.WithClientSecret("..."),
    // Recommended
    setu.WithProductInstanceID("..."),      // For KYC / AA APIs
    setu.WithEnvironment(setu.Production),  // Default: Sandbox
    // Tuning
    setu.WithTimeout(30 * time.Second),     // Default: 30s
    setu.WithMaxAttempts(4),                // 1 + 3 retries
    setu.WithRetryWait(500*time.Millisecond, 10*time.Second),
    setu.WithRateLimit(100, 20),            // 100 RPS, burst 20
    // Advanced
    setu.WithHTTPTransport(myTransport),
    setu.WithUserAgent("my-app/1.0"),
)

UPI Flash — Dynamic & Static QR

// Dynamic QR (single-use, amount fixed or flexible)
dqr, _ := client.Payments.UPI.CreateDQR(ctx, merchantID, &upi.CreateDQRRequest{
    Amount:      10000,   // ₹100 in paise
    MerchantVPA: "merchant@pineaxis",
    ReferenceID: "ORDER-001",
})
// dqr.IntentLink → render as QR code image

// Static QR (permanent, multi-use, for in-store display)
sqr, _ := client.Payments.UPI.CreateSQR(ctx, merchantID, &upi.CreateSQRRequest{
    MerchantVPA: "shop@pineaxis",
    ReferenceID: "STORE-001",
})

// Check last payment on any link
payment, _ := client.Payments.UPI.GetLastPayment(ctx, merchantID, dqr.ID)
history, _ := client.Payments.UPI.GetPaymentHistory(ctx, merchantID, sqr.ID)

UPI TPV (SEBI-mandated for capital markets)

tpv, _ := client.Payments.UPI.CreateTPV(ctx, merchantID, &upi.CreateTPVRequest{
    Amount:      50000,       // ₹500
    MerchantVPA: "mf@pineaxis",
    CustomerAccount: upi.CustomerAccount{
        IFSC:          "HDFC0001234",
        AccountNumber: "9876543210",
    },
    ReferenceID: "MF-INV-001",
})
// Payment is accepted only from the registered account

UPI Mandates

// Recurring mandate
mandate, _ := client.Payments.UPI.CreateMandate(ctx, merchantID, &upi.CreateMandateRequest{
    Frequency: "monthly", Purpose: "14", BlockFunds: false,
    AllowMultipleDebit: false, /* … */
})

// One-time mandate (e.g. IPO reservation)
mandate, _ := client.Payments.UPI.CreateMandate(ctx, merchantID, &upi.CreateMandateRequest{
    Frequency: "one time", RecurrenceValue: 0, /* … */
})

// Single Block Multi-Debit (cash-on-delivery / try-and-buy)
mandate, _ := client.Payments.UPI.CreateMandate(ctx, merchantID, &upi.CreateMandateRequest{
    Frequency: "as presented", Purpose: "76",
    BlockFunds: true, AllowMultipleDebit: true, /* … */
})

// Pre-debit notification (required 48–72h before execution)
notif, _ := client.Payments.UPI.PreDebitNotify(ctx, merchantID, mandateID, &upi.PreDebitNotifyRequest{
    Amount: 1000, ExecutionDate: "15042025", UMN: mandate.UMN,
    SequenceNumber: 1, MerchantReferenceID: "EXEC-001",
})

// Execute after notification succeeds
exec, _ := client.Payments.UPI.ExecuteMandate(ctx, merchantID, mandateID, &upi.ExecuteMandateRequest{
    Amount: 1000, UMN: mandate.UMN,
    SequenceNumber: 1, MerchantReferenceID: "EXEC-001",
})

// Update / Revoke
client.Payments.UPI.UpdateMandate(ctx, merchantID, mandateID, &upi.UpdateMandateRequest{
    AmountLimit: 2000, EndDate: "01012028",
})
client.Payments.UPI.RevokeMandate(ctx, merchantID, mandateID, &upi.RevokeMandateRequest{
    MerchantReferenceID: "REVOKE-001",
})

Disputes

dispute, _ := client.Payments.UPI.GetDispute(ctx, merchantID, disputeID)

// Accept → automatic refund
client.Payments.UPI.AcceptDispute(ctx, merchantID, disputeID)

// Reject → provide evidence to NPCI
client.Payments.UPI.RejectDispute(ctx, merchantID, disputeID, &upi.RejectDisputeRequest{
    Evidence:     base64PDF,
    EvidenceType: "invoice",
    Remarks:      "Service rendered as agreed",
})

Account Aggregator

// Create consent (redirect customer to consent.URL)
consent, _ := client.Data.AA.CreateConsent(ctx, &aa.CreateConsentRequest{
    VUA: "9999999999",
    FetchType: aa.FetchTypePeriodic,
    ConsentDuration: &aa.Duration{Unit: aa.DurationUnitMonth, Value: 4},
    ConsentMode: aa.ConsentModeStore,
    ConsentTypes: []aa.ConsentType{aa.ConsentTypeTransactions, aa.ConsentTypeProfile},
    FITypes: []aa.FIType{aa.FITypeDeposit, aa.FITypeMutualFunds},
    Purpose: aa.PurposeLoanUnderwriting,
    DataRange: &aa.DateRange{From: from, To: to},
    DataLife: &aa.Duration{Unit: aa.DurationUnitMonth, Value: 1},
    Frequency: &aa.Frequency{Unit: aa.FrequencyUnitMonthly, Value: 1},
    RedirectURL: "https://yourapp.com/callback",
    Context: []aa.ContextParam{
        aa.WithAccountType("SAVINGS"),
        aa.WithAccountSelectionMode("multi"),
    },
    Tags: []string{"loan_q2"},
})

// After consent is ACTIVE, create data session
session, _ := client.Data.AA.CreateDataSession(ctx, &aa.CreateDataSessionRequest{
    ConsentID: consent.ID,
    Format:    aa.DataFormatJSON,
})

// After session is COMPLETED, fetch FI data
data, _ := client.Data.AA.FetchFIData(ctx, session.ID)

Webhook Handler

h := webhook.NewHandler(webhook.Config{
    OnPaymentUpdate: func(n *webhook.PaymentNotification) {
        log.Printf("payment %s → %s (type: %s)", n.ID, n.Status, n.ProductInstanceType)
    },
    OnMandateUpdate: func(n *webhook.MandateNotification) {
        log.Printf("mandate event: %s", n.EventType)
    },
    OnRefundUpdate: func(n *webhook.RefundNotification) {
        log.Printf("refund %s → %s", n.Data.ID, n.Data.Status)
    },
    OnDisputeUpdate: func(n *webhook.DisputeNotification) {
        log.Printf("dispute %s → %s", n.Data.ID, n.Data.Status)
    },
    OnConsentUpdate: func(n *aa.ConsentNotification) {
        log.Printf("consent %s → %s", n.ConsentID, n.Data.Status)
        if n.Data.Status == aa.ConsentStatusActive {
            // start data session
        }
    },
    OnSessionUpdate: func(n *aa.SessionNotification) {
        if n.Data.Status == aa.SessionStatusCompleted {
            // fetch FI data
        }
    },
    OnBBPSSettlement: func(n *bbps.SettlementNotification) {
        log.Printf("BBPS settlement: %d events", len(n.Events))
    },
})
http.Handle("/webhooks/setu", h)

Error Handling

result, err := client.Data.KYC.PAN.Verify(ctx, req)
if err != nil {
    if setuerrors.IsNotFound(err)     { /* PAN not in NSDL */ }
    if setuerrors.IsRateLimit(err)    { /* back off */ }
    if setuerrors.IsUnauthorized(err) { /* check credentials */ }

    traceID := setuerrors.GetTraceID(err) // for Setu support ticket

    var setuErr setuerrors.Error
    if errors.As(err, &setuErr) {
        log.Printf("status=%d code=%q retryable=%v trace=%s",
            setuErr.HTTPStatus(), setuErr.Code(),
            setuErr.Retryable(), setuErr.TraceID())
    }
}

Environments

Constant Notes
setu.Sandbox Default. No real money. Sandbox credentials only.
setu.Production Real transactions. Production credentials required.

Credentials are environment-specific — never swap sandbox and production keys.


Project Structure

setu-client-go/
├── setu.go                          Root client: New(), Client, sub-client wiring
├── options.go                       WithClientID, WithEnvironment, WithRateLimit, …
├── go.mod                           module github.com/iamkanishka/setu-client-go · go 1.25
│
├── internal/
│   ├── auth/tokenmanager.go         Token cache, auto-refresh, singleflight dedup
│   ├── transport/client.go          HTTP: retry, rate-limit, body replay, error decode
│   ├── retry/retry.go               Exponential backoff + full-jitter (math/rand/v2)
│   └── ratelimit/ratelimit.go       Token-bucket (x/time/rate)
│
├── pkg/
│   ├── setuerrors/errors.go         APIError, AuthError, RateLimitError, NetworkError, ValidationError
│   └── types/types.go               Currency, Environment, FailureReason, DateRange
│
├── payments/
│   ├── upi/client.go                Flash/DQR/SQR, Collect, TPV, Mandates (3 types),
│   │                                Mandate ops, Pre-debit, Execution, Refunds, Disputes,
│   │                                Merchant onboarding
│   ├── bbps/client.go               BillCollect: biller types, settlement, transaction lookup
│   ├── billpay/client.go            BillPay agent: FetchBill, PayBill
│   └── whatsapp/client.go           SendReminder, GetReminderStatus
│
├── data/
│   ├── aa/client.go                 AA FIU: full consent + data session flows
│   │                                + AA webhook notification types
│   ├── esign/client.go              Aadhaar eSign: Create, Get, Download
│   └── kyc/
│       ├── pan/client.go            PAN verify (NSDL)
│       ├── bav/client.go            Bank account verify (sync + async)
│       ├── gst/client.go            GSTIN verify
│       ├── digilocker/client.go     DigiLocker: session + document fetch
│       ├── ekyc/client.go           Aadhaar eKYC
│       └── namematch/client.go      Name match (optimistic + pessimistic)
│
├── webhook/handler.go               Unified dispatcher (UPI + AA + BBPS)
└── examples/main.go                 Full runnable demo

License

MIT © 2026 Kanishka Naik

Documentation

Overview

Package setu is the root of the Setu Go SDK.

Products covered

  • UPI Setu (UMAP): Flash/DQR/SQR payment links, Collect (VPA-push), TPV (Third Party Validation), Refunds, Disputes, UPI Mandates (Recurring, One-time, Single Block Multi-Debit), Mandate operations (Update, Revoke, Pause, Unpause), Merchant onboarding for aggregators.
  • BBPS BillCollect: biller-side bill-fetch/receipt APIs, settlement.
  • BBPS BillPay: agent-side bill-fetch and bill-payment.
  • WhatsApp Collect: send payment reminders via WhatsApp.
  • Account Aggregator: full FIU consent + data-fetch flow, multi-consent, revoke, last fetch status, data session management.
  • PAN Verification (NSDL).
  • Bank Account Verification — penny drop, sync and async.
  • GST / GSTIN Verification.
  • DigiLocker — consent session + document fetch.
  • Aadhaar eKYC.
  • Name Match — optimistic and pessimistic scoring.
  • Aadhaar eSign — create, get, download signed PDF.

Quick start

client, err := setu.New(
    setu.WithClientID("your-client-id"),
    setu.WithClientSecret("your-client-secret"),
    setu.WithEnvironment(setu.Sandbox),
)

Error handling

All errors implement setuerrors.Error and are compatible with errors.As. Use setuerrors.IsNotFound, setuerrors.IsRateLimit, setuerrors.GetTraceID, etc.

Index

Constants

View Source
const (
	Sandbox    = types.Sandbox
	Production = types.Production
)

Environment aliases — re-exported for convenience.

View Source
const SDKVersion = "1.0.2"

SDKVersion is the current semantic version of this SDK.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// Payments exposes all payments-product clients.
	Payments *PaymentsClient
	// Data exposes all data-product clients.
	Data *DataClient
	// contains filtered or unexported fields
}

Client is the root Setu SDK client. Construct with New. All sub-clients share the underlying transport, rate limiter, and token manager.

func New

func New(opts ...Option) (*Client, error)

New constructs a *Client using the provided options.

Required: WithClientID, WithClientSecret.

client, err := setu.New(
    setu.WithClientID("your-id"),
    setu.WithClientSecret("your-secret"),
    setu.WithEnvironment(setu.Production),
    setu.WithProductInstanceID("your-pid"), // for KYC / AA
)

func (*Client) Environment

func (c *Client) Environment() types.Environment

Environment returns the environment the client targets.

type DataClient

type DataClient struct {
	// AA is the Account Aggregator FIU client.
	AA *aa.Client
	// KYC groups all identity verification clients.
	KYC *KYCClient
	// ESign is the Aadhaar eSign client.
	ESign *esign.Client
}

DataClient groups all data-product sub-clients.

type KYCClient

type KYCClient struct {
	PAN        *pan.Client
	BAV        *bav.Client
	GST        *gst.Client
	DigiLocker *digilocker.Client
	EKYC       *ekyc.Client
	NameMatch  *namematch.Client
}

KYCClient groups identity and verification sub-clients.

type Option

type Option func(*config)

Option is a functional option for configuring a Client.

func WithClientID

func WithClientID(id string) Option

WithClientID sets the Setu API client ID. Required.

func WithClientSecret

func WithClientSecret(secret string) Option

WithClientSecret sets the Setu API client secret. Required.

func WithEnvironment

func WithEnvironment(env types.Environment) Option

WithEnvironment selects types.Sandbox or types.Production. Defaults to types.Sandbox.

func WithHTTPTransport

func WithHTTPTransport(t http.RoundTripper) Option

WithHTTPTransport replaces the default HTTP transport. Useful for custom TLS, proxies, or test mocks.

func WithMaxAttempts

func WithMaxAttempts(n int) Option

WithMaxAttempts sets the total attempt count (1 = no retries). Default: 4.

func WithProductInstanceID

func WithProductInstanceID(id string) Option

WithProductInstanceID sets the x-product-instance-id header used by KYC and Account Aggregator APIs.

func WithRateLimit

func WithRateLimit(rps float64, burst int) Option

WithRateLimit configures the client-side token-bucket rate limiter. rps = sustained requests/second; burst = maximum burst capacity. Default: 100 RPS, burst 20.

func WithRetryWait

func WithRetryWait(base, max time.Duration) Option

WithRetryWait sets the base and maximum backoff duration. Default: 500ms / 10s.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the per-request HTTP timeout. Default: 30s.

func WithUserAgent

func WithUserAgent(ua string) Option

WithUserAgent overrides the SDK User-Agent header.

type PaymentsClient

type PaymentsClient struct {
	// UPI covers Flash/DQR/SQR, Collect, TPV, Mandates, Refunds, Disputes.
	UPI *upi.Client
	// BBPS covers BillCollect biller-side APIs.
	BBPS *bbps.Client
	// BillPay covers BBPS agent-side bill-payment APIs.
	BillPay *billpay.Client
	// WhatsApp covers WhatsApp Collect reminder APIs.
	WhatsApp *whatsapp.Client
}

PaymentsClient groups all payments-product sub-clients.

Directories

Path Synopsis
data
aa
Package aa provides the Setu Account Aggregator FIU API client.
Package aa provides the Setu Account Aggregator FIU API client.
esign
Package esign provides the Setu Aadhaar eSign API client.
Package esign provides the Setu Aadhaar eSign API client.
kyc/bav
Package bav provides the Setu Bank Account Verification (BAV / penny-drop) client.
Package bav provides the Setu Bank Account Verification (BAV / penny-drop) client.
kyc/digilocker
Package digilocker provides the Setu DigiLocker API client.
Package digilocker provides the Setu DigiLocker API client.
kyc/ekyc
Package ekyc provides the Setu Aadhaar eKYC API client.
Package ekyc provides the Setu Aadhaar eKYC API client.
kyc/gst
Package gst provides the Setu GSTIN Verification API client.
Package gst provides the Setu GSTIN Verification API client.
kyc/namematch
Package namematch provides the Setu Name Match API client.
Package namematch provides the Setu Name Match API client.
kyc/pan
Package pan provides the Setu PAN Verification API client.
Package pan provides the Setu PAN Verification API client.
Package main demonstrates the complete Setu Go SDK.
Package main demonstrates the complete Setu Go SDK.
internal
auth
Package auth manages Setu UPI/BBPS access-token lifecycle.
Package auth manages Setu UPI/BBPS access-token lifecycle.
ratelimit
Package ratelimit provides a client-side token-bucket rate limiter backed by golang.org/x/time/rate.
Package ratelimit provides a client-side token-bucket rate limiter backed by golang.org/x/time/rate.
retry
Package retry implements exponential backoff with full jitter.
Package retry implements exponential backoff with full jitter.
transport
Package transport provides the shared HTTP client for all Setu SDK sub-clients.
Package transport provides the shared HTTP client for all Setu SDK sub-clients.
payments
bbps
Package bbps provides the Setu BBPS BillCollect client.
Package bbps provides the Setu BBPS BillCollect client.
billpay
Package billpay provides the Setu BBPS BillPay (agent) client.
Package billpay provides the Setu BBPS BillPay (agent) client.
upi
Package upi provides the Setu UPI Setu (UMAP) API client.
Package upi provides the Setu UPI Setu (UMAP) API client.
whatsapp
Package whatsapp provides the Setu WhatsApp Collect client.
Package whatsapp provides the Setu WhatsApp Collect client.
pkg
setuerrors
Package setuerrors defines all structured error types for the Setu SDK.
Package setuerrors defines all structured error types for the Setu SDK.
types
Package types defines shared domain types used across the Setu SDK.
Package types defines shared domain types used across the Setu SDK.
Package webhook provides a unified http.Handler that dispatches all Setu webhook notifications (UPI Setu payments, mandates, refunds, disputes, Account Aggregator, and BBPS settlement) to typed callback functions.
Package webhook provides a unified http.Handler that dispatches all Setu webhook notifications (UPI Setu payments, mandates, refunds, disputes, Account Aggregator, and BBPS settlement) to typed callback functions.

Jump to

Keyboard shortcuts

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