API ReferenceChangelog

ⓘ Reading Time: 15 mins

Merchant search provides a way to search Spade's merchant database. It currently supports only a subset of Spade's merchants (mostly larger, frequently transacted merchants), with more merchants being added over time.

We recommend working along as you go, using your API key for our sandbox environment.

Merchant search is not enabled by default. To request access, please contact us at [email protected].

Searching for merchants

You can use Spade's merchant search API to fetch a merchant's ID, name, logo, and website:

import requests

response = requests.get("https://east.sandbox.spade.com/merchants", params={"name": "app"}, headers={"X-Api-Key": "<Your API Key Here>"})
merchants = response.json()

print(merchants)

Sending the above request returns:

{
  "merchants": [
    {
      "id": "77c757db-27b1-47b8-80f6-d3f99a4c5a97",
      "name": "Cash App",
      "similarity": 44.44,
      "logo": "https://v1.spadeapi.com/logos/verified/cashapp.png?size=large",
      "website": "cash.app"
    },
    {
      "id": "d005fe49-6115-44f0-922d-6297a5c2d31f",
      "name": "Kick.app",
      "similarity": 44.44,
      "logo": "https://v1.spadeapi.com/logos/verified/kickapp.png?size=large",
      "website": "kick.app"
    },
    {
      "id": "d65346f4-8975-4109-b4e6-a7a33eca4ffe",
      "name": "Grid App",
      "similarity": 44.44,
      "logo": "https://v1.spadeapi.com/logos/verified/gridapp.png?size=large",
      "website": "https://getgrid.app/"
    },
    {
      "id": "2b838cce-6565-4632-a53e-efbd2fb4b083",
      "name": "Apple",
      "similarity": 42.86,
      "logo": "https://v1.spadeapi.com/logos/verified/apple.png?size=large",
      "website": "apple.com"
    },
    {
      "id": "63f680f6-a963-4fdb-87e7-4d0740338784",
      "name": "Apptoto",
      "similarity": 33.33,
      "logo": "https://v1.spadeapi.com/logos/verified/apptoto.png?size=large",
      "website": "apptoto.com"
    }
  ]
}

As you can see, the results are listed in decreasing order by the similarity score. The similarity score simply indicates how closely each merchant matches the input query, and the number of results is currently limited to five. This behavior allows you to build an autocomplete interface into your application(s) out of the box:

Merchant Search Example

Integrating merchant search / transaction rules into your application

This section show you how to integrate merchant search and transaction rules into your application's UI.

Because client-side code is public and your API key is secret, you will need to proxy merchant search and transaction rule requests through your backend to Spade's servers.

Request proxying

⚠ NEVER send your API key to the client. This includes any client-side application code bundles (websites, mobile apps, etc...).

Step 1: Set up a proxy endpoint on your backend

For security reasons, you'll first need to set up an endpoint on your backend to act as a middleman between your frontend and Spade's API.

Here's how you might set up this endpoint using Flask:

from flask import Flask, request
from flask_login import login_required
import requests

app = Flask(__name__)
spade_api_key = os.environ.get("SPADE_API_KEY")

@app.get('merchants')
# Make sure the user is authenticated. Only authenticated users should be able to query Spade's merchant database.
@login_required
def get_merchants():
    # Grab the name from the query parameters (i.e. GET /merchants?name=walmart)
    name = request.args.get('name', '')

    # Forward the request to Spade
    response = requests.get("https://east.sandbox.spade.com/merchants", params={"name": name}, headers={"X-Api-Key": spade_api_key})

    # Relay Spade's response to your frontend
    return response.json(), response.status_code

Step 2: Add the autocomplete input to your frontend

Now that you have an endpoint to hit, you can add an autocomplete input to your frontend to allow your users to search Spade's merchant database.

Many frameworks and packages provide autocomplete functionality out of the box. Here's an example written in Svelte using the simple-svelte-autocomplete package:

<script>
import AutoComplete from "simple-svelte-autocomplete";

async function getMerchants(name) {
  const url = "https://<YOUR_API_DOMAIN_HERE>/merchants?name=" + encodeURIComponent(name);

  const response = await fetch(url);
  const json = await response.json();

  return json.results;
}
</script>

<AutoComplete
  searchFunction="{getMerchants}"
  delay="400"
  localFiltering={false}
  labelFieldName="name"
  valueFieldName="id"
  bind:selectedItem="{selectedMerchant}"
/>;

In this example, we're using the simple-svelte-autocomplete package's built-in throttling functionality (this is what the delay="400" setting configures).

Depending on your tech stack, you may need to throttle / debounce requests manually. Because Spade's merchant search API is rate-limited, it is important that you throttle / debounce requests in order to avoid making too many requests.

If your existing tech stack doesn't provide a function to throttle / debounce requests, lodash is a relatively lightweight package that provides simple functions for throttling and debouncing.

Step 3 (optional): Enable your users to create transaction rules

Once you've set up the merchant search input, you can use the selectedMerchant to create a transaction rule (note that you'll need to set up a separate endpoint on your backend to proxy the transaction rule request to Spade's API, just like you did for the merchant search endpoint):

<script>
import AutoComplete from "simple-svelte-autocomplete";

async function createTransactionRule() {
  const url = "https://<YOUR_API_DOMAIN_HERE>/transaction-rules";

  const response = await fetch(url, {
    method: "PUT",
    body: JSON.stringify({
      userId: "<Card ID>",
      cardId: "<User ID>",
      type: "allow",
      condition: "counterparty_id in @allowed_counterparty_ids",
      parameters: {"allowed_counterparty_ids": [selectedMerchant.id]},
    })
  });

  const json = await response.json();

  // Display a success message / handle errors as needed
  ...
}

async function getMerchants(name) {
  const url = "https://<YOUR_API_DOMAIN_HERE>/merchants?name=" + encodeURIComponent(name);

  const response = await fetch(url);

  const json = await response.json();
  return json.results;
}
</script>

<AutoComplete
  searchFunction="{getMerchants}"
  delay="400"
  localFiltering={false}
  labelFieldName="name"
  valueFieldName="id"
  bind:selectedItem="{selectedMerchant}"
/>;

<button type="button" on:click:{createTransactionRule}>Restrict spending to this merchant</button>

Conclusion

Congratulations! You've now added merchant search and transaction rules to your application. Your users can now set up transaction rules for any merchant included in Spade's merchant search endpoint.

To provide maximum control to users, you can also allow them to enter custom conditions using Spade's DSL syntax. In this case, you may want to validate rules in real-time before actually creating them. To do so, just call PUT /transaction-rules/validate instead of PUT /transaction-rules.

Next steps

Modifying Existing Transaction Rules

Transaction Rules Language Guide

Transaction Rules FAQ