Seev Business API

Go SDK

Integrate Seev payments into your Go application. Build checkouts, handle callbacks, process webhooks, and manage transactions with the seevpay package.

The Seev Go SDK (seevcashplus/pkg/seevpay) provides a type-safe, idiomatic Go interface to the Seev payment API. It works with any Go web framework — Gin, Echo, Chi, net/http, and more.

Installation

go get github.com/seev/sdk/pkg/seevpay

Or if working inside the same workspace, import directly:

import "seevcashplus/pkg/seevpay"

Initialise the SDK

Call seevpay.Init() once at startup — in init() or your application bootstrap — before making any API calls.

package main

import (
	"log"
	"seevcashplus/pkg/seevpay"
)

func init() {
	err := seevpay.Init(seevpay.Config{
		PublicKey:  "pk_your_public_key",
		PrivateKey: "sk_your_secret_key",
	})
	if err != nil {
		log.Fatal("Failed to initialise Seev SDK:", err)
	}
}

Create a charge

seevpay.Charge(req ChargeRequest)

Create a checkout session and redirect the customer to the returned CheckoutURL.

Returns: (*Charge, error)

With a fixed amount:

charge, err := seevpay.Charge(seevpay.ChargeRequest{
	Type: "checkout",
	Recipient: seevpay.CheckoutRecipient{
		Name:    "Jane Doe",
		Email:   "jane@example.com",
		Phone:   "+233501234567",
		Address: "123 Main St",
		City:    "Accra",
	},
	Amount:      seevpay.Int64Ptr(10000), // 10000 = GHS 100.00
	Currency:    "GHS",
	Channels:    []string{"card", "mobile_money"},
	Discount:    seevpay.Float64Ptr(5),
	Tax:         seevpay.Float64Ptr(2.5),
	RedirectURL: "https://myapp.com/callback",
})
if err != nil {
	log.Fatalf("Charge failed: %v", err)
}

// Redirect the customer
fmt.Println(charge.CheckoutURL)

With line items (amount calculated server-side):

charge, err := seevpay.Charge(seevpay.ChargeRequest{
	Type: "checkout",
	Recipient: seevpay.CheckoutRecipient{
		Name:  "John Doe",
		Email: "john@example.com",
	},
	Items: []seevpay.CheckoutItem{
		{
			Name:        "Product A",
			Description: "A great product",
			Quantity:    seevpay.Int64Ptr(2),
			Price:       5000,
			Image:       "https://example.com/product-a.jpg",
		},
		{
			Name:     "Product B",
			Quantity: seevpay.Int64Ptr(1),
			Price:    3000,
		},
	},
	Currency:    "GHS",
	RedirectURL: "https://myapp.com/callback",
})

Charge fields:

FieldTypeDescription
charge.IDstringCheckout session ID
charge.CheckoutURLstringURL to redirect the customer to
charge.StatusstringInitial session status
charge.Amountint64Resolved charge amount
charge.CurrencystringCharge currency
charge.GetResponse()map[string]interface{}Full API response
charge.GetRaw(key)interface{}Access any field from the raw response

Handle the callback

seevpay.Callback(sessionID string)

Verify the session after the customer returns from the checkout page.

Returns: (*Callback, error)

// Gin example
func handleCallback(c *gin.Context) {
	sessionID := c.Query("session_id")

	session, err := seevpay.Callback(sessionID)
	if err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	if session.IsSuccessful() {
		log.Printf("Payment successful — session: %s", session.ID)
		c.JSON(200, gin.H{"status": "success"})
	} else {
		c.JSON(200, gin.H{"status": session.Status})
	}
}

Callback fields:

Field / MethodTypeDescription
session.IDstringSession ID
session.StatusstringPayment status
session.ReferencestringTransaction reference
session.IsSuccessful()booltrue if payment completed
session.GetSession()map[string]interface{}Full session object

Handle webhooks

seevpay.Webhook(body map[string]interface{}, user interface{})

Parse incoming Seev webhook events. Always return 200 quickly and process asynchronously.

Returns: (*Webhook, error)

func handleWebhook(c *gin.Context) {
	var body map[string]interface{}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, gin.H{"error": "Invalid request"})
		return
	}

	event, err := seevpay.Webhook(body, nil)
	if err != nil {
		c.JSON(400, gin.H{"error": "Invalid webhook"})
		return
	}

	switch {
	case event.Is("checkout.completed"):
		data := event.GetData()
		log.Printf("Payment completed: %v %v %v",
			data["checkoutId"], data["amount"], data["currency"])

	case event.Is("checkout.failed"):
		data := event.GetData()
		log.Printf("Payment failed: %v%v", data["checkoutId"], data["reason"])

	case event.Is("refund.issued"):
		log.Printf("Refund issued: %v", event.GetData())

	default:
		log.Printf("Unhandled event: %s", event.Type())
	}

	c.JSON(200, gin.H{"received": true})
}

Webhook fields:

Field / MethodDescription
event.Type()Event type string, e.g. "checkout.completed"
event.Is(type)true if the event matches the given type
event.GetData()Event payload as map[string]interface{}
event.User()Associated user (passed as second arg to Webhook())
event.GetRawEvent()Full raw event object

Common webhook events:

EventDescription
checkout.completedPayment succeeded
checkout.failedPayment failed
checkout.pendingPayment is pending confirmation
refund.issuedA refund was issued
invoice.createdInvoice was created
invoice.paidInvoice was paid

Fetch a transaction

seevpay.Transaction(transactionID string)

