# Snowdrop Enrichment MRS

Snowdrop Enrichment API (MRS - Merchant Reconciliation System) guide. Here you will find detailed explanations of how our API works, the required data, and best practices for optimal results.

### Overview

* The Snowdrop MRS API enriches banking data with information about the merchants associated with each transaction. It helps to make “messy” transaction data clear and easily understood.
* Send the raw transaction data to our API, and it will return the merchant name, logo, its postal address, website, category, and other information.

{% hint style="success" %}
Take your Payment Data to the next level. Get in touch with our team.

[**Try our demo**](https://snowdropsolutions.com/try-our-demo/)
{% endhint %}

### API Specification

Want to skip the guides and go directly to the tech specs? See [OpenAPI Docs](/openapi-docs).

### Data Flow

<figure><img src="/files/LGzQ59xJdMk8n7RKFESb" alt=""><figcaption></figcaption></figure>


# OpenAPI Docs

OpenAPI Technical Documentation for MRS.

{% hint style="info" %}
For guides on how to actually implement MRS, see [Quick Start](/implementation-guides/quick-start).
{% endhint %}

### Full OpenAPI spec:

{% file src="/files/D3J1MINa2rbkF4iznALj" %}


# Enrich one transaction - GET

{% openapi src="/files/jfRNjrxvpEmpbLxymQQO" path="/api/v3/merchant" method="get" %}
[mrsapi.yaml](https://3426765591-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3PkUQNFQ8zz26qyVygsV%2Fuploads%2Fgit-blob-5b8750f5ac5786cd4813a830d75c43fadaad3d97%2Fmrsapi.yaml?alt=media)
{% endopenapi %}


# Enrich multiple transactions - POST

{% openapi src="/files/jfRNjrxvpEmpbLxymQQO" path="/api/v3/merchant/list" method="post" %}
[mrsapi.yaml](https://3426765591-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3PkUQNFQ8zz26qyVygsV%2Fuploads%2Fgit-blob-5b8750f5ac5786cd4813a830d75c43fadaad3d97%2Fmrsapi.yaml?alt=media)
{% endopenapi %}


# Implementation Guides


# Quick Start

{% hint style="info" %}
We recommend you read the full guides below. But if you prefer, you can just skip to the [OpenAPI Docs](/openapi-docs) for the technical specification.
{% endhint %}

Snowdrop Solutions' Merchant Reconciliation System (MRS) is a REST API that is simple and easy to implement. To make your first API request, you can use the [OpenAPI documentation](/openapi-docs), or you can make a request in the language of your choice, below.

{% hint style="info" %}
Note: You will need a valid ***API Key*** and know your ***Regional Domain*** to make an MRS request. Please contact us if you do not have these. (See [FAQ](/faq)).
{% endhint %}

To start, we will call the simple `/api/v3/merchant`endpoint, using a GET request.&#x20;

{% tabs %}
{% tab title="cURL" %}
`curl --request GET`\
`--url 'https://regional-snowdrop-domain-goes-here.com/api/v3/merchant?merchant_name=mcdonalds&type=restrictive&location=london&country=GBR'`\
`--header 'X-Api-Key:`` `**`<YOUR-API-KEY>`**`'`
{% endtab %}

{% tab title="Python" %}
`import http.client`

`conn = http.client.HTTPSConnection("`**`regional-snowdrop-domain-goes-here.com`**`")`

`payload = ""`

`headers = { 'X-Api-Key': "`**`<YOUR-API-KEY>`**`" }`

`conn.request("GET", "/api/v3/merchant?merchant_name=mcdonalds&type=restrictive&location=london&country=GBR", payload, headers)`

`res = conn.getresponse() data = res.read()`

`print(data.decode("utf-8"))`
{% endtab %}

{% tab title="C#" %}
`var client = new RestClient("https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/merchant?merchant_name=mcdonalds&type=restrictive&location=london&country=GBR");`&#x20;

`var request = new RestRequest(Method.GET);`

`request.AddHeader("X-Api-Key", "`**`<YOUR-API-KEY>`**`");`&#x20;

`IRestResponse response = client.Execute(request);`
{% endtab %}

{% tab title="Javascript" %}
`const data = null;`

`const xhr = new XMLHttpRequest();`

`xhr.withCredentials = true;`

`xhr.addEventListener("readystatechange", function () {`

&#x20;   `if (this.readyState === this.DONE) {`

&#x20;       `console.log(this.responseText);`&#x20;

&#x20;   `}`&#x20;

`});`

`xhr.open("GET", "https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/merchant?merchant_name=mcdonalds&type=restrictive&location=london&country=GBR");`

`xhr.setRequestHeader("X-Api-Key", "`**`<YOUR-API-KEY>`**`");`

`xhr.send(data);`
{% endtab %}

{% tab title="Java" %}
`HttpResponse response = Unirest.get("https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/merchant?merchant_name=mcdonalds&type=restrictive&location=london&country=GBR") .header("X-Api-Key", "`**`<YOUR-API-KEY>`**`") .asString();`
{% endtab %}
{% endtabs %}

*Note: the `type=restrictive` part refers to the **type** of request. You don't have to worry about this for now, we will cover restrictive vs extended later.*

The returned response contains the enriched transaction in JSON format:

```
[
	{
		"name": "McDonald's",
		"website": "https://www.mcdonalds.com",
		"address": "",
		"img": "https://storage.googleapis.com/production-mrs-tm-logos/6273ea24bb09494554c95b90_2x.png",
		"logoImg": "https://storage.googleapis.com/production-mrs-tm-logos/6273ea24bb09494554c95b90_2x.png",
		"categoryImg": "https://storage.googleapis.com/production-mrs-category-logos/default/food_2x.png",
		"logoScore": 1,
		"category": "Eating out",
		"categories": [
			"restaurant"
		],
		"isClearResponse": false
	}
]
```

For more on the meaning of these fields, consult the [OpenAPI Docs](/openapi-docs).

Having problems? Consult [Troubleshooting](/troubleshooting) or [FAQ](/faq).


# Data. How to get the best results

How to get the best results from MRS and keep your users happy.

#### Data Richness

* The quality and amount of transaction data has a **big impact** on the accuracy of results. The data available may vary at different stages of processing (e.g. Pending, Pre-authorised, Authorised but not posted)
* You should attempt to include as many input fields as possible in your requests to MRS. See the [OpenAPI Docs](/openapi-docs) for the fields we support. All are valuable, but the most valuable are, in order:
  * `country`
  * `mcc` (see [Merchant Category Codes](/basic-concepts/merchant-category-codes))
  * `city`
  * `location`
  * (This is in addition to the `merchant_name` and `type` parameters, which are both mandatory).

#### Data Notes

* MRS requires information about the merchant involved in the transaction.
* MRS does not process end-user personal data
* The collected data may be “messy” and not all fields may be available for all transactions.&#x20;
* Often only one single field with location is available. Also, the merchant description may include location information.&#x20;


# Examples

Examples of fields to send in your requests to MRS.

<table><thead><tr><th>merchant</th><th>location</th><th>city</th><th>country</th><th data-type="number">mcc</th></tr></thead><tbody><tr><td>mcdonald's</td><td>paddington stn</td><td>london</td><td>GB</td><td>5812</td></tr><tr><td>amzn mktplace</td><td>luxembourg</td><td></td><td>LUX</td><td>5999</td></tr><tr><td>cindys fashion     slough  gb</td><td></td><td></td><td>GBR</td><td>5621</td></tr></tbody></table>


# Recommended UX

Recommended User Experience for your app.

Recommendations for a typical banking application to optimize cost and efficiency:

1. Use a [List request](/basic-concepts/list-request) (type `restrictive`)  to fill the initial list of transactions using the cleaned up name and logo, and optionally also include categorisation and category icon in this view.
2. When a user wants more information about a transaction then they can press/click on it. At this point a individual call (see [Quick Start](/implementation-guides/quick-start)) of type `extended` is made and the user will navigate to the Detail View.

See also [Restrictive vs Extended](/basic-concepts/restrictive-vs-extended).

See also [Additional UX Considerations](/implementation-guides/additional-ux-considerations).

<figure><img src="/files/DiJXpS9k7vDomqadP1Kz" alt=""><figcaption></figcaption></figure>


# Additional UX Considerations

* Consider providing the **original merchant description** and perhaps other transaction info at the bottom of the Detail View page. This can be useful for your customer service function, should they be contacted about a transaction and they do not have access to the enriched information.
* The transaction categories can be used to present summarised spending to your users (see [Additional UX Considerations](/implementation-guides/additional-ux-considerations)).
* Consider allowing your users the ability to re-categorise specific transactions themselves.
* You may also wish to summarise transaction info in other ways:
  * List the merchants that your users spend the most money with.
  * You can summarise recent spending on a map.

#### Examples

<figure><img src="https://lh7-us.googleusercontent.com/1QQcPVSE3WbvmMH85vtKjki3gsFP9pc_SvZHtTBfPnU3OOkOQLg95EdmhOoBy-aiCAXPeXdy-ZXVCjTAvEtVpFlZW4BwL80IngK5qHi3hgsL0rQDxP5P96XZTacPQsoqUHDhqDc8JbdyI9MtQreppuQSLQ=s2048" alt="" width="375"><figcaption><p>Transaction Categorization</p></figcaption></figure>

<figure><img src="https://lh7-us.googleusercontent.com/ZR17qd3eUwkYfFEIczeNh5JSkycZKGwOJ8RLsb9Dn7SlSU34mm5TviF-PJLcvS4qjevfm0pyn3SIR3CtnrtNd5TDYRMiAjB56D2U_c8_1Hkucdy308P8VX0YP4HH74qE8tVeRruaZyl8RbSImPlvhiDpWQ=s2048" alt="" width="375"><figcaption><p>Top Merchant</p></figcaption></figure>

<figure><img src="https://lh7-us.googleusercontent.com/VsgJQUOvoX5SRrCuvSsYHp50WbEyWS6K2ae2WQvPG4tZF7Nd7rF3-mG65DYE3IS4HPo7gW8n1lKjZPbgzyiYdYm6jEYId5nuBRA-CtSRLk7b2L4YfqHFyydoytH3Y2bcAvZ4OZwd0mSUGnGtu0l4rrcBYQ=s2048" alt="" width="375"><figcaption><p>Recent spends map</p></figcaption></figure>

<br>

<br>

<br>


# Basic Concepts


# List request

Sending multiple transactions in one request

{% hint style="info" %}
Please read the [Quick Start](/implementation-guides/quick-start) guide first to understand the basics of MRS before attempting this.
{% endhint %}

#### Overview

After you've made a simple GET request, you can use a List request to send *multiple transactions at once* in a single request. This is typically used for the List view of transactions in Bank apps.

Start by constructing a JSON object containing transactions you wish to enrich. Send that JSON object in a POST request to the `/api/v3/merchant/list` endpoint, and MRS will return JSON containing the merchants found for those transactions.

#### Request Size

* List requests are recommended to contain **25 or less** elements. Requests with higher amounts can be supported. Very long lists might have an impact on response times. *Please contact us with any questions on this.*

#### Transaction Ids

* Each transaction must have a **unique** id property, which is used to identify the transaction in the response.
* The id only has to be unique for this request, and can be any string. You could use the numeric index of the transaction in the transaction array, generate a unique UUID then and there for each transaction, etc.&#x20;
* This id is required when submitting [Crowdsourcing](/advanced-use-cases/crowdsourcing)  reports, as it is used to identify the transaction within the request. The other parameters for each transaction are the same as the individual `/v3/merchant` GET request (see [Quick Start](/implementation-guides/quick-start)).

#### Type

* Typically it's recommended to use `restrictive` calls for List requests. See [Restrictive vs Extended](/basic-concepts/restrictive-vs-extended)

#### Example Code

{% tabs %}
{% tab title="cURL" %}
`curl --request POST`\
`--url https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/merchant/list`\
`--header 'Content-Type: application/json'`\
`--header 'X-Api-Key:`` `**`<YOUR-API-KEY>`**`'`\
`--data '{ "type": "restrictive", "transactions": [ { "merchant_name": "mcdonalds", "location": "london", "country": "GBR", "id": "1" }, { "merchant_name": "starbucks", "location": "Manchester", "id": "2", "country": "GBR" }, { "merchant_name": "ikea", "location": "Malmo", "id": "3", "country": "GBR" } ] }'`
{% endtab %}

{% tab title="Python" %}
`import http.client`

`conn = http.client.HTTPSConnection("`**`regional-snowdrop-domain-goes-here.com`**`")`

`payload = "{"type": "restrictive","transactions": [{"merchant_name": "mcdonalds","location": "london","country": "GBR","id": "1"},{"merchant_name": "starbucks","location": "Manchester","id": "2","country": "GBR"},{"merchant_name": "ikea","location": "Malmo","id": "3","country": "GBR"}]}"`

`headers = { 'Content-Type': "application/json", 'x-api-key': "`**`<YOUR-API-KEY>`**`" }`

`conn.request("POST", "/api/v3/merchant/list", payload, headers)`

`res = conn.getresponse() data = res.read()`

`print(data.decode("utf-8"))`
{% endtab %}

{% tab title="C#" %}
`var client = new RestClient("https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/merchant/list");`

`var request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "application/json");`

`request.AddHeader("x-api-key", "`**`<YOUR-API-KEY>`**`");`&#x20;

`request.AddParameter("application/json", "{"type": "restrictive","transactions": [{"merchant_name": "mcdonalds","location": "london","country": "GBR","id": "1"},{"merchant_name": "starbucks","location": "Manchester","id": "2","country": "GBR"},{"merchant_name": "ikea","location": "Malmo","id": "3","country": "GBR"}]}", ParameterType.RequestBody);`

`IRestResponse response = client.Execute(request);`
{% endtab %}

{% tab title="Javascript" %}
`const data = JSON.stringify({ "type": "restrictive", "transactions": [ { "merchant_name": "mcdonalds", "location": "london", "country": "GBR", "id": "1" }, { "merchant_name": "starbucks", "location": "Manchester", "id": "2", "country": "GBR" }, { "merchant_name": "ikea", "location": "Malmo", "id": "3", "country": "GBR" } ] });`

`const xhr = new XMLHttpRequest(); xhr.withCredentials = true;`

`xhr.addEventListener("readystatechange", function () { if (this.readyState === this.DONE) { console.log(this.responseText); } });`

`xhr.open("POST", "https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/merchant/list");`

`xhr.setRequestHeader("Content-Type", "application/json"); xhr.setRequestHeader("x-api-key", "`**`<YOUR-API-KEY>`**`");`

`xhr.send(data);`
{% endtab %}

{% tab title="Java" %}
`HttpResponse response = Unirest.post("https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/merchant/list") .header("Content-Type", "application/json") .header("x-api-key", "`**`<YOUR-API-KEY>`**`") .body("{"type": "restrictive","transactions": [{"merchant_name": "mcdonalds","location": "london","country": "GBR","id": "1"},{"merchant_name": "starbucks","location": "Manchester","id": "2","country": "GBR"},{"merchant_name": "ikea","location": "Malmo","id": "3","country": "GBR"}]") .asString();`
{% endtab %}
{% endtabs %}

The returned response contains the enriched transactions in JSON format:

```
{
	"1": [
		{
			"name": "McDonald's",
			"website": "https://www.mcdonalds.com",
			"address": "",
			"img": "https://storage.googleapis.com/production-mrs-tm-logos/6273ea24bb09494554c95b90_2x.png",
			"logoImg": "https://storage.googleapis.com/production-mrs-tm-logos/6273ea24bb09494554c95b90_2x.png",
			"categoryImg": "https://storage.googleapis.com/production-mrs-category-logos/6266950140122693b803c7e0/eatingout_2x.png",
			"logoScore": 1,
			"category": "Eating Out",
			"categories": [
				"restaurant"
			],
			"isClearResponse": false,
			"cachePolicy": {
				"name": "MRS",
				"website": "MRS",
				"address": "MRS",
				"img": "MRS",
				"logoImg": "MRS",
				"categoryImg": "MRS",
				"logoScore": "MRS",
				"category": "MRS",
				"categories": "MRS",
				"isClearResponse": "MRS"
			}
		}
	],
	"2": [
		{
			"name": "Starbucks",
			"website": "https://www.starbucks.com",
			"address": "",
			"img": "https://storage.googleapis.com/production-mrs-tm-logos/6273e431bb09494554c93079_2x.png",
			"logoImg": "https://storage.googleapis.com/production-mrs-tm-logos/6273e431bb09494554c93079_2x.png",
			"categoryImg": "https://storage.googleapis.com/production-mrs-category-logos/6266950140122693b803c7e0/eatingout_2x.png",
			"logoScore": 1,
			"category": "Eating Out",
			"categories": [
				"cafe"
			],
			"isClearResponse": false,
			"cachePolicy": {
				"name": "MRS",
				"website": "MRS",
				"address": "MRS",
				"img": "MRS",
				"logoImg": "MRS",
				"categoryImg": "MRS",
				"logoScore": "MRS",
				"category": "MRS",
				"categories": "MRS",
				"isClearResponse": "MRS"
			}
		}
	],
	"3": [
		{
			"name": "IKEA",
			"website": "https://www.ikea.com",
			"address": "",
			"img": "https://storage.googleapis.com/production-mrs-tm-logos/6273e4c1bb09494554c934c8_2x.png",
			"logoImg": "https://storage.googleapis.com/production-mrs-tm-logos/6273e4c1bb09494554c934c8_2x.png",
			"categoryImg": "https://storage.googleapis.com/production-mrs-category-logos/6266950140122693b803c7e0/shopping_2x.png",
			"logoScore": 1,
			"category": "Shopping",
			"categories": [
				"furniture_store"
			],
			"isClearResponse": false,
			"cachePolicy": {
				"name": "MRS",
				"website": "MRS",
				"address": "MRS",
				"img": "MRS",
				"logoImg": "MRS",
				"categoryImg": "MRS",
				"logoScore": "MRS",
				"category": "MRS",
				"categories": "MRS",
				"isClearResponse": "MRS"
			}
		}
	]
}
```

This is a JSON object containing one property per transaction sent.

The keys of this object are the ID that was provided, previously passed in as the `id` property in each transaction array element.&#x20;

For more on the meaning of these fields, consult the  [OpenAPI Docs](/openapi-docs) .

Remember, the example above is simple, but you should add as many fields as you can for the best results. See [Data. How to get the best results](/implementation-guides/data.-how-to-get-the-best-results).

Having problems? Consult [Troubleshooting](/troubleshooting) or [FAQ](/faq).


# Restrictive vs Extended

Exploring MRS request types.

There are two different types of requests you can make to MRS:

* `restrictive`
* `extended`

You specify which type you want with the `type` parameter.

### Restrictive&#x20;

The Restrictive Call is used to populate a statement view of transactions.

Its main purpose is to return merchant names and logos.

Characteristics of the Restrictive call

* Does not rely on the Google Maps Platform APIs.
* The caching rules are determined by Snowdrop.
* Match rates will typically be lower as compared to the Extended call.
* Returns what is needed to populate a statement view of transactions.

#### Example UX for Restrictive calls:

![](https://lh7-us.googleusercontent.com/VtYAW9I3XRiYrvmyDmjcMRNVqJ5exk0qZgsH7z3jv-qSGiuFEsAvcU5QzJLzJsB9LPngIe4DTY2fcihETjf7FTV6JoF6IbsMv43UMhM1UF_pjCE_ElvbwVqTD63uD4wbLGE9DwUWhcMdjDqD9M5L06-K=s2048)

#### &#x20;**Information returned by a Restrictive call:**

| name                                                                     | The merchant name.                                                                                                                                                                                                                                                           |
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| website                                                                  | The website for the merchant (if appropriate).                                                                                                                                                                                                                               |
| <p>Img (logo) </p><p>logoImg (string): </p><p>categoryImg (string): </p> | <p>A logo for the merchant, if one is found. If a logo is not found a general category icon is returned.</p><p>A logo for the merchant, if one is found. (Does not return a category icon).</p><p>A category icon for the merchant. These can be customised by the bank.</p> |
| cachePolicy                                                              | An indicator for the caching rules for the returned information.                                                                                                                                                                                                             |
| logoScore                                                                | An indicator as to the likelihood that the returned image is a logo.                                                                                                                                                                                                         |
| categorisation                                                           | Categorisation is returned when the merchant has been found in the Snowdrop Top Merchants database.                                                                                                                                                                          |
| ID                                                                       | This is an optional transaction identifier that can be sent to Snowdrop. If sent, it is returned. This is to allow for linking up the returned information with other systems.                                                                                               |

### Extended

The Extended call is used to populate a statement view of a single transaction with enriched GeoLocation data points.

Its main purpose is to return a map location (when appropriate) for the transaction. It also returns categorisation and other information.

The typical architecture is to present a statement view (list of transactions) first and then allow the user to press (or click) on a transaction to get more info. This is when the Extended call is used.

Characteristics of the Extended call

* Relies on the Google Maps Platform.
* The caching rules are determined by Google.
* Match rates will typically be higher as compared to the Restrictive call. This is because the Google Places database is very comprehensive.

#### Example UX for Extended call:

![](https://lh7-us.googleusercontent.com/KP0M_FRM8ZV3MTcdqky4vqMSiMQonxgxFVlRYlHNTWKkXevPGFxeNVcstxmN8g7Wks-SrsMaHZnW5sR4FRNF4NV8tt4uzXl_BQymzG4n5LWliSnWw9mnLZUm1dUpNWlsSyUtWM00zcPdpgb5YkGD6KJm=s2048)

#### Information returned by the Extended call:

Includes [everything provided by the Restrictive call](#information-returned-by-a-restrictive-call).

Includes the address, map coordinates, categorisation and more.

See the API specification for more details.

### &#x20;Data Flow Diagram: Restrictive vs Extended

<figure><img src="/files/mISm3BYtIEfF9fIwSNb1" alt=""><figcaption></figcaption></figure>


# Merchant Category Codes

One important request parameter is `mcc`, for [Merchant Category Codes](https://en.wikipedia.org/wiki/Merchant_category_code).

This Parameter is optional but **very helpful for good results.**

MRS uses MCCs in various ways to help identify the correct merchant. A key example is MRS uses MCCs to assist in identifying Automated Teller Machine (ATM) transactions. The code for automated cash disbursements is `6011`. This is helpful because in some cases, ATMs are not easily identifiable from the merchant description.

Also, certain airline, hotel and car rental companies have their own unique MCC code and if an MCC is provided it can help to identify the correct merchant.

Finally, an MCC can be used as an extra parameter to distinguish between different businesses that might share a name (for example the Metro Department store, Metro Supermarket and Metro Gas Station).


# Advanced Use Cases


# Brands

The `brand` object provides detailed metadata about the overarching brand associated with the merchant. This data is useful for categorization, UI representation (e.g. showing brand logos), aggregation and understanding corporate relationships.&#x20;

**Response Object:**

<figure><img src="/files/4yJ451gU2hxopbJXRNb6" alt=""><figcaption></figcaption></figure>

#### Field Overview

| Field                  | Type           | Description                                                                                                                                                       |
| ---------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                   | `string`       | Unique identifier for the brand.                                                                                                                                  |
| `name`                 | `string`       | The official name of the brand (e.g., “Carrefour Express”).                                                                                                       |
| `img`                  | `string (URL)` | Main image associated with the brand. Typically used for brand visualization (e.g., banners, highlights).                                                         |
| `website`              | `string (URL)` | Official website of the brand.                                                                                                                                    |
| `esg`                  | `object`       | ESG (Environmental, Social, and Governance) data. Excluded from this section; refer to [ESG Documentation](/advanced-use-cases/esg) for full details.             |
| `brandCategory`        | `object`       | Hierarchical classification of the brand. Excluded from this section. See [Categorization](/advanced-use-cases/categorization/categorization-overview) reference. |
| brandParentCategoryImg | `object`       | Icon representing the **brand’s parent category**, used when no brand logo is available                                                                           |
| brandCategoryGroupImg  | `object`       | Icon representing the **brand category group**, used when no brand logo is available                                                                              |

### Virtual Brands:

The API supports virtual brands to allow temporary representation of merchants that are not yet linked to a recognized brand. The virtual brand response essentially returns the merchant information inside the brand information as a placeholder. The way you can identify a virtual brand is by the missing id field inside the brand response. Once the proper brand is assigned, the virtual placeholder will be replaced accordingly.

If an MCC is included in the request, the response will also contain detailed categorisation regardless of whether a brand is found or not based on our MCC mapping techniques.

### Brand Category Icons:

Brands support category icons for brand parent categories and brand category groups (not category types). These icons are always returned and are also used as the brand image when a brand logo is unavailable.\
Using brand category icons helps maintain a consistent visual experience and makes transactions easier for users to recognise. While default icons are provided, we recommend supplying your own so they better align with your product’s look and feel.

#### Supported image sizes

* PNG images at **96 × 96 pixels**
* PNG images at **192 × 192 pixels**


# Categorization


# Categorization Overview

We have upgraded our transaction categorization system from a 2-level hierarchy to a 3-level hierarchy as of June 2024. This new structure enhances the granularity  and flexibility of categorizing transactions, allowing for more precise and customized mapping. We still support the old legacy category system.&#x20;

All new customers will have access to this new system by default. Existing customers will continue to use the old 2-level categorization system unless they opt-in to switch to the new system by getting in touch with our sales team.&#x20;

#### Key Features:

* 3-Level Hierarchy: Our categorization now includes three distinct levels: Parent Category, Category Group and Category Type.
* Extensive Categories: Over 500 Category Types are available, which can be mapped to Category Groups, and these Category Groups can be mapped to Parent Categories.
* Customization: The categorization system is flexible and can be customized to align with your specific category requirements.

#### Importance of the New Categorisation System

The enhanced 3-level categorisation system is crucial for several reasons:

1. **Understanding Spending Patterns**
   * The detailed categorization helps in identifying and analysing consumer spending patterns more accurately.
   * Businesses can track which categories are seeing the most spending and adjust their strategies accordingly.
2. **Consumer Behaviour Insights**
   * With more granular data, businesses can gain deeper insights into consumer behaviour.
   * This can include understanding preferences, frequent purchase categories, and seasonal trends.
3. **Bespoke Analysis**:
   * The enhanced categorization allows for more specific and customized analysis.
   * Businesses can tailor their reporting to focus on niche categories and specific consumer segments.
4. **Targeted Offers and Campaigns**:
   * By understanding detailed spending habits, businesses can create targeted marketing campaigns and personalized offers.
   * This increases the effectiveness of promotional efforts and improves customer engagement.
5. **Fraud Detection**
   * Improves the detection of fraudulent transactions by recognizing spending patterns that deviate from the norm.

<figure><img src="/files/dl7as60xEuCNw9DD5iXY" alt=""><figcaption><p>Smart categorisation</p></figcaption></figure>


# Transaction Category

### Hierarchy Breakdown

1. **Parent Category:** 12 Top level categories that provide a broad classification. Example: Retail & Shopping, Health & Wellness etc.
2. **Category Group:** 34 Mid-level categories that group related category types under a Parent category. Examples: Retail & Department Stores, Clothing & Fashion etc.
3. **Category Type:** 500+ Detailed categories that specify the exact nature of the transaction. Examples: Clothing, Apparel, Footwear etc.

<figure><img src="/files/YoQvDtpr7gaXSZAnwfY0" alt=""><figcaption><p>Hierarchy Breakdown</p></figcaption></figure>

#### Response Object:

<div align="left"><figure><img src="/files/y7llpldEfQ0uB510vk1F" alt=""><figcaption></figcaption></figure></div>

### Customising Categories

If you have an existing category system and prefer to continue using it, Snowdrop can integrate its categorization with yours. By default, MRS Category Types will be mapped to the most detailed level of your category system. However, the system is highly flexible, allowing for various mapping configurations, such as mapping our Category Groups to your category system or aligning all our Types with your custom categories.

Steps:

1. Provide Snowdrop with your equivalent parent and group categories. Also custom icons if you wish.
2. Snowdrop will perform an initial mapping to your categories which is then forwarded to you for review.
3. After confirmation, Snowdrop will implement the new custom categorisation.

<figure><img src="/files/5dPUqISgrf0CP62IMJZx" alt=""><figcaption><p>Choose any category level for transactions with category flexibility</p></figcaption></figure>

In addition you will need to supply the custom category icons you wish to use. See [Category Icons](/advanced-use-cases/categorization/category-icons).

<br>


# Category Icons

MRS includes the ability to send back a category icon.

* Icons are served when a logo is unavailable.
* It’s recommended that you use your own Icons so that they fit with your user experience.
* MRS supports two sizes for the image:
  * &#x20;PNG images of 96x96 pixels and 192x192 pixels&#x20;
* If not supplied, MRS will use the following default categories and category icons:

<figure><img src="/files/vpr2zFj5m0KDEPu1V0Sg" alt=""><figcaption></figcaption></figure>

Note: These icons are defaults only, it is recommended that your own icons be used.


# ESG

#### What is ESG Data? <a href="#what-is-esg-data" id="what-is-esg-data"></a>

We have added a new property to the MRS response: `brand`, as explained before. It also contains `esg.` This holds an array of participations, representing the *ESG schemes* that that **merchant** is participating in. Within each participation, there is a list of commitments. This represent whether the merchant has committed publicly to each of the goals of that scheme, and the details of each commitment.

**E.g.** ‘Mercadona’ is participating in the *United Nations Sustainable Development Goals* scheme. If you make a request with the merchant\_name of ‘Mercadona’, you will get a response containing ESG data about which of the UN goals they are committed to.

<figure><img src="/files/eRykHaSyVbr9uIPal4v4" alt=""><figcaption></figcaption></figure>


# Aggregation

When querying brand data, the API response includes both the specific **brand** and its corresponding **aggregateLevel**, which represents the highest-level parent brand. The goal for this is to make it easier to aggregate spending in situations where a large brand operates one or more sub-brands.

The new '**aggregateLevel**' field allows you to merge transactions from 'parent brands' and 'sub-brands'. For example, with this new feature, you can seamlessly compile all transactions from sub-brands like 'Carrefour Express' and 'Carrefour Market' along with the main brand 'Carrefour' for your users.

<figure><img src="/files/5IEYv5nlICHXvNbrcsoQ" alt=""><figcaption></figcaption></figure>

**Response Object:**

<figure><img src="/files/wAlHNlIsrogLjA655eTT" alt=""><figcaption></figcaption></figure>

**How to Use**

* Use the `brand` object for specific sub-brand data.
* Use the `aggregateLevel` object to group or associate the sub-brand with its parent brand entity.
* This is useful for reporting, filtering, or visual grouping under a single master brand in your application.
* In the cases where the brand doesn’t belong to any parent brand, the same brand itself will be returned as the aggregate brand.
* If you wish to consolidate transactions at the sub-brand level without including the main brand, avoid using the `aggregateLevel` attribute. For instance, if you want transactions at Carrefour Express to appear under Carrefour Express instead of the overarching brand Carrefour, do not apply this attribute.&#x20;


# Crowdsourcing


# Overview

#### Overview

After you've made a simple GET request (see [Quick Start](/implementation-guides/quick-start)), and tried a few [List request](/basic-concepts/list-request), you can send a *Crowdsourcing Report.* This is a way for end users to send feedback on MRS results.&#x20;

Examples that your users may wish to report:

* Incorrect merchant ("This is Jacob's Bakery not Jacob's Mechanics")
* Incorrect location ("This is not in Bristol, it is in London")
* Incorrect logos  ("This is the logo for Mandy's Flowers not Mandy's Pizza")

As a goal, it continually improves the clarity and accuracy of the information and further reduces the calls to the call centre + match rates + user trust.

Crowdsourcing is listed as a separate step because it requires extra user interface development (e.g. prompt to fix/report error at bottom on transaction details).

Here's an example of how you might implement a crowdsourcing  sequence:

1. Your app enriches a transaction, using the `/merchant/list` or `/merchant` endpoints (see [Quick Start](/implementation-guides/quick-start)). It records  the `X-Request-Id` and `X-Timestamp` headers that are returned for each enriched transaction. It also records the `transactionId`.
2. This enriched transaction is shown to the end user in your banking app.
3. The user notices that the merchant name is wrong - it's Peter's Pizza, not Peter's Pezza!
4. They click on the transaction in your app, taking them to a 'Detail' screen (see [Recommended UX](/implementation-guides/recommended-ux)).
5. The Detail screen has a button - 'Improve name, location or logo'. The user clicks this button.
6. They specify the correct name in a dialog - "Peter's Pizza", and click 'Send'.
7. Your app takes the `X-Request-Id` and `X-Timestamp` headers that were originally recorded for that transaction and sends them to the `/crowdsourcing` endpoint, along with the User's Feedback.

Next, let's see how to implement this in [Crowdsourcing Example](/advanced-use-cases/crowdsourcing/crowdsourcing-example).


# Crowdsourcing Example

Helps improve match rates on an ongoing basis

{% hint style="info" %}
Please read the [Quick Start](/implementation-guides/quick-start) guide to understand the basics of MRS first.
{% endhint %}

In order to call the /crowdsourcing endpoint, and report user feedback (see [Overview](/advanced-use-cases/crowdsourcing/overview)):

#### Required Fields

In the `/merchant/list` and `/merchant` endpoints, the `X-Request-Id` and `X-Timestamp` headers are returned. In order to submit a crowdsourcing request, you must store these values and send them in the `requestId` and `requestTimstamp` fields. If the report is in relation to a transaction in a `/merchant/list` request, you must also include the `transactionId` field of that transaction.

More on this in the OpenAPI spec.

{% tabs %}
{% tab title="cURL" %}
`curl --request POST`\
`--url https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/crowdsourcing`\
`--header 'Content-Type: application/json'`\
`--header 'X-Api-Key:`` `**`<YOUR-API-KEY>`**`'`\
`--data '{ "requestId": "1234abcd-1234-1234-1234-1234567890abc", "requestTimestamp": 1663766866877, "transactionId": "1234x1234", "wrongFields": [ "name", "address", "img" ], "suggestions": { "name": "McDonalds", "address":"10 Downing Street", "img": "new_logo.url" } }'`
{% endtab %}

{% tab title="Python" %}
`import http.client`

`conn = http.client.HTTPSConnection("`**`regional-snowdrop-domain-goes-here.com`**`")`

`payload = "{"requestId": "1234abcd-1234-1234-1234-1234567890abc","requestTimestamp": 1663766866877,"transactionId": "218x09d","wrongFields": ["name","address","img"],"suggestions": {"name": "McDonalds","address":"10 Downing Street","img": "new_logo.url"}}"`

`headers = { 'Content-Type': "application/json", 'X-Api-Key': "`**`<YOUR-API-KEY>`**`" }`

`conn.request("POST", "/api/v3/crowdsourcing", payload, headers)`

`res = conn.getresponse() data = res.read()`

`print(data.decode("utf-8"))`
{% endtab %}

{% tab title="C#" %}
`var client = new RestClient("https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/crowdsourcing");`&#x20;

`var request = new RestRequest(Method.POST);`

`request.AddHeader("Content-Type", "application/json"); request.AddHeader("X-Api-Key", "`**`<YOUR-API-KEY>`**`"); request.AddParameter("application/json", "{"requestId": "1234abcd-1234-1234-1234-1234567890abc","requestTimestamp": 1663766866877,"transactionId": "218x09d","wrongFields": ["name","address","img"],"suggestions": {"name": "McDonalds","address":"10 Downing Street","img": "new_logo.url"}}", ParameterType.RequestBody);`

`IRestResponse response = client.Execute(request);`
{% endtab %}

{% tab title="Javascript" %}
`const data = JSON.stringify({ "requestId": "1234abcd-1234-1234-1234-1234567890abc", "requestTimestamp": 1663766866877, "transactionId": "218x09d", "wrongFields": [ "name", "address", "img" ], "suggestions": { "name": "McDonalds", "address": "10 Downing Street", "img": "new_logo.url" } });`

`const xhr = new XMLHttpRequest();`&#x20;

`xhr.withCredentials = true;`

`xhr.addEventListener("readystatechange", function () {`&#x20;

&#x20;   `if (this.readyState === this.DONE) {`

&#x20;       `console.log(this.responseText);`&#x20;

&#x20;   `}`

`});`

`xhr.open("POST", "https://`**`regional-snowdrop-domain-goes-here.com`**`/api/v3/crowdsourcing");`&#x20;

`xhr.setRequestHeader("Content-Type", "application/json");`&#x20;

`xhr.setRequestHeader("X-Api-Key", "`**`<YOUR-API-KEY>`**`");`

`xhr.send(data);`
{% endtab %}

{% tab title="Java" %}
`HttpResponse response = Unirest.post("`**`https://regional-snowdrop-domain-goes-here.com`**`/api/v3/crowdsourcing") .header("Content-Type", "application/json") .header("X-Api-Key", "`**`<YOUR-API-KEY>`**`") .body("{"requestId": "1234abcd-1234-1234-1234-1234567890abc","requestTimestamp": 1663766866877,"transactionId": "218x09d","wrongFields": ["name","address","img"],"suggestions": {"name": "McDonalds","address":"10 Downing Street","img": "new_logo.url"}}") .asString();`
{% endtab %}
{% endtabs %}

#### Response

If you supplied the required fields correctly, you should recieve a success message:

```
{
    "message": "Report created"
}
```

Having problems? Consult [Troubleshooting](/troubleshooting) or [FAQ](/faq).


# Payment Intermediaries

This pertains to when a payment intermediary is involved in a transaction, such as Paypal or Alipay. MRS attempts to find the merchant involved in the transaction. For example if the merchant description is ‘`Paypal* McDonalds`’ then MRS will return ‘McDonalds’. If MRS cannot find the merchant then it returns Paypal (and the Paypal logo, website, etc.)&#x20;

An additional, separate return field allows MRS to also return the payment intermediary even when the merchant is found. So in the example above, MRS will return McDonalds but will also return Paypal separately.&#x20;

**Note: This is a configuration setting which is off by default.** When turned on, the additional payment company information will be included in the response. *Contact us if you wish to enable this functionality.*

This capability can be considered if it is thought that displaying both the merchant and the payment intermediary is a desirable experience in the application. &#x20;


# Payment Intermediaries Example

Example response with added Payment intermediary information. The input merchant description is: ‘`paypal *starbucks`’:

```json
[
  {
    "categories": [
      "cafe"
    ],
    "category": "Eating out",
    "name": "Starbucks",
    "website": "www.starbucks.com",
    "cachePolicy": {
      "name": "MRS",
      "categoryImg": "MRS"
    },
    "img": "https://storage.googleapis.com/pro-merchant-reconciliation-system-logos-europe/source00/5242783627476992_2x.png",
    "logoScore": 1,
    "logoImg": "https://storage.googleapis.com/pro-merchant-reconciliation-system-logos-europe/source00/5242783627476992_2x.png",
    "categoryImg": "https://storage.googleapis.com/pro-merchant-reconciliation-system-logos-europe/categories/default/food_2x.png",
    "intermediary": {
      "name": "PayPal",
      "website": "https://www.paypal.com",
      "img": "https://storage.googleapis.com/pro-merchant-reconciliation-system-logos-europe/source00/5525619504840704_2x.jpg"
      }
    }
  }
]
```

**Note: No change to the input request sent to MRS is required.**

The extra payment intermediary information is only returned if the appropriate configuration setting is turned on. Contact us if you would like us to enable this functionality.

<br>

<br>


# Clear Response Enrichment

Enriching Merchant Descriptions (even when the merchant is not found)

For transactions where MRS is unable to identify the merchant there is an option to clean the merchant description and categorise the transaction.

* Consider this a “backup” option for when MRS is unable to identify a merchant.
* It provides some “cleaning” of the Merchant Description when a match is not found.

<table><thead><tr><th width="443">Example input merchant description</th><th>Example cleaned result</th></tr></thead><tbody><tr><td>JOHN’S BOAT HOUSE 5671121110</td><td>John’s Boat House</td></tr><tr><td>#SNOWDROP#RESTAURANT#AND#POOL#HALL#</td><td>Snowdrop Restaurant And Pool Hall</td></tr></tbody></table>

* When an MCC Code is provided in the request then the response will also include Categorisation.&#x20;
* This means that a transaction can be categorised even in cases where the Merchant was not identified.&#x20;

### ClearResponse

We use the parameter `clearResponse` and show the `isclearResponse` field in the response to show the above behavior.

**Input Parameter**

`clearResponse` is an optional parameter. If this is set to `true`, even if we cannot find the merchant, we will attempt to clean up the transaction/add categorization as above.  This is set to `true` by default.

**Response Field**

For MRS Responses where we did not find a merchant, but were still cleaned up in this way, will have the `isClearResponse` flag set to `true` in the response.

More in the [OpenAPI Docs](/openapi-docs).


# Google Maps

Many of our customers display details of the merchant on a Detail page, with a Google Map showing the location of the merchant (see [Recommended UX](/implementation-guides/recommended-ux)):

![](https://lh7-us.googleusercontent.com/slidesz/AGV_vUcIlK7HKSmAFNgy_cckowdiuM8VU9tlPZ44_qRBdAKi84M23L19l-y6JqNNBnyXrwywKoDeXd4o8W2XDxTTSniAjg28Eb-GbFJvhm9h7rvM7-GMt4DyQh1TzDMHgP7zks8lQzKplvla6-kvkvwGig0PHJCT_pbx=s2048?key=ylfgmPEICIhqqglPem5QQA)

Map loads on mobile can be addressed via Google Maps APIs or Google Maps SDKs.

Two basic types of map presentation are offered

* Static Maps - single image is presented
* Dynamic Maps - interactive map which can be panned and zoomed

Using Google Maps API calls

* Incurs a cost per call
* Dynamic Maps cost more than Static Maps&#x20;
* Snowdrop can help model the costs.

#### Recommended: Using Google Maps Software Developer Kit (SDK)

* Generally speaking calls are free and unlimited if you use the SDK (both Dynamic and Static).
  * Avoid the use of a Map ID when loading the map.  As per this price list: [Link](https://developers.google.com/maps/documentation/android-sdk/usage-and-billing)
* SDK automatically handles access to Google Maps servers, map display, and response to user gestures
* When using the SDK it is best practice to restrict the API key to just map Map calls. Here is a [blog post](https://cloud.google.com/blog/products/maps-platform/google-maps-platform-best-practices-restricting-api-keys).
* The SDKs are created and supported by Google but Snowdrop can assist with questions and support as well.

#### Further Recommendations

* Use Static Maps when only displaying the Merchant&#x20;
* Use the Mobile Maps SDK if possible

#### Links

[Google Maps SDK for Android](https://developers.google.com/maps/documentation/android-sdk/overview)

[Google Maps SDK for iOS](https://developers.google.com/maps/documentation/ios-sdk/overview)


# About Google Maps IDs

Response Parameter:  `place_id`

Each entry in the Google Places database is assigned a Place ID.

Place IDs are unique identifiers.

Place IDs are only returned when an `extended` call is made and a result is obtained from Google Places. See [Restrictive vs Extended](/basic-concepts/restrictive-vs-extended).

Place IDs can be used to obtain other information about the place.

Place IDs can be cached indefinitely.

#### Example Place ID

Here is an example response with the `place_id` highlighted

> &#x20;`{`
>
> &#x20;   `"address": "207 Edgware Rd, Tyburnia, London W2 1ES, UK",`
>
> &#x20;   `"categories": [`
>
> &#x20;     `"cafe"`
>
> &#x20;   `],`
>
> &#x20;   `"category": "Eating out",`
>
> &#x20;   `"name": "Starbucks",`
>
> &#x20;   `"website": "www.starbucks.com",`
>
> &#x20;   `"country": "United Kingdom",`
>
> &#x20;   `"postal_code": "W2 1ES",`
>
> &#x20;   **`"place_id": "ChIJG2-uP7QadkgR6sN3Fcgg2X0",`**


# Legal & Compliance


# Security / Compliance FAQ

This section contains answers to common questions on the topic of security and compliance.


# Data Encryption

* Google Cloud Platform encrypts customer data stored at rest by default &#x20;
* Google employs several security measures to help ensure the authenticity, integrity, and privacy of data in transit

More information can be found here

* <https://cloud.google.com/security/encryption-at-rest>
* <https://cloud.google.com/security/encryption-in-transit> &#x20;


# Penetration Testing

* Snowdrop contracts for third parties to perform Penetration Testing on MRS on a regular basis.
* OWASP Top Ten vulnerability testing is performed regularly during our development and build process.
* Google adheres to various global and regional compliance regimes for its data centers.
  * ISO/IEC 27001
  * SOC 1
  * HIPAA
  * FedRamp
* Note: Regional compliance is also taken into account. Google adheres to a large number of country and bank specific standards:&#x20;

  <https://cloud.google.com/security/compliance/offerings#/regions=EMEA>&#x20;

  <https://cloud.google.com/security/compliance/>


# Terms of Service


# MRS Terms of Service

#### Data Caching&#x20;

* Snowdrop data can be cached on a per Transaction basis for up to 7 Years&#x20;
  * A transaction is defined as a unit of Purchase related activity by an Individual Consumer at a Specific Time and Place &#x20;
* Google Maps data can be cached in line with the [Google Maps Terms of Service](https://cloud.google.com/maps-platform/terms) (further details can be found in [Google Maps Terms of Service](/legal-and-compliance/terms-of-service/google-maps-terms-of-service) )
  * Data received from an `extended` Call will be a combination of information that belongs to Snowdrop and Google Maps
* 3rd Parties
  * With the exception of cardholders, cached information cannot be shared with third parties unless required by applicable laws or regulations or Snowdrop has provided written consent
* Similar services
  * No data may be used to build a similar service to MRS

#### Note&#x20;

The MRS Response includes a `cachePolicy` value to show which category a data field is in.&#x20;

<br>


# Google Maps Terms of Service

The following is NOT permitted:

* The use of Google Places information (e.g. Merchant details) on a non-Google Map
* Caching of Data&#x20;
  * Information provided cannot be cached, with the following two exceptions:
    * The Google Places ID (a unique identifier for each entry in the database): Indefinite
    * The Lat/Long information of a Place:  30 days.
* Tracking a users’ device without the user’s express consent
* Use of data for Fraudulent or Illicit purposes

More detail can be found here: <https://cloud.google.com/maps-platform/terms/>


# Troubleshooting

{% hint style="info" %}
If you have a problem that you don't see here, please contact us!&#x20;
{% endhint %}

<details>

<summary>Error: Couldn't resolve host name</summary>

Does your code call the Snowdrop MRS domain name we supplied you? If you used the example code in the quickstart, it does not contain a valid domain. You should replace the `regional-snowdrop-domain-goes-here.com` in your code.

</details>

<details>

<summary>401 Error: Invalid apiKey</summary>

You must specify the `X-Api-Key` value in the Headers, as in the [Quick Start](/implementation-guides/quick-start) guide. Make sure your code has the API Key that Snowdrop supplied you. If you do not have an API key, please contact us.

</details>

<details>

<summary>404 Error: Not Found</summary>

Are you sure you have specified the full URL correctly? It is easy to miss out components of the URL. Make sure you contain the /api/v3/ part.\
It should read: <https://regional-domain-goes-here.co&#x6D;**/api/v3/**&#x6D;erchant?merchant\\_name=mcdonalds\\&type=extended\\&location=london\\&country=GBR\\>
or \
<https://regional-domain-goes-here.co&#x6D;**/api/v3/**&#x6D;erchant/list>

</details>


# FAQ

<details>

<summary>What does 'restrictive' or 'extended' mean?</summary>

See [Restrictive vs Extended](/basic-concepts/restrictive-vs-extended).

</details>

<details>

<summary>What is a 'Regional Domain'?</summary>

We offer regional subdomains of MRS in Google Cloud Platform, so that our customers can use MRS in the GCP data center closest to them. This means that they can experience the lowest latency possible. For example, we offer a subdomain in Germany for our customers near Germany, and a subdomain in Singapore for our customers near Singapore.

</details>

<details>

<summary>What is an 'API Key'?</summary>

We will supply you with an API key to authorise your MRS requests, which is a long string of letters and numbers. You send it as a header with every request you make - see [Quick Start](/implementation-guides/quick-start).  We strongly recommend you store this securely as we cannot retrieve it for you.

</details>


