Merchant enrichment API
Turn messy card descriptors into clean merchant data
One API call turns a raw statement line into a merchant name, category, website, location and payment processor, with a confidence score. Works with statements from any country, Arabic script included.
500 free enrichments a month. No credit card.
POS 4521 CAREEM*RIDE DXB AE
{ } View API response
{
"descriptor": "POS 4521 CAREEM*RIDE DXB AE",
"normalized": "CAREEM RIDE",
"merchant": {
"id": "mer_01M4TKG2681HHBYZWQE4FEQARK",
"name": "Careem",
"legal_name": null,
"website": "https://www.careem.com",
"logo_url": "https://cdn.descriptorapi.com/logos/careem-218be11e.png",
"category": "transportation",
"subcategory": "ride_hailing",
"mcc": "4121"
},
"location": {
"city": "Dubai",
"country": "AE"
},
"processor": null,
"is_subscription": false,
"confidence": 0.97,
"source": "rules",
"verified": true
}TALABAT DUBAI 12/10
Talabat
✓ Verified rules{ } View API response
{
"descriptor": "TALABAT DUBAI 12/10",
"normalized": "TALABAT",
"merchant": {
"id": "mer_01M4TMVAE0TMX23ZB0FT7TQVT8",
"name": "Talabat",
"legal_name": null,
"website": "https://www.talabat.com",
"logo_url": "https://cdn.descriptorapi.com/logos/talabat-20d0b4d7.png",
"category": "food_and_dining",
"subcategory": "food_delivery",
"mcc": "5812"
},
"location": {
"city": "Dubai",
"country": "AE"
},
"processor": null,
"is_subscription": false,
"confidence": 0.97,
"source": "rules",
"verified": true
}PAYPAL *NETFLIX 4029357733
Netflix
✓ Verified rules{ } View API response
{
"descriptor": "PAYPAL *NETFLIX 4029357733",
"normalized": "NETFLIX",
"merchant": {
"id": "mer_01M4TMV772ZMACDZMVHM14VJH3",
"name": "Netflix",
"legal_name": null,
"website": "https://www.netflix.com",
"logo_url": "https://cdn.descriptorapi.com/logos/netflix-5a54a17a.png",
"category": "subscriptions_and_streaming",
"subcategory": "video_streaming",
"mcc": null
},
"location": null,
"processor": "PayPal",
"is_subscription": true,
"confidence": 0.97,
"source": "rules",
"verified": true
}شراء كارفور الرياض
Carrefour
✓ Verified rules{ } View API response
{
"descriptor": "شراء كارفور الرياض",
"normalized": "كارفور",
"merchant": {
"id": "mer_01M4TNEWV2E3F49GFMW1K97SH0",
"name": "Carrefour",
"legal_name": null,
"website": "https://www.carrefour.com",
"logo_url": "https://cdn.descriptorapi.com/logos/carrefour-2fcf3be4.png",
"category": "groceries",
"subcategory": "supermarkets",
"mcc": null
},
"location": {
"city": "Riyadh",
"country": "SA"
},
"processor": null,
"is_subscription": false,
"confidence": 0.97,
"source": "rules",
"verified": true
}AMZN MKTP AE*2K3J91ZQ0
Amazon Marketplace
✓ Verified rules{ } View API response
{
"descriptor": "AMZN MKTP AE*2K3J91ZQ0",
"normalized": "AMAZON MARKETPLACE",
"merchant": {
"id": "mer_01M4TMV5JBT5FT3XJQPTK0T3WT",
"name": "Amazon Marketplace",
"legal_name": null,
"website": "https://www.amazon.ae",
"logo_url": "https://cdn.descriptorapi.com/logos/amazon-marketplace-7c5edf10.png",
"category": "shopping",
"subcategory": "marketplaces",
"mcc": "5999"
},
"location": {
"city": null,
"country": "AE"
},
"processor": "Amazon Marketplace",
"is_subscription": false,
"confidence": 0.97,
"source": "rules",
"verified": true
}Before and after
Your users see this. They should see this.
The same eight transactions, as a bank prints them and as your app can show them. The decoded side is live output from the API.
- 12 Oct POS 4521 CAREEM*RIDE DXB AE AED 23.50
- 12 Oct TALABAT DUBAI 12/10 AED 64.00
- 11 Oct NOON.COM RIYADH SA SAR 219.00
- 11 Oct SALIK DUBAI AE AED 4.00
- 10 Oct PAYPAL *SPOTIFY 4029357733 AED 21.99
- 09 Oct JARIR BOOKSTORE JEDDAH SAR 89.00
- 08 Oct كارفور الرياض SAR 342.15
- 08 Oct UBER *TRIP HELP.UBER.COM AED 37.20
-
Careem
Transportation · Dubai
AED 23.50
-
Talabat
Food & dining · Dubai
AED 64.00
-
NOON
Shopping · Riyadh
SAR 219.00
-
SALIK
Transportation · Dubai
AED 4.00
-
Spotify
Subscriptions & streaming · via PayPal
AED 21.99
-
Jarir Bookstore
Shopping · Jeddah
SAR 89.00
-
Carrefour
Groceries · Riyadh
SAR 342.15
-
Uber
Transportation
AED 37.20
How it works
Four steps, cheapest first
Every descriptor falls through the same sieve. Most stop at the first step; the AI only sees descriptors nothing else could answer, and its answer is cached so the same line never costs twice.
- 1 Cache Seen this exact descriptor before? Answer from memory or the database.
- 2 Rules Exact, prefix and regex patterns for known merchants.
- 3 Fuzzy Trigram match against merchant names, for typos and truncation.
- 4 AI Only for descriptors never seen before. The answer is cached and reviewed.
Lit up: the step that answered the example in the Decoder above.
252 countries · 1,335 cities
Reads statements the way they are written
Airport codes, English spellings and Arabic names all resolve to the same city. Payment processors and wallets are detected and peeled off, so the merchant underneath is what gets matched.
- DXB · DUBAI · دبي Dubai, AE
- LON · LONDON London, GB
- NYC · NEW YORK New York, US
- RUH · RIYADH · الرياض Riyadh, SA
- BOM · MUMBAI Mumbai, IN
- GRU · SAO PAULO São Paulo, BR
- CAI · CAIRO · القاهرة Cairo, EG
- PARIS Paris, FR
- LAGOS Lagos, NG
- TOKYO Tokyo, JP
- NLU · MEXICO CITY Mexico City, MX
- BER · BERLIN Berlin, DE
- AUH · ABU DHABI · ابوظبي Abu Dhabi, AE
- BIRMINGHAM Birmingham, GB
- SAN FRANCISCO San Francisco, US
- JED · JEDDAH · جدة Jeddah, SA
Processors and wallets we detect
- PayPal
- Square
- Toast
- Stripe
- Amazon Marketplace
- Apple
- Paddle
- FastSpring
- Polar
- 2Checkout
- Digital River
- Tabby
- Tamara
- PayTabs
- Checkout.com
- Geidea
- Paymob
- Fawry
- Moyasar
- HyperPay
- Kashier
- MyFatoorah
- PayFort
- Telr
- Tap Payments
- PaySky
- OPay
- Apple Pay
- Google Pay
- Samsung Pay
For developers
One request. One clean answer.
JSON in, JSON out, from any language. Send the descriptor and, if you have it, the card country; get back the merchant and how sure we are.
curl https://api.descriptorapi.com/v1/enrich \
-X POST \
-H "Authorization: Bearer $DESCRIPTORAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"descriptor": "POS 4521 CAREEM*RIDE DXB AE", "country": "AE", "mcc": "4121"}'
body := strings.NewReader(`{"descriptor": "POS 4521 CAREEM*RIDE DXB AE", "country": "AE", "mcc": "4121"}`)
req, _ := http.NewRequest("POST", "https://api.descriptorapi.com/v1/enrich", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+os.Getenv("DESCRIPTORAPI_KEY"))
resp, err := http.DefaultClient.Do(req)
const res = await fetch("https://api.descriptorapi.com/v1/enrich", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DESCRIPTORAPI_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"descriptor": "POS 4521 CAREEM*RIDE DXB AE", "country": "AE", "mcc": "4121"}),
});
const data = await res.json();
import os, requests
res = requests.post(
"https://api.descriptorapi.com/v1/enrich",
headers={"Authorization": f"Bearer {os.environ['DESCRIPTORAPI_KEY']}"},
json={"descriptor": "POS 4521 CAREEM*RIDE DXB AE", "country": "AE", "mcc": "4121"},
timeout=10,
)
data = res.json()
$ch = curl_init("https://api.descriptorapi.com/v1/enrich");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => '{"descriptor": "POS 4521 CAREEM*RIDE DXB AE", "country": "AE", "mcc": "4121"}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DESCRIPTORAPI_KEY'),
'Content-Type: application/json',
],
]);
$data = json_decode(curl_exec($ch), true);
Response · 200 OK
{
"descriptor": "POS 4521 CAREEM*RIDE DXB AE",
"normalized": "CAREEM RIDE",
"merchant": {
"id": "mer_01M4TKG2681HHBYZWQE4FEQARK",
"name": "Careem",
"legal_name": null,
"website": "https://www.careem.com",
"logo_url": "https://cdn.descriptorapi.com/logos/careem-218be11e.png",
"category": "transportation",
"subcategory": "ride_hailing",
"mcc": "4121"
},
"location": {
"city": "Dubai",
"country": "AE"
},
"processor": null,
"is_subscription": false,
"confidence": 0.97,
"source": "rules",
"verified": true
}In every response
Answers you can act on
Confidence scores
Every answer says how sure it is, from 0 to 1. Show high-confidence matches straight away and route the rest to review.
Verified merchants
verified: true means a person on our team approved the merchant record. AI suggestions stay unverified until they are reviewed.
Arabic, natively
Arabic-script and mixed descriptors are normalized, matched against Arabic merchant names and returned with the same clean fields.
شراء كارفور الرياض
Batch endpoint
Send up to 100 descriptors in one call. Results come back in order, and one bad line never fails the rest.
POST /v1/enrich/batch
Private by design
We need the descriptor, never the cardholder. Amounts are not stored, person-to-person transfers are never cached, and we do not train models on your data.
Fast where it counts
Descriptors we have seen before are answered from memory. Only lines nobody has sent before go further down the pipeline.
Start free, grow when you need to
Compare plans- Free 500 enrichments / month Free
- Starter 10,000 enrichments / month Talk to us
- Growth 100,000 enrichments / month Talk to us
- Enterprise Custom volume Talk to us
Decode your first descriptor in two minutes
Sign up, copy your key, send one request. Or try it right now without an account.