Skip to main content
The Loyalty API allows you to search and track loyalty events in a Square loyalty program. Each change in a buyer’s loyalty account point balance is recorded as an event that you can query and analyze.

Client Initialization

Access the Loyalty client through the main Square client:
import (
    "context"
    "github.com/square/square-go-sdk/v3"
)

client := square.NewClient(
    square.WithAccessToken("YOUR_ACCESS_TOKEN"),
)

// Access the Loyalty API
loyaltyClient := client.Loyalty

Core Methods

SearchEvents

Search for loyalty events using various filters. Events are sorted by created_at in descending order.
request := &square.SearchLoyaltyEventsRequest{
    Query: &square.LoyaltyEventQuery{
        Filter: &square.LoyaltyEventFilter{
            OrderFilter: &square.LoyaltyEventOrderFilter{
                OrderID: "PyATxhYLfsMqpVkcKJITPydgEYfZY",
            },
        },
    },
    Limit: square.Int(30),
}

response, err := client.Loyalty.SearchEvents(context.TODO(), request)
if err != nil {
    // Handle error
}

for _, event := range response.Events {
    fmt.Printf("Event: %s, Type: %s\n", 
        *event.ID, 
        event.Type)
}
query
*square.LoyaltyEventQuery
Query object containing filter and sort criteria.
limit
*int
Maximum number of events to return per page. Default is 30.
cursor
*string
Pagination cursor from a previous call to retrieve the next set of results.
events
[]*square.LoyaltyEvent
Array of loyalty events matching the search criteria.
cursor
*string
Pagination cursor for the next page of results (if available).
errors
[]*square.Error
Any errors that occurred during the request.

Query Filters

LoyaltyEventFilter

The main filter object supports multiple filter types that are combined with logical AND.
loyaltyAccountFilter
*square.LoyaltyEventLoyaltyAccountFilter
Filter events by loyalty account ID.
typeFilter
*square.LoyaltyEventTypeFilter
Filter by event types (combined with logical OR).
dateTimeFilter
*square.LoyaltyEventDateTimeFilter
Filter by creation date range (start is inclusive, end is exclusive).
locationFilter
*square.LoyaltyEventLocationFilter
Filter by location IDs (combined with logical OR).
orderFilter
*square.LoyaltyEventOrderFilter
Filter by order ID.

Event Types

Loyalty events track different types of point balance changes:
  • ACCUMULATE_POINTS - Points earned from a purchase
  • EXPIRE_POINTS - Points expired due to time limit
  • ADJUST_POINTS - Manual point adjustment by merchant
  • REDEEM_REWARD - Points redeemed for a reward

Complete Example

package main

import (
    "context"
    "fmt"
    "log"
    "time"
    
    "github.com/square/square-go-sdk/v3"
)

func main() {
    client := square.NewClient(
        square.WithAccessToken("YOUR_ACCESS_TOKEN"),
    )

    // Search for all events for a specific loyalty account
    // in the last 30 days
    thirtyDaysAgo := time.Now().AddDate(0, 0, -30)
    
    request := &square.SearchLoyaltyEventsRequest{
        Query: &square.LoyaltyEventQuery{
            Filter: &square.LoyaltyEventFilter{
                LoyaltyAccountFilter: &square.LoyaltyEventLoyaltyAccountFilter{
                    LoyaltyAccountID: "LOYALTY_ACCOUNT_ID",
                },
                DateTimeFilter: &square.LoyaltyEventDateTimeFilter{
                    CreatedAt: &square.TimeRange{
                        StartAt: square.String(
                            thirtyDaysAgo.Format(time.RFC3339),
                        ),
                    },
                },
            },
        },
        Limit: square.Int(100),
    }

    response, err := client.Loyalty.SearchEvents(
        context.TODO(), 
        request,
    )
    if err != nil {
        log.Fatal(err)
    }

    // Process events
    totalPointsEarned := 0
    totalPointsRedeemed := 0
    
    for _, event := range response.Events {
        switch event.Type {
        case square.LoyaltyEventTypeAccumulatePoints:
            if event.AccumulatePoints != nil {
                totalPointsEarned += *event.AccumulatePoints.Points
            }
        case square.LoyaltyEventTypeRedeemReward:
            if event.RedeemReward != nil {
                totalPointsRedeemed += *event.RedeemReward.Points
            }
        }
    }

    fmt.Printf("Points earned: %d\n", totalPointsEarned)
    fmt.Printf("Points redeemed: %d\n", totalPointsRedeemed)
    fmt.Printf("Net points: %d\n", 
        totalPointsEarned - totalPointsRedeemed)
}

Types

LoyaltyEvent

Represents a single loyalty event.
type LoyaltyEvent struct {
    ID                    *string
    Type                  LoyaltyEventType
    CreatedAt             *string
    AccumulatePoints      *LoyaltyEventAccumulatePoints
    CreateReward          *LoyaltyEventCreateReward
    RedeemReward          *LoyaltyEventRedeemReward
    DeleteReward          *LoyaltyEventDeleteReward
    AdjustPoints          *LoyaltyEventAdjustPoints
    LoyaltyAccountID      string
    LocationID            *string
    Source                LoyaltyEventSource
    ExpirePoints          *LoyaltyEventExpirePoints
    OtherEvent            *LoyaltyEventOther
    AccumulatePromotionPoints *LoyaltyEventAccumulatePromotionPoints
}

LoyaltyEventQuery

Query structure for searching events.
type LoyaltyEventQuery struct {
    Filter *LoyaltyEventFilter
}

type LoyaltyEventFilter struct {
    LoyaltyAccountFilter *LoyaltyEventLoyaltyAccountFilter
    TypeFilter           *LoyaltyEventTypeFilter
    DateTimeFilter       *LoyaltyEventDateTimeFilter
    LocationFilter       *LoyaltyEventLocationFilter
    OrderFilter          *LoyaltyEventOrderFilter
}

Use Cases

Search loyalty events by account to display a customer’s complete loyalty history, including points earned, redeemed, and expired.
Filter events by location to analyze which stores generate the most loyalty activity and engagement.
Use type filters to track promotion-specific point accumulation and measure campaign effectiveness.
Filter by order ID to see all loyalty events associated with a specific purchase.
Use date filters to generate reports on loyalty activity over specific time periods.

Best Practices

Combine Multiple Filters

Use multiple filters together (e.g., location + date range + event type) to create precise queries and reduce result set size.

Pagination

Always handle pagination using the cursor field for large result sets to ensure you retrieve all matching events.

Event Timestamps

Events are sorted by created_at in descending order (newest first). Use this for chronological analysis.

Logical Operators

Remember: Multiple filters use AND logic, but arrays within filters (like location IDs) use OR logic.

Build docs developers (and LLMs) love