Real-time merchant matching guide

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

Overview

Real time merchant matching allows you to effectively match a small volume of merchants to locations and counterparties in Spade's database. In this guide, we'll use the /merchants/ match POST endpoint to submit a real-time merchant match.

Request Schema

{
  // REQUIRED
  "merchantName": "SHELL",
  "address": "11458 S Cicero Ave",
  "city": "Alsip",
  "region": "IL",
  "postalCode": "60803",
  "country": "USA",
  "requestId": "your‑internal‑id‑123",

  // OPTIONAL – improves accuracy
  "latitude": 41.6839,
  "longitude": -87.7398,
  "website": "shell.com",

  // OPTIONAL – echoed back so you
  "customAttributes": {
    "importBatch": "oct‑15‑2025",
    "source": "legacy_sql_dump"
  }
}

Tip: Latitude & longitude are the strongest disambiguators after name + address. Use them when you have them.


Performing Your First Match

1. Prepare the payload

Pick a merchant from your database -- ideally one with a full postal address.

2. Send the request

import requests, json, pprint

payload = {
  "merchantName": "SHELL",
  "address": "11458 S Cicero Ave",
  "city": "Alsip",
  "region": "IL",
  "postalCode": "60803",
  "country": "USA",
  "latitude": 41.6839,
  "longitude": -87.7398,
  "requestId": "your‑internal‑id‑123"
}

resp = requests.post(
    "https://east.sandbox.spade.com/merchants/match",
    headers={"X-Api-Key": "<YOUR_SANDBOX_API_KEY>"},
    json=payload,
    timeout=2,
)
pprint.pp(resp.json())

A minimal cURL equivalent:

curl https://east.sandbox.spade.com/merchants/match \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: <YOUR_SANDBOX_API_KEY>" \
  -d @payload.json

3. Inspect the response

{
  "requestId": "your‑internal‑id‑123",
  "counterparty": {
    "id": "d90d6e09-1be3-4042-8283-7e2a7544b65d",
    "name": "Shell",
    "similarity": 100
  },
  "location": {
    "id": "e1f396bc-a0a8-4615-b317-066164e98677",
    "name": "Shell",
    "address": "11458 S Cicero Ave",
    "city": "Alsip",
    "similarity": 100
  },
  "customAttributes": {
    "importBatch": "oct‑15‑2025",
    "source": "legacy_sql_dump"
  }
}

Response Breakdown

counterparty

FieldDescription
idSpade Counterparty ID
nameCanonical business name.
similarity0–100 match confidence.

location

FieldDescription
idSpade Location ID
name Location‑level business name (if distinct from brand).
addressCleansed, correctly cased postal address.
cityCleaned city corresponding to the Location
similarityConfidence that this physical location is the one you provided.

Similarity vs. Match Score?
For merchant matching we use similarity (string & geo distance based). Card enrichment uses matchScore (ML model across many signals). Treat them the same way: higher = better.


Handling Non‑Matches

A null counterparty or location means we couldn’t find an acceptable match. Typical reasons:

  • Typos or missing street numbers
  • Recently opened stores not yet in our DB
  • PO boxes or corporate HQ addresses

What to do

  1. Retry with more info – add latitude/longitude if you have it.
  2. Store as unknown – save the original name; you can re‑run matching later.

Batch Matching (Optional)

If you have > 1000 merchants, use POST /batches/merchants/match. Learn more in our batch merchant matching guide.

Implementation Notes

  • Content‑Type must be application/json. Some HTTP tools fallback to multipart/form-data; override it explicitly.
  • 400 errors → invalid or missing required fields (address, city, region, postalCode, country, merchantName).
    Parse the response JSON for details.
  • 403 errors → invalid or missing API key.
  • 500 errors → Spade’s infrastructure. These are rare; exponential back‑off is recommended.

💡

Troubleshooting Suite/Apt/Unit Numbers

If your request includes a suite, apartment, or unit designator (e.g., “123 Main St Ste 204”) and you don’t get a satisfactory match, resend the request without the suite information.
Likewise, if your original request omits the suite but still fails to match, try adding the suite/apt/unit string. Suite tags are recorded inconsistently across data providers, so toggling them on or off often nudges a borderline similarity score over the threshold.


Best Practices Checklist ✅

Done?Recommendation
 Send full street address and city/region/postalCode.
 Provide latitude/longitude when available (mobile checkouts, GPS capture).
 Store counterparty.id and location.id once → attach to every transaction.
 Decide on a similarity threshold (e.g., drop matches <70).
 Use batch matching for historical backfills and weekly sync jobs.