Client API
The Client is the main entry point for interacting with the VaultSandbox Gateway. It handles authentication, inbox creation, and provides utility methods for managing inboxes.
Constants
Section titled “Constants”TTL (time-to-live) constants for inbox creation:
const ( MinTTL = 60 * time.Second // Minimum TTL: 1 minute MaxTTL = 604800 * time.Second // Maximum TTL: 7 days)Constructor
Section titled “Constructor”func New(apiKey string, opts ...Option) (*Client, error)Creates a new VaultSandbox client instance.
Options
Section titled “Options”Configuration options for the client using the functional options pattern.
// Available optionsWithBaseURL(url string) OptionWithHTTPClient(client *http.Client) OptionWithDeliveryStrategy(strategy DeliveryStrategy) OptionWithTimeout(timeout time.Duration) OptionWithRetries(count int) OptionWithRetryOn(statusCodes []int) OptionWithOnSyncError(fn func(error)) OptionOption Functions
Section titled “Option Functions”| Option | Type | Default | Description |
|---|---|---|---|
WithBaseURL | string | https://api.vaultsandbox.com | Gateway URL |
WithHTTPClient | *http.Client | Default client | Custom HTTP client |
WithDeliveryStrategy | DeliveryStrategy | StrategyAuto | Email delivery strategy |
WithTimeout | time.Duration | 60s | Request timeout |
WithRetries | int | 3 | Maximum retry attempts for HTTP requests |
WithRetryOn | []int | [408, 429, 500, 502, 503, 504] | HTTP status codes that trigger a retry |
WithOnSyncError | func(error) | nil | Callback for background sync errors |
Polling Configuration Options
Section titled “Polling Configuration Options”For advanced control over polling behavior, use WithPollingConfig:
// Polling configuration structtype PollingConfig struct { InitialInterval time.Duration // Starting polling interval (default: 2s) MaxBackoff time.Duration // Maximum polling interval (default: 30s) BackoffMultiplier float64 // Interval multiplier after no changes (default: 1.5) JitterFactor float64 // Randomness factor to prevent synchronized polling (default: 0.3) SSEConnectionTimeout time.Duration // Timeout for SSE before falling back to polling (default: 5s)}
WithPollingConfig(cfg PollingConfig) Option| Field | Type | Default | Description |
|---|---|---|---|
InitialInterval | time.Duration | 2s | Starting polling interval |
MaxBackoff | time.Duration | 30s | Maximum polling interval after backoff |
BackoffMultiplier | float64 | 1.5 | Multiplier for interval after each poll with no changes |
JitterFactor | float64 | 0.3 | Random jitter factor (30%) to prevent synchronized polling |
SSEConnectionTimeout | time.Duration | 5s | Timeout for SSE connection in auto mode before fallback |
Delivery Strategies
Section titled “Delivery Strategies”const ( StrategyAuto DeliveryStrategy = "auto" // SSE with fallback to polling StrategySSE DeliveryStrategy = "sse" // Server-Sent Events only StrategyPolling DeliveryStrategy = "polling" // Periodic polling only)Example
Section titled “Example”package main
import ( "os" "time"
vaultsandbox "github.com/vaultsandbox/client-go")
func main() { client, err := vaultsandbox.New( os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL("https://api.vaultsandbox.com"), vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyAuto), vaultsandbox.WithRetries(5), vaultsandbox.WithTimeout(30*time.Second), ) if err != nil { panic(err) } defer client.Close()}Methods
Section titled “Methods”CreateInbox
Section titled “CreateInbox”Creates a new email inbox with automatic key generation and encryption setup.
func (c *Client) CreateInbox(ctx context.Context, opts ...InboxOption) (*Inbox, error)Parameters
Section titled “Parameters”ctx: Context for cancellation and timeoutsopts(optional): Configuration options for the inbox
// Available inbox optionsWithTTL(ttl time.Duration) InboxOptionWithEmailAddress(email string) InboxOption| Option | Type | Description |
|---|---|---|
WithTTL | time.Duration | Time-to-live for the inbox (min: 60s, max: 7 days, default: 1 hour) |
WithEmailAddress | string | Request a specific email address (e.g., [email protected]) |
Returns
Section titled “Returns”*Inbox- The created inbox instanceerror- Any error that occurred
Example
Section titled “Example”ctx := context.Background()
// Create inbox with default settingsinbox, err := client.CreateInbox(ctx)if err != nil { log.Fatal(err)}fmt.Println(inbox.EmailAddress())
// Create inbox with custom TTL (1 hour)inbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(time.Hour))
// Request specific email addressinbox, err := client.CreateInbox(ctx,)Errors
Section titled “Errors”ErrUnauthorized- Invalid API keyErrInboxAlreadyExists- Requested email address is already in use*NetworkError- Network connection failure*APIError- API-level error (invalid request, permission denied)
DeleteAllInboxes
Section titled “DeleteAllInboxes”Deletes all inboxes associated with the current API key. Useful for cleanup in test environments.
func (c *Client) DeleteAllInboxes(ctx context.Context) (int, error)Returns
Section titled “Returns”int- Number of inboxes deletederror- Any error that occurred
Example
Section titled “Example”deleted, err := client.DeleteAllInboxes(ctx)if err != nil { log.Fatal(err)}fmt.Printf("Deleted %d inboxes\n", deleted)Best Practice
Section titled “Best Practice”Use this in test cleanup to avoid orphaned inboxes:
func TestMain(m *testing.M) { // Setup client, _ := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY"))
code := m.Run()
// Cleanup deleted, _ := client.DeleteAllInboxes(context.Background()) if deleted > 0 { log.Printf("Cleaned up %d orphaned inboxes\n", deleted) } client.Close()
os.Exit(code)}ServerInfo
Section titled “ServerInfo”Returns information about the VaultSandbox Gateway server. This information is fetched once during client initialization.
func (c *Client) ServerInfo() *ServerInfoReturns
Section titled “Returns”*ServerInfo - Server information struct
type ServerInfo struct { AllowedDomains []string MaxTTL time.Duration DefaultTTL time.Duration}| Field | Type | Description |
|---|---|---|
AllowedDomains | []string | List of domains allowed for inbox creation |
MaxTTL | time.Duration | Maximum time-to-live for inboxes |
DefaultTTL | time.Duration | Default time-to-live for inboxes |
Example
Section titled “Example”info := client.ServerInfo()fmt.Printf("Max TTL: %v, Default TTL: %v\n", info.MaxTTL, info.DefaultTTL)fmt.Printf("Allowed domains: %v\n", info.AllowedDomains)CheckKey
Section titled “CheckKey”Validates the API key with the server.
func (c *Client) CheckKey(ctx context.Context) errorReturns
Section titled “Returns”error-nilif the API key is valid, otherwise an error
Example
Section titled “Example”if err := client.CheckKey(ctx); err != nil { log.Fatal("Invalid API key:", err)}Useful for verifying configuration before running tests:
func TestMain(m *testing.M) { client, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY")) if err != nil { log.Fatal(err) }
if err := client.CheckKey(context.Background()); err != nil { log.Fatal("VaultSandbox API key is invalid:", err) }
os.Exit(m.Run())}WatchInboxes
Section titled “WatchInboxes”Returns a channel that receives events from multiple inboxes. The channel closes when the context is cancelled.
func (c *Client) WatchInboxes(ctx context.Context, inboxes ...*Inbox) <-chan *InboxEventParameters
Section titled “Parameters”ctx: Context for cancellation - when cancelled, the channel closes and all watchers are cleaned upinboxes: Variadic list of inbox instances to watch
Returns
Section titled “Returns”<-chan *InboxEvent- Receive-only channel of inbox events
InboxEvent Type
Section titled “InboxEvent Type”type InboxEvent struct { Inbox *Inbox // The inbox that received the email Email *Email // The received email}Example
Section titled “Example”inbox1, _ := client.CreateInbox(ctx)inbox2, _ := client.CreateInbox(ctx)
watchCtx, cancel := context.WithTimeout(ctx, 5*time.Minute)defer cancel()
for event := range client.WatchInboxes(watchCtx, inbox1, inbox2) { fmt.Printf("New email in %s: %s\n", event.Inbox.EmailAddress(), event.Email.Subject)}Behavior
Section titled “Behavior”- Returns immediately closed channel if no inboxes provided
- Channel has buffer size of 16
- Non-blocking sends: if channel buffer is full, events may be dropped
- All internal goroutines and watchers are cleaned up when context is cancelled
See Real-time Monitoring Guide for more details.
WatchInboxesFunc
Section titled “WatchInboxesFunc”Calls a callback function for each event from multiple inboxes until the context is cancelled. This is a convenience wrapper around WatchInboxes for simpler use cases where you don’t need channel semantics.
func (c *Client) WatchInboxesFunc(ctx context.Context, fn func(*InboxEvent), inboxes ...*Inbox)Parameters
Section titled “Parameters”ctx: Context for cancellation - when cancelled, watching stopsfn: Callback function called for each new eventinboxes: Variadic list of inbox instances to watch
Example
Section titled “Example”ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)defer cancel()
client.WatchInboxesFunc(ctx, func(event *vaultsandbox.InboxEvent) { fmt.Printf("Email in %s: %s\n", event.Inbox.EmailAddress(), event.Email.Subject)
// Route based on inbox switch event.Inbox.EmailAddress() { handleAlert(event.Email) default: handleGeneral(event.Email) }}, inbox1, inbox2, inbox3)Behavior
Section titled “Behavior”- Blocks until context is cancelled
- Each event is passed to the callback function
- Uses
WatchInboxesinternally with proper context handling
When to Use
Section titled “When to Use”Use WatchInboxesFunc instead of WatchInboxes when:
- You prefer callback-style processing over channel iteration
- You want simpler code without channel select statements
- You’re processing events in a blocking manner
GetInbox
Section titled “GetInbox”Retrieves an inbox by its email address from the client’s managed inboxes.
func (c *Client) GetInbox(emailAddress string) (*Inbox, bool)Parameters
Section titled “Parameters”emailAddress: The email address of the inbox to retrieve
Returns
Section titled “Returns”*Inbox- The inbox instance if foundbool-trueif the inbox was found,falseotherwise
Example
Section titled “Example”if !ok { log.Fatal("Inbox not found")}fmt.Println(inbox.EmailAddress())Inboxes
Section titled “Inboxes”Returns all inboxes currently managed by the client.
func (c *Client) Inboxes() []*InboxReturns
Section titled “Returns”[]*Inbox - Slice of all managed inbox instances
Example
Section titled “Example”for _, inbox := range client.Inboxes() { fmt.Printf("Inbox: %s (expires: %v)\n", inbox.EmailAddress(), inbox.ExpiresAt())}DeleteInbox
Section titled “DeleteInbox”Deletes a specific inbox by its email address.
func (c *Client) DeleteInbox(ctx context.Context, emailAddress string) errorParameters
Section titled “Parameters”ctx: Context for cancellation and timeoutsemailAddress: The email address of the inbox to delete
Returns
Section titled “Returns”error- Any error that occurred
Example
Section titled “Example”if err != nil { log.Fatal(err)}ExportInboxToFile
Section titled “ExportInboxToFile”Exports an inbox to a JSON file on disk. The exported data includes sensitive key material and should be treated as confidential.
func (c *Client) ExportInboxToFile(inbox *Inbox, filePath string) errorParameters
Section titled “Parameters”inbox: Inbox instance to exportfilePath: Path where the JSON file will be written
Returns
Section titled “Returns”error- Any error that occurred
Example
Section titled “Example”inbox, _ := client.CreateInbox(ctx)
// Export to fileerr := client.ExportInboxToFile(inbox, "./backup/inbox.json")if err != nil { log.Fatal(err)}
fmt.Println("Inbox exported to ./backup/inbox.json")Security Warning
Section titled “Security Warning”Exported data contains private encryption keys. Store securely and never commit to version control.
ImportInbox
Section titled “ImportInbox”Imports a previously exported inbox, restoring all data and encryption keys.
func (c *Client) ImportInbox(ctx context.Context, data *ExportedInbox) (*Inbox, error)Parameters
Section titled “Parameters”ctx: Context for cancellation and timeoutsdata: Previously exported inbox data
Returns
Section titled “Returns”*Inbox- The imported inbox instanceerror- Any error that occurred
ExportedInbox Type
Section titled “ExportedInbox Type”type ExportedInbox struct { EmailAddress string `json:"emailAddress"` ExpiresAt time.Time `json:"expiresAt"` InboxHash string `json:"inboxHash"` ServerSigPk string `json:"serverSigPk"` PublicKeyB64 string `json:"publicKeyB64"` SecretKeyB64 string `json:"secretKeyB64"` ExportedAt time.Time `json:"exportedAt"`}Example
Section titled “Example”// Load exported datadata, _ := os.ReadFile("./backup/inbox.json")
var exportedData vaultsandbox.ExportedInboxjson.Unmarshal(data, &exportedData)
inbox, err := client.ImportInbox(ctx, &exportedData)if err != nil { log.Fatal(err)}
fmt.Printf("Imported inbox: %s\n", inbox.EmailAddress())
// Use inbox normallyemails, _ := inbox.GetEmails(ctx)Errors
Section titled “Errors”ErrInboxAlreadyExists- Inbox is already imported in this clientErrInvalidImportData- Import data is invalid or corrupted*APIError- Server rejected the import (inbox may not exist)
ImportInboxFromFile
Section titled “ImportInboxFromFile”Imports an inbox from a JSON file.
func (c *Client) ImportInboxFromFile(ctx context.Context, filePath string) (*Inbox, error)Parameters
Section titled “Parameters”ctx: Context for cancellation and timeoutsfilePath: Path to the exported inbox JSON file
Returns
Section titled “Returns”*Inbox- The imported inbox instanceerror- Any error that occurred
Example
Section titled “Example”// Import from fileinbox, err := client.ImportInboxFromFile(ctx, "./backup/inbox.json")if err != nil { log.Fatal(err)}
fmt.Printf("Imported inbox: %s\n", inbox.EmailAddress())
// Watch for new emailswatchCtx, cancel := context.WithTimeout(ctx, 5*time.Minute)defer cancel()
for email := range inbox.Watch(watchCtx) { fmt.Printf("New email: %s\n", email.Subject)}Use Cases
Section titled “Use Cases”- Test reproducibility across runs
- Sharing inboxes between environments
- Manual testing workflows
- Debugging production issues
Closes the client, terminates any active SSE or polling connections, and cleans up resources.
func (c *Client) Close() errorReturns
Section titled “Returns”error- Any error that occurred during cleanup
Example
Section titled “Example”client, _ := vaultsandbox.New(apiKey)
defer client.Close()
inbox, _ := client.CreateInbox(ctx)// Use inbox...Best Practice
Section titled “Best Practice”Always close the client when done, especially in long-running processes:
var client *vaultsandbox.Client
func TestMain(m *testing.M) { var err error client, err = vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY")) if err != nil { log.Fatal(err) }
code := m.Run()
client.Close() os.Exit(code)}Errors
Section titled “Errors”The client package exports sentinel errors for use with errors.Is() checks, as well as error types for detailed error handling.
Sentinel Errors
Section titled “Sentinel Errors”var ( ErrMissingAPIKey error // No API key provided ErrClientClosed error // Operations attempted on a closed client ErrUnauthorized error // Invalid or expired API key ErrInboxNotFound error // Inbox not found ErrEmailNotFound error // Email not found ErrInboxAlreadyExists error // Inbox already exists (import conflict) ErrInvalidImportData error // Invalid or corrupted import data ErrDecryptionFailed error // Email decryption failed ErrSignatureInvalid error // Signature verification failed ErrRateLimited error // API rate limit exceeded)Example
Section titled “Example”inbox, err := client.CreateInbox(ctx)if errors.Is(err, vaultsandbox.ErrUnauthorized) { log.Fatal("Invalid API key")}if errors.Is(err, vaultsandbox.ErrRateLimited) { log.Println("Rate limited, retrying...")}Error Types
Section titled “Error Types”APIError
Section titled “APIError”Represents an HTTP error from the VaultSandbox API.
type APIError struct { StatusCode int // HTTP status code Message string // Error message from server RequestID string // Request ID for support}NetworkError
Section titled “NetworkError”Represents a network-level failure.
type NetworkError struct { Err error // Underlying network error}SignatureVerificationError
Section titled “SignatureVerificationError”Indicates signature verification failed, including potential server key mismatch (MITM detection).
type SignatureVerificationError struct { Message string}ResourceType
Section titled “ResourceType”Used to identify which resource type an error relates to:
type ResourceType string
const ( ResourceUnknown ResourceType = "" // Resource type not specified ResourceInbox ResourceType = "inbox" // Error relates to an inbox ResourceEmail ResourceType = "email" // Error relates to an email)Example: Type Assertions
Section titled “Example: Type Assertions”email, err := inbox.GetEmail(ctx, emailID)if err != nil { var apiErr *vaultsandbox.APIError if errors.As(err, &apiErr) { log.Printf("API error %d: %s (request: %s)", apiErr.StatusCode, apiErr.Message, apiErr.RequestID) }
var netErr *vaultsandbox.NetworkError if errors.As(err, &netErr) { log.Printf("Network error: %v", netErr.Err) }}Complete Example
Section titled “Complete Example”Here’s a complete example showing typical client usage:
package main
import ( "context" "fmt" "log" "os" "regexp" "time"
vaultsandbox "github.com/vaultsandbox/client-go")
func main() { ctx := context.Background()
// Create client client, err := vaultsandbox.New( os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL(os.Getenv("VAULTSANDBOX_URL")), vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyAuto), vaultsandbox.WithRetries(5), ) if err != nil { log.Fatal(err) } defer client.Close()
// Verify API key if err := client.CheckKey(ctx); err != nil { log.Fatal("Invalid API key:", err) }
// Get server info info := client.ServerInfo() fmt.Printf("Connected to VaultSandbox (default TTL: %v)\n", info.DefaultTTL)
// Create inbox inbox, err := client.CreateInbox(ctx) if err != nil { log.Fatal(err) } fmt.Printf("Created inbox: %s\n", inbox.EmailAddress())
// Export for later use if err := client.ExportInboxToFile(inbox, "./inbox-backup.json"); err != nil { log.Fatal(err) }
// Wait for email email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(30*time.Second), vaultsandbox.WithSubjectRegex(regexp.MustCompile(`Test`)), ) if err != nil { log.Fatal(err) }
fmt.Printf("Received: %s\n", email.Subject)
// Clean up if err := inbox.Delete(ctx); err != nil { log.Fatal(err) }
// Delete any other orphaned inboxes deleted, err := client.DeleteAllInboxes(ctx) if err != nil { log.Fatal(err) } fmt.Printf("Cleaned up %d total inboxes\n", deleted)}Next Steps
Section titled “Next Steps”- Inbox API Reference - Learn about inbox methods
- Email API Reference - Work with email objects
- Error Handling - Handle errors gracefully
- Import/Export Guide - Advanced import/export usage