Documentation Index
Fetch the complete documentation index at: https://docs.lux-core.io/llms.txt
Use this file to discover all available pages before exploring further.
Go Examples
Complete Go examples for integrating with the LuxCore API using the standard library.LuxCore Client Package
package luxcore
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"math"
"net/http"
"net/url"
"os"
"time"
)
const BaseURL = "https://api.lux-core.io/api/v1"
type Client struct {
APIKey string
HTTPClient *http.Client
BaseURL string
}
type LuxCoreError struct {
Message string
StatusCode int
ErrorCode string
}
func (e *LuxCoreError) Error() string {
return fmt.Sprintf("LuxCore API error (%d): %s", e.StatusCode, e.Message)
}
func NewClient(apiKey string) *Client {
if apiKey == "" {
apiKey = os.Getenv("LUXCORE_API_KEY")
}
return &Client{
APIKey: apiKey,
HTTPClient: &http.Client{Timeout: 30 * time.Second},
BaseURL: BaseURL,
}
}
func (c *Client) request(method, path string, body interface{}, params url.Values) ([]byte, error) {
reqURL := c.BaseURL + path
if params != nil {
reqURL += "?" + params.Encode()
}
var reqBody io.Reader
if body != nil {
jsonBody, err := json.Marshal(body)
if err != nil {
return nil, err
}
reqBody = bytes.NewBuffer(jsonBody)
}
req, err := http.NewRequest(method, reqURL, reqBody)
if err != nil {
return nil, err
}
req.Header.Set("X-API-Key", c.APIKey)
req.Header.Set("Content-Type", "application/json")
resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode >= 400 {
var errResp struct {
Message string `json:"message"`
Error string `json:"error"`
}
json.Unmarshal(respBody, &errResp)
return nil, &LuxCoreError{
Message: errResp.Message,
StatusCode: resp.StatusCode,
ErrorCode: errResp.Error,
}
}
return respBody, nil
}
// Payment types
type PaymentRequest struct {
Amount int64 `json:"amount"`
Currency string `json:"currency"`
Method string `json:"method"`
Type string `json:"type"`
MerchantReference string `json:"merchant_reference"`
Description string `json:"description,omitempty"`
Customer Customer `json:"customer"`
Payout *PayoutDetails `json:"payout,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type Customer struct {
Name string `json:"name"`
Email string `json:"email"`
Phone string `json:"phone,omitempty"`
ExternalID string `json:"external_id,omitempty"`
}
type PayoutDetails struct {
RecipientName string `json:"recipient_name"`
BankAccount string `json:"bank_account"`
BankCode string `json:"bank_code"`
Reference string `json:"reference,omitempty"`
AccountType string `json:"account_type,omitempty"`
BeneficiaryTaxID string `json:"beneficiary_tax_id,omitempty"`
Description string `json:"description,omitempty"`
PayID string `json:"payid,omitempty"`
PayIDType string `json:"payid_type,omitempty"`
}
type Payment struct {
TransactionID string `json:"transaction_id"`
Status string `json:"status"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
Method *string `json:"method"`
Type string `json:"type"`
MerchantReference string `json:"merchant_reference"`
FeeAmount *int64 `json:"fee_amount,omitempty"`
NetAmount *int64 `json:"net_amount,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
ErrorMessage string `json:"error_message,omitempty"`
CreatedAt time.Time `json:"created_at"`
BankDetails *BankDetails `json:"bank_details,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type BankDetails struct {
Amount string `json:"amount"`
Purpose string `json:"purpose"`
Currency string `json:"currency"`
BankName string `json:"bank_name"`
SwiftCode *string `json:"swift_code"`
AccountHolder string `json:"account_holder"`
AccountNumber string `json:"account_number"`
}
type PaymentListResponse struct {
Success bool `json:"success"`
Data []Payment `json:"data"`
Total int `json:"total"`
Pagination *Pagination `json:"pagination,omitempty"`
}
type Pagination struct {
Limit int `json:"limit"`
Offset int `json:"offset"`
TotalPages int `json:"total_pages"`
}
// Payment methods
func (c *Client) CreatePayment(req PaymentRequest) (*Payment, error) {
respBody, err := c.request("POST", "/payments", req, nil)
if err != nil {
return nil, err
}
var payment Payment
if err := json.Unmarshal(respBody, &payment); err != nil {
return nil, err
}
return &payment, nil
}
func (c *Client) GetPayment(paymentID string) (*Payment, error) {
respBody, err := c.request("GET", "/payments/"+paymentID, nil, nil)
if err != nil {
return nil, err
}
var payment Payment
if err := json.Unmarshal(respBody, &payment); err != nil {
return nil, err
}
return &payment, nil
}
func (c *Client) ListPayments(filters map[string]string) (*PaymentListResponse, error) {
params := url.Values{}
for k, v := range filters {
params.Set(k, v)
}
respBody, err := c.request("GET", "/payments", nil, params)
if err != nil {
return nil, err
}
var result PaymentListResponse
if err := json.Unmarshal(respBody, &result); err != nil {
return nil, err
}
return &result, nil
}
func (c *Client) CancelPayment(paymentID string) error {
_, err := c.request("POST", "/payments/"+paymentID+"/cancel", nil, nil)
return err
}
// Balance
type BalanceResponse struct {
Success bool `json:"success"`
MerchantID int `json:"merchant_id"`
Currency string `json:"currency"`
BalanceType string `json:"balance_type"`
BalanceAmount string `json:"balance_amount"`
AvailableAmount string `json:"available_amount"`
FrozenAmount string `json:"frozen_amount"`
NewBalance int `json:"new_balance"`
AvailableBalance int `json:"available_balance"`
}
func (c *Client) GetBalance(currency string) (*BalanceResponse, error) {
params := url.Values{}
if currency != "" {
params.Set("currency", currency)
}
respBody, err := c.request("GET", "/balance", nil, params)
if err != nil {
return nil, err
}
var balance BalanceResponse
if err := json.Unmarshal(respBody, &balance); err != nil {
return nil, err
}
return &balance, nil
}
// Webhook verification
func VerifyWebhookSignature(payload []byte, signature string, timestamp int64, secret string) error {
// Check timestamp (reject if older than 5 minutes)
currentTime := time.Now().Unix()
if math.Abs(float64(currentTime-timestamp)) > 300 {
return fmt.Errorf("webhook timestamp too old")
}
// Calculate expected signature
payloadToSign := fmt.Sprintf("%d.%s", timestamp, string(payload))
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(payloadToSign))
expectedSignature := "hmac_sha256=" + hex.EncodeToString(mac.Sum(nil))
// Compare signatures
if !hmac.Equal([]byte(signature), []byte(expectedSignature)) {
return fmt.Errorf("invalid webhook signature")
}
return nil
}
Usage Examples
Create a Deposit Payment
package main
import (
"fmt"
"log"
"time"
"your-project/luxcore"
)
func main() {
client := luxcore.NewClient("")
payment, err := client.CreatePayment(luxcore.PaymentRequest{
Amount: 100000, // $1,000.00 MXN (in centavos)
Currency: "MXN",
Method: "spei",
Type: "deposit",
MerchantReference: fmt.Sprintf("order_%d", time.Now().Unix()),
Customer: luxcore.Customer{
Name: "Juan Perez",
Email: "juan@example.com",
Phone: "+525551234567",
},
Metadata: map[string]interface{}{
"order_id": "12345",
"source": "web",
},
})
if err != nil {
log.Fatalf("Failed to create payment: %v", err)
}
fmt.Printf("Payment created: %s\n", payment.TransactionID)
fmt.Printf("Status: %s\n", payment.Status)
if payment.BankDetails != nil {
fmt.Printf("Bank: %s\n", payment.BankDetails.BankName)
fmt.Printf("Account: %s\n", payment.BankDetails.AccountNumber)
fmt.Printf("Holder: %s\n", payment.BankDetails.AccountHolder)
}
}
Create a Withdrawal (Payout)
payout, err := client.CreatePayment(luxcore.PaymentRequest{
Amount: 50000,
Currency: "MXN",
Method: "spei",
Type: "withdrawal",
MerchantReference: fmt.Sprintf("payout_%d", time.Now().Unix()),
Customer: luxcore.Customer{
Name: "Finance Team",
Email: "finance@company.com",
},
Payout: &luxcore.PayoutDetails{
RecipientName: "Maria Garcia",
BankAccount: "012345678901234567",
BankCode: "002",
Reference: "PAYOUT-001",
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Payout created: %s\n", payout.TransactionID)
Webhook Handler (net/http)
package main
import (
"encoding/json"
"io"
"log"
"net/http"
"os"
"strconv"
"your-project/luxcore"
)
var webhookSecret = os.Getenv("LUXCORE_WEBHOOK_SECRET")
// WebhookPayload uses the envelope structure
type WebhookPayload struct {
ID string `json:"id"`
CreatedAt string `json:"created_at"`
MerchantID int `json:"merchant_id"`
Data WebhookData `json:"data"`
}
type WebhookData struct {
Payment json.RawMessage `json:"payment"`
}
func webhookHandler(w http.ResponseWriter, r *http.Request) {
// Read body
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read body", http.StatusBadRequest)
return
}
// Get headers
signature := r.Header.Get("X-Webhook-Signature")
timestampStr := r.Header.Get("X-Webhook-Timestamp")
timestamp, _ := strconv.ParseInt(timestampStr, 10, 64)
event := r.Header.Get("X-Webhook-Event")
webhookId := r.Header.Get("X-Webhook-Id")
// Verify signature
if err := luxcore.VerifyWebhookSignature(body, signature, timestamp, webhookSecret); err != nil {
log.Printf("Webhook verification failed: %v", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Parse payload (envelope structure)
var payload WebhookPayload
if err := json.Unmarshal(body, &payload); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}
// Process event from header
log.Printf("Received webhook event: %s (id: %s)", event, webhookId)
switch event {
case "payment.completed":
log.Println("Payment completed!")
// Handle completed payment
case "payment.failed":
log.Println("Payment failed!")
// Handle failed payment
case "payment.cancelled":
log.Println("Payment cancelled!")
// Handle cancelled payment
default:
log.Printf("Unhandled event: %s", event)
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]bool{"received": true})
}
func main() {
http.HandleFunc("/webhooks/luxcore", webhookHandler)
log.Println("Starting webhook server on :3000")
log.Fatal(http.ListenAndServe(":3000", nil))
}
Error Handling
payment, err := client.CreatePayment(req)
if err != nil {
if luxErr, ok := err.(*luxcore.LuxCoreError); ok {
switch luxErr.StatusCode {
case 401:
log.Println("Invalid API key")
case 400:
log.Printf("Validation error: %s", luxErr.Message)
case 429:
log.Println("Rate limited - waiting to retry")
time.Sleep(60 * time.Second)
// Retry...
case 500, 503:
log.Println("Server error - retrying")
time.Sleep(5 * time.Second)
// Retry...
default:
log.Printf("API error (%d): %s", luxErr.StatusCode, luxErr.Message)
}
} else {
log.Printf("Network error: %v", err)
}
return
}
Complete Example with Gin
package main
import (
"log"
"net/http"
"os"
"github.com/gin-gonic/gin"
"your-project/luxcore"
)
var client *luxcore.Client
func main() {
client = luxcore.NewClient(os.Getenv("LUXCORE_API_KEY"))
r := gin.Default()
// Create payment endpoint
r.POST("/api/payments", createPaymentHandler)
// Webhook endpoint
r.POST("/webhooks/luxcore", webhookHandler)
r.Run(":8080")
}
func createPaymentHandler(c *gin.Context) {
var req struct {
Amount int64 `json:"amount" binding:"required"`
OrderID string `json:"order_id" binding:"required"`
Customer struct {
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required"`
} `json:"customer" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
payment, err := client.CreatePayment(luxcore.PaymentRequest{
Amount: req.Amount,
Currency: "MXN",
Method: "spei",
Type: "deposit",
MerchantReference: req.OrderID,
Customer: luxcore.Customer{
Name: req.Customer.Name,
Email: req.Customer.Email,
},
})
if err != nil {
if luxErr, ok := err.(*luxcore.LuxCoreError); ok {
c.JSON(luxErr.StatusCode, gin.H{"error": luxErr.Message})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": "Payment creation failed"})
return
}
c.JSON(http.StatusOK, gin.H{
"payment_id": payment.TransactionID,
"status": payment.Status,
"bank_details": payment.BankDetails,
})
}
