> ## 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.

# Internal currency integration

> Learn how to create external loyalty rules with progress tracking and multiple reward tiers

<head>
  <script type="application/ld+json">
    {JSON.stringify({
            "@context": "https://schema.org",
            "@graph": [
              {
                "@type": "TechArticle",
                "headline": "Internal currency integration",
                "description": "Learn how to create external loyalty rules with progress tracking and multiple reward tiers",
                "author": {"@type": "Organization", "name": "Snag Solutions", "url": "https://www.snagsolutions.io/"},
                "publisher": {"@type": "Organization", "name": "Snag Solutions", "url": "https://www.snagsolutions.io/", "logo": {"@type": "ImageObject", "url": "https://assets.snagsolutions.io/public/docs/snag-logo-dark-no-bg.svg"}},
                "mainEntityOfPage": "https://docs.snagsolutions.io/loyalty/internal-currency-integration"
              },
              {
                "@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": "Advanced workflows", "item": "https://docs.snagsolutions.io/loyalty/managing-user-accounts"},
                  {"@type": "ListItem", "position": 4, "name": "Internal currency integration"}
                ]
              }
            ]
          })}
  </script>
</head>

### Overview

If you have an existing loyalty system, or want to interact with an off-chain points system we allow partners to integrate existing loyalty points to be distributed as a part of the Snag Loyalty Program to be used as your all-in-one destination for points & points management moving forward.

### Configuration

In our self-serve dashboard we will ask for the following:

* Get balance URL

* Update balance URL

* API key

### Authentication

Please include API key authentication on your server. Allow us to pass in the API key as a header

```sql theme={null}
# we will send the following header on all relevant requests
x-api-key: YOUR_API_KEY

```

### Get loyalty point balance

* This endpoint will be called many times from our frontend, please ensure it is performant

* If we query for a wallet address which is not present in your system then please either don't include that wallet in the response array or ensure the balance value is set to `0`.

* For multi-currency setups, please include separate account balance objects in the array for each currency, and map your currency to the loyaltyCurrencyId provided in the snag admin.

```jsx theme={null}
GET <URL can be specified, e.g. https://api.domain.com/api/balances>

Query parameters:
{
  walletAddress: string | string[],  // case-insensitive
  startingAfter?: string // optional, only if pagination is required.
}

// no pagination
Status code: 2**
Response body:
{
  "data": [{
    "id": string // optional, only if pagination is required
    walletAddress: string
    amount: string // important: amount must be a string
    loyaltyCurrencyId: string
  }],
  hasNextPage: boolean // if pagination is required
}

```

### Update loyalty point balance

* This endpoint should process all updates transactionally (all succeed, or all fail), or return a 400 error.

* It is the APIs responsibility to balance check prior to executing the balance updates.

* For multi-currency setups please specify a separate path for each currency.

* Example: if one wallet has insufficient balance, then return a 400 and a proper error message. We will surface the error message to the frontend.

```jsx theme={null}
POST <URL can be specified, e.g. https://api.domain.com/api/balances>

Body parameters:
{
  entries: [
		{
		  walletAddress: string // case-insensitive
		  direction: 'debit' | 'credit'
		  amount: string // important: amount must be string.
		  idempotencyKey: string | undefined // external client responsible for saving only once
		  metadata: Json | undefined
		}
	],
	description: "description of event",
	loyaltyRuleId: uuid | undefined
}

Response:

Success:
Status code: 2**

Failure:
Satus code: 4** or 5**
Response body:
{
  message: string
}


```

### Get loyalty account history

* Returns the list of balance changes for a wallet address

* This endpoint will be called many times from our frontend, so make sure it is performant and can handle the load

```jsx theme={null}

GET <URL can be specified, e.g. https://api.domain.com/api/entries>

Query parameters:
{
  walletAddress: string,  // case-insensitive

  // If passed in then filter by this value
  // return only the most recent per each rule.
	userCompletedLoyaltyRuleId: string | string[],

  // id from previous request, optional, if pagination is required.
  startingAfter?: string

  // number of elements to return
  limit?: int
}

// sorted by createdAt desc
Status code: 2**
Response body:
{
  "data": [{
    "id": string // optional, only if pagination is required
    walletAddress: string
    direction: 'debit' | 'credit'

    // we need this to determine if rule was completed
    idempotencyKey: string | undefined

    metadata: Json | undefined

    loyaltyRuleId: string | undefined
    amount: string // important: amount must be a string
    loyaltyCurrencyId: string
    description: string
    createdAt: datetime
  }],
  hasNextPage: boolean // if pagination is required
}

```

### API Structure & Guidelines for Loyalty Rules

We expect specific standards for an API endpoint that our loyalty rules interact with (e.g. to get off-chain data from your system that somehow impacts rule evaluation and/or rewards).

### Configuration

For our system to be able to call your endpoint(s) during rule execution we ask for the following:

* Endpoint URL

* API key

* Standard pagination & sorting parameters