Retrieve details about a specific transaction. Use this server-side to confirm payment status.

Returns: (*Transaction, error)

txn, err := seevpay.Transaction("txn_abc123xyz")
if err != nil {
	log.Fatalf("Failed to fetch transaction: %v", err)
}

log.Printf("Status: %s — Amount: %d %s", txn.Status, txn.Amount, txn.Currency)

Transaction fields:

FieldTypeDescription
txn.IDstringTransaction ID
txn.Statusstring"completed", "pending", "failed"
txn.Amountint64Transaction amount
txn.CurrencystringTransaction currency
txn.ReferencestringOptional reference

Type reference

Config

type Config struct {
	PublicKey  string        // Your Seev public key
	PrivateKey string        // Your Seev private key
	BaseURL    string        // Optional — defaults to production URL
	Timeout    time.Duration // Optional — defaults to 30s
}

ChargeRequest

type ChargeRequest struct {
	Type        string            // "checkout" | "invoice" | "payment_link"
	Recipient   CheckoutRecipient
	Currency    string            // GHS | USD | EUR | GBP | NGN | USDC | USDT | ETH | BTC | XRP
	Channels    []string          // card | mobile_money | bank_transfer | seev | crypto
	Amount      *int64            // Omit if using Items
	Items       []CheckoutItem    // Omit if using Amount
	Discount    *float64
	Tax         *float64
	RedirectURL string            // Required
}

CheckoutRecipient

type CheckoutRecipient struct {
	Name    string // Required
	Email   string // Required
	Address string // Optional
	City    string // Optional
	Phone   string // Optional
}

CheckoutItem

type CheckoutItem struct {
	Name        string
	Description string // Optional
	Quantity    *int64 // Optional — defaults to 1
	Price       int64  // Required
	Image       string // Optional
}

Helper functions

The SDK provides pointer helpers for optional numeric fields:

amount   := seevpay.Int64Ptr(10000)
discount := seevpay.Float64Ptr(5.0)

Error handling

All SDK functions return Go errors. Use errors.As to inspect SDK-specific errors:

charge, err := seevpay.Charge(seevpay.ChargeRequest{ /* ... */ })
if err != nil {
	var sdkErr *seevpay.SDKError
	if errors.As(err, &sdkErr) {
		log.Printf("SDK error [%s]: %s", sdkErr.Code, sdkErr.Message)
	} else {
		log.Printf("Unexpected error: %v", err)
	}
}

Common errors:

ErrorCause
"Seev SDK not initialized. Call Init() first."Init() was not called before making a request
"Failed to create checkout session: ..."Bad request data or invalid API keys
"Failed to verify checkout session: session not found or invalid"Expired or invalid session ID
"Invalid webhook payload: missing event type"Malformed webhook body
"Network error: ..."Connectivity issue or unreachable endpoint

Full integration example

package main

import (
	"log"

	"github.com/gin-gonic/gin"
	"seevcashplus/pkg/seevpay"
)

func init() {
	if err := seevpay.Init(seevpay.Config{
		PublicKey:  "pk_test_123",
		PrivateKey: "sk_test_456",
	}); err != nil {
		log.Fatal(err)
	}
}

func main() {
	r := gin.Default()

	r.POST("/checkout", func(c *gin.Context) {
		charge, err := seevpay.Charge(seevpay.ChargeRequest{
			Type:      "checkout",
			Recipient: seevpay.CheckoutRecipient{Name: "Jane Doe", Email: "jane@example.com"},
			Items: []seevpay.CheckoutItem{
				{Name: "Widget", Price: 2500, Quantity: seevpay.Int64Ptr(1)},
			},
			Currency:    "GHS",
			RedirectURL: "https://myapp.com/callback",
		})
		if err != nil {
			c.JSON(400, gin.H{"error": err.Error()})
			return
		}
		c.JSON(200, gin.H{"checkoutUrl": charge.CheckoutURL})
	})

	r.GET("/callback", func(c *gin.Context) {
		result, err := seevpay.Callback(c.Query("session_id"))
		if err != nil {
			c.JSON(400, gin.H{"error": err.Error()})
			return
		}
		if result.IsSuccessful() {
			c.JSON(200, gin.H{"status": "success", "sessionId": result.ID})
		} else {
			c.JSON(200, gin.H{"status": result.Status})
		}
	})

	r.POST("/webhooks/seev", func(c *gin.Context) {
		var body map[string]interface{}
		if err := c.ShouldBindJSON(&body); err != nil {
			c.JSON(400, gin.H{"error": "Invalid request"})
			return
		}
		event, err := seevpay.Webhook(body, nil)
		if err != nil {
			c.JSON(400, gin.H{"error": "Invalid webhook"})
			return
		}
		if event.Is("checkout.completed") {
			log.Printf("Payment completed: %v", event.GetData())
		}
		c.JSON(200, gin.H{"received": true})
	})

	r.GET("/transaction/:id", func(c *gin.Context) {
		txn, err := seevpay.Transaction(c.Param("id"))
		if err != nil {
			c.JSON(400, gin.H{"error": err.Error()})
			return
		}
		c.JSON(200, txn)
	})

	r.Run(":8080")
}

Advanced configuration

// Custom base URL (e.g. sandbox) and timeout
seevpay.Init(seevpay.Config{
	PublicKey:  "pk_test_123",
	PrivateKey: "sk_test_456",
	BaseURL:    "https://sandbox-api.seevpay.com",
	Timeout:    45 * time.Second,
})

Next steps

On this page