> ## Documentation Index
> Fetch the complete documentation index at: https://docs.snagsolutions.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Checking Rule Completion Status

> Learn how to verify/check if a user has completed specific loyalty rules and received rewards

<head>
  <script type="application/ld+json">
    {JSON.stringify({
            "@context": "https://schema.org",
            "@type": "BreadcrumbList",
            "itemListElement": [
              {"@type": "ListItem", "position": 1, "name": "Home", "item": "https://docs.snagsolutions.io/welcome"},
              {"@type": "ListItem", "position": 2, "name": "Loyalty", "item": "https://docs.snagsolutions.io/loyalty/loyalty-overview"},
              {"@type": "ListItem", "position": 3, "name": "Development", "item": "https://docs.snagsolutions.io/loyalty/development/getting-started"},
              {"@type": "ListItem", "position": 4, "name": "Check rule completion status"}
            ]
          })}
  </script>
</head>

## Overview

When implementing loyalty rules in your application, you often need to know whether a user has already completed a rule and received rewards. This information is useful for:

* Displaying completed rules differently in your UI
* Preventing users from attempting to complete already-completed rules
* Building custom reward history displays

Snag provides a straightforward way to check rule completion and reward status using the transaction entries endpoint.

## Using Transaction Entries to Verify Rule Completion

The transaction entries API endpoint allows you to check whether a user has completed specific rules by looking for reward transactions associated with those rules.

### API Endpoint

GET /api/loyalty/transaction\_entries

### Required Parameters

| Parameter                    | Type      | Description                                       |
| ---------------------------- | --------- | ------------------------------------------------- |
| `userCompletedLoyaltyRuleId` | string\[] | Array of loyalty rule IDs to check for completion |
| `userId`                     | string    | The ID of the user to check                       |

### Key Behavior

**Important:** When using the `userCompletedLoyaltyRuleId` parameter, the endpoint will return **only the latest transaction entry** for each specified rule ID. This optimized behavior makes it ideal for quickly checking completion status without filtering through multiple entries per rule.

### Example Request

```javascript theme={null}
const fetchRuleCompletionStatus = async (userId, ruleIds) => {
  const queryParams = new URLSearchParams({
    userId: userId,
  });
  
  // Add each rule ID to the query parameters
  ruleIds.forEach(ruleId => {
    queryParams.append('userCompletedLoyaltyRuleId', ruleId);
  });
  
  const response = await fetch(
    `${API_BASE_URL}/api/loyalty/transaction_entries?${queryParams.toString()}`,
    {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json'
      }
    }
  );
  
  return await response.json();
};
```

## Interpreting Results

The response contains an array of transaction entries, each representing the most recent reward transaction for a completed rule:

1. **Rule is completed**: If a transaction entry exists for a specific rule ID, the user has completed that rule and received rewards.

2. **Rule is not completed**: If no transaction entry exists for a rule ID, the user has not completed that rule or has not received rewards for it.

3. **Latest entries only**: Since the `userCompletedLoyaltyRuleId` parameter is used, the endpoint returns only the latest entry per rule, you'll always see the most recent completion status, which is particularly useful for rules that can be completed multiple times (like daily check-ins).

## Implementation Example

Here's a complete example showing how to check if a user has completed specific rules and display the appropriate UI:

```javascript theme={null}
// Check if user has completed specific rules
async function checkRuleCompletionStatus(userId, ruleIds) {
  try {
    const queryParams = new URLSearchParams({ userId });
    ruleIds.forEach(ruleId => {
      queryParams.append('userCompletedLoyaltyRuleId', ruleId);
    });
    
    const response = await fetch(
      `${API_BASE_URL}/api/loyalty/transaction_entries?${queryParams.toString()}`,
      {
        headers: {
          'Authorization': `Bearer ${API_KEY}`,
          'Content-Type': 'application/json'
        }
      }
    );
    
    const { data } = await response.json();
    
    // Create a map of rule IDs to completion status
    const completionStatus = {};
    ruleIds.forEach(ruleId => {
      completionStatus[ruleId] = false;
    });
    
    // Update completion status based on transaction entries
    // Each entry is guaranteed to be the latest for that rule
    data.forEach(entry => {
      if (entry.userCompletedLoyaltyRuleId && 
          ruleIds.includes(entry.userCompletedLoyaltyRuleId)) {
        completionStatus[entry.userCompletedLoyaltyRuleId] = true;
      }
    });
    
    return completionStatus;
  } catch (error) {
    console.error('Error checking rule completion status:', error);
    throw error;
  }
}

// Example usage in a component
function QuestsComponent({ userId, quests }) {
  const [completionStatus, setCompletionStatus] = useState({});
  const [isLoading, setIsLoading] = useState(true);
  
  useEffect(() => {
    const ruleIds = quests.map(quest => quest.ruleId);
    
    checkRuleCompletionStatus(userId, ruleIds)
      .then(status => {
        setCompletionStatus(status);
        setIsLoading(false);
      })
      .catch(() => {
        setIsLoading(false);
      });
  }, [userId, quests]);
  
  if (isLoading) {
    return <div>Loading quests...</div>;
  }
  
  return (
    <div className="quests-container">
      {quests.map(quest => (
        <QuestItem 
          key={quest.ruleId}
          quest={quest}
          isCompleted={completionStatus[quest.ruleId]}
        />
      ))}
    </div>
  );
}
```

## Related Documentation

For more information on handling rule completion, refer to:

* [Verifying Rule Completion](/loyalty/verifying-rule-completion) - Details on the complete process for submitting and verifying rule completion
* [API Reference: Get Loyalty Transaction Entries](https://docs.snagsolutions.io/api-reference/loyalty/get-loyalty-transaction-entries) - Full API documentation for the transaction entries endpoint

## Limitations and Considerations

* For some rule types (like cadence-based rules), completion status may update on a schedule rather than immediately
* Using the `userCompletedLoyaltyRuleId` parameter, the endpoint returns only the latest entry per rule, making it efficient for checking current completion status
* Cache results where appropriate to reduce API calls in your application
