Documentation Index
Fetch the complete documentation index at: https://docs.snappay.dev/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The SnapPay Go SDK provides a comprehensive, idiomatic interface for integrating payment processing, subscription management, and real-time event streaming into your Go applications. Built with modern Go patterns including context support, channel-based concurrency, and explicit error handling, it offers seamless integration with SnapPay’s platform.
Requirements: Go 1.21+
Key Features
- Idiomatic Go design with context.Context support for cancellation and timeouts
- Channel-based concurrency for optimal performance and real-time event handling
- Explicit error handling following Go conventions
- Full type safety with struct definitions and interface contracts
- Goroutine-safe client for concurrent usage across your application
- Real-time event streaming via Server-Sent Events (SSE) using channels
- Context-aware operations with deadline propagation and cancellation
- Environment-based configuration with sensible defaults
Installation
go get github.com/snappay/snappay-go
Add to your go.mod:
module your-app
go 1.21
require (
github.com/snappay/snappay-go v0.0.1-beta
)
Configuration & Initialization
The SDK client is configured via a constructor function that accepts an optional configuration struct. All operations support context.Context for proper timeout and cancellation handling.
API Key Authentication
Authentication is handled via an API key that must start with pk_test_ (for testing) or pk_live_ (for production). Configure your API key in one of these ways:
Environment Variable (Recommended):
export SNAPPAY_API_KEY="pk_test_xxxxxxxxxx"
Direct Configuration:
package main
import (
"context"
"log"
"github.com/snappay/snappay-go"
"github.com/snappay/snappay-go/services"
)
func main() {
// Using environment variable (recommended)
client, err := snappay.NewClient(nil)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
// Using direct API key
client, err = snappay.NewClient(&services.Config{
APIKey: "pk_test_xxxxxxxxxx",
})
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
}
Core Methods
All methods accept a context.Context as the first parameter and return a result struct pointer and an error, following standard Go patterns. The client is safe for concurrent use across multiple goroutines.
Customer Management
GetCustomer
Retrieves or creates a customer record (upsert logic).
import "github.com/snappay/snappay-go/services/customer"
ctx := context.Background()
customer, err := customer.Get(client, ctx, customer.GetCustomerArgs{
CustomerId: "cus_123",
Email: "user@example.com", // Optional
Name: stringPtr("John Doe"), // Optional
})
if err != nil {
log.Fatalf("Failed to get customer: %v", err)
}
fmt.Printf("Customer ID: %s\n", customer.CustomerID)
Parameters:
CustomerId (string): Customer identifier
Email (*string): Customer email address (optional)
Name (*string): Customer full name (optional)
Returns: (*Customer, error)
type Customer struct {
CustomerID string `json:"cus_id"` // SnapPay customer ID
Email string `json:"email"` // Customer email
Name *string `json:"name"` // Customer name (optional)
}
Checkout Sessions
CreateCheckoutSession
Creates a payment checkout session URL for customer purchases.
import "github.com/snappay/snappay-go/services/checkout"
ctx := context.Background()
session, err := checkout.CreateSession(client, ctx, checkout.CreateCheckoutSessionArgs{
CustomerID: "cus_123",
ProductID: "premium-plan",
SuccessURL: "https://yourapp.com/success",
CancelURL: stringPtr("https://yourapp.com/cancel"), // Optional
})
if err != nil {
log.Fatalf("Failed to create checkout session: %v", err)
}
fmt.Printf("Checkout URL: %s\n", session.URL)
Parameters:
CustomerID (string): SnapPay customer ID
ProductID (string): Product ID from your snappay dashboard
PriceID (*string): Price ID from your snappay dashboard (optional)
SuccessURL (string): URL to redirect after successful payment
CancelURL (*string): URL to redirect on cancellation (optional)
Returns: (*CheckoutSession, error)
type CheckoutSession struct {
SessionID string `json:"session_id"` // Unique session identifier
URL string `json:"url"` // Checkout URL for customer
ExpiresAt string `json:"expires_at"` // Session expiration timestamp
}
Access Control
CheckAccess
Checks if a customer has access to a specific feature based on their subscription and usage limits.
import "github.com/snappay/snappay-go/services/access"
ctx := context.Background()
access, err := access.Check(client, ctx, access.CheckAccessArgs{
CustomerID: "cus_123",
FeatureID: "premium-features",
})
if err != nil {
log.Fatalf("Failed to check access: %v", err)
}
if access.HasAccess {
if access.Usage != nil && access.Allowance != nil {
remaining := *access.Allowance - *access.Usage
fmt.Printf("Access granted. %d/%d used\n", *access.Usage, *access.Allowance)
fmt.Printf("Remaining: %d\n", remaining)
} else {
fmt.Println("Access granted (unlimited feature)")
}
} else {
fmt.Println("Access denied. Upgrade required.")
}
Parameters:
CustomerID (string): SnapPay customer ID
FeatureID (string): Feature identifier
Returns: (*AccessCheck, error)
type AccessCheck struct {
HasAccess bool `json:"has_access"`
FeatureID string `json:"feature_id"`
Usage *int64 `json:"usage"`
Allowance *int64 `json:"allowance"`
NextResetAt *int64 `json:"next_reset_at"`
}
Usage Tracking
TrackUsage
Reports usage for a metered feature. This action is idempotent to prevent duplicate tracking.
import "github.com/snappay/snappay-go/services/usage"
ctx := context.Background()
result, err := usage.Track(client, ctx, usage.TrackUsageArgs{
CustomerID: "cus_123",
FeatureID: "ai-messages",
Usage: 1, // integer usage units
IdempotencyKey: stringPtr("unique-operation-123"), // Optional
})
if err != nil {
log.Fatalf("Failed to track usage: %v", err)
}
fmt.Printf("Tracked %d units. Total: %d (idempotency: %v)\n", result.Added, result.Used, result.IdempotencyKey)
Parameters:
CustomerID (string): SnapPay customer ID
FeatureID (string): Feature identifier for usage tracking
Usage (int64): Usage amount to track
IdempotencyKey (*string): Prevents duplicate tracking (optional)
Returns: (*TrackUsageResponse, error)
type TrackUsageResponse struct {
CustomerID string `json:"customer_id"` // Customer ID
FeatureID string `json:"feature_id"` // Feature ID
UsageRecorded int64 `json:"usage_recorded"` // Amount of usage recorded
UsageTotal int64 `json:"usage_total"` // Total usage after this operation
Timestamp string `json:"timestamp"` // Timestamp of the operation
IdempotencyKey *string `json:"idempotency_key"` // Idempotency key used (if any)
}
GetUsage
Retrieves current usage details for a customer’s feature.
ctx := context.Background()
items, err := usage.Get(client, ctx, usage.GetUsageArgs{
CustomerID: "cus_123",
FeatureID: "ai-messages",
})
if err != nil {
log.Fatalf("Failed to get usage: %v", err)
}
for i, u := range *items {
fmt.Printf("Record %d:\n", i+1)
fmt.Printf(" Product ID: %s\n", u.ProductID)
fmt.Printf(" Feature ID: %s\n", u.FeatureID)
fmt.Printf(" Total usage: %d\n", u.TotalUsage)
fmt.Printf(" Remaining: %s\n", formatUsage(u.Remaining))
fmt.Printf(" Limit: %s\n", formatUsage(u.Limit))
if u.NextResetAt != nil {
fmt.Printf(" Next reset: %d\n", *u.NextResetAt)
}
fmt.Println()
}
Parameters:
CustomerID (string): SnapPay customer ID
FeatureID (string): Feature identifier
Returns: (*[]GetUsageResponse, error)
type GetUsageResponse struct {
TotalUsage int64 `json:"total_usage"`
ProductID string `json:"product_id"`
FeatureID string `json:"feature_id"`
Remaining *int64 `json:"remaining,omitempty"`
Limit *int64 `json:"limit,omitempty"`
NextResetAt *int64 `json:"next_reset_at,omitempty"`
}
Real-time Event Handling
Say goodbye to webhook hell! snappay eliminates the complexity of managing payment webhooks by processing all provider webhooks (Stripe, PayPal, etc.) internally and delivering clean, structured events directly to your application via Server-Sent Events (SSE) using Go channels.
🚫 What You DON’T Need:
- No webhook endpoints to create and maintain
- No webhook signature verification
- No webhook retry logic or failure handling
- No webhook security concerns
- No debugging webhook delivery issues
✅ What You GET:
- Real-time events delivered instantly via Go channels
- Guaranteed delivery with automatic reconnection
- Clean, structured data - no raw webhook payloads
- Channel-based concurrency perfect for Go’s goroutine model
- Context-aware with proper cancellation support
Supported Events
See the list of supported events: Server-sent Event Types
Stream Events (Async Generator)
Consume the SSE stream via channels for direct, context-aware processing:
package main
import (
"context"
"log"
"os/signal"
"syscall"
"github.com/snappay/snappay-sdk-go"
"github.com/snappay/snappay-sdk-go/services/sse"
)
func main() {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
client, err := snappay.NewClient(nil)
if err != nil {
log.Fatalf("create client: %v", err)
}
if err := client.StartEvents(ctx); err != nil {
log.Fatalf("start events: %v", err)
}
evCh, errCh := client.StreamEvents(ctx)
for {
select {
case <-ctx.Done():
return
case err := <-errCh:
if err != nil { log.Printf("sse error: %v", err) }
case ev := <-evCh:
if ev == nil { continue }
if ev.Type == sse.EventTypeSubscriptionUpdated {
if d, err := ev.GetSubscriptionData(); err == nil {
log.Printf("subscription: customer=%s status=%s", d.CustomerID, d.PaymentStatus)
}
}
}
}
}
Event Handlers
Register handlers as separate functions and wire them up succinctly:
package main
import (
"context"
"log"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/snappay/snappay-sdk-go"
"github.com/snappay/snappay-sdk-go/services/sse"
)
func handleSubscriptionUpdated(e *sse.SSEEvent) error {
if d, err := e.GetSubscriptionData(); err == nil {
log.Printf("subscription: customer=%s status=%s", d.CustomerID, d.PaymentStatus)
}
return nil
}
func handleAnyEvent(e *sse.SSEEvent) error {
if e.IsSystemEvent() { return nil }
log.Printf("event: %s", e.Type)
return nil
}
func setupEventHandlers(client *snappay.Client) {
client.OnEvent(sse.EventTypeSubscriptionUpdated, handleSubscriptionUpdated)
client.OnAnyEvent(handleAnyEvent)
}
func main() {
client, err := snappay.NewClient(nil)
if err != nil { log.Fatalf("create client: %v", err) }
setupEventHandlers(client)
ctx := context.Background()
if err := client.StartEvents(ctx); err != nil { log.Fatalf("start events: %v", err) }
// Set up signal handling for graceful shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
// Wait for interrupt signal
<-sigChan
fmt.Println("\n\n🛑 Stopping SSE connection...")
if err := client.StopEvents(); err != nil {
log.Printf("Error stopping events: %v", err)
}
}
Error Handling
Error Types
// Error hierarchy
type SnapPayError interface {
error
StatusCode() int
RequestID() string
}
type AuthenticationError struct {
Message string
Code int
ReqID string
}
type ValidationError struct {
Message string
Code int
ReqID string
Fields map[string]string // Field-specific validation errors
}
type RateLimitError struct {
Message string
Code int
ReqID string
RetryAfter int // Seconds to wait before retrying
}
type NotFoundError struct {
Message string
Code int
ReqID string
}
type ServerError struct {
Message string
Code int
ReqID string
}