curl --request GET \
--url https://api.prefetch.io/transaction \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.prefetch.io/transaction"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.prefetch.io/transaction', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.prefetch.io/transaction",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.prefetch.io/transaction"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.prefetch.io/transaction")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.prefetch.io/transaction")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"descriptor": "SQ *BLUE BOTTLE COFFE OAKLAND CA",
"kind": "merchant",
"merchant": {
"name": "Blue Bottle Coffee",
"domain": "bluebottlecoffee.com",
"url": "https://bluebottlecoffee.com",
"confidence": 0.88,
"source": "live"
},
"candidates": [
{
"name": "Blue Bottle Coffee",
"domain": "bluebottlecoffee.com",
"url": "https://bluebottlecoffee.com",
"confidence": 0.88,
"source": "live"
}
],
"payment_processor": "Square",
"location": {
"city": "Oakland",
"region": "CA",
"country": "US"
},
"category": "Coffee shop",
"logo_url": "https://logo.prefetch.io/bluebottlecoffee.com?token=pk_4f1c9e2b7a0d4c3e8b6a1f2d3c4b5a69",
"parsed_by": "model",
"warnings": []
},
"meta": {
"requestId": "6f1d2c3b-4a5e-4f60-8b7a-9c0d1e2f3a4b",
"durationMs": 1840
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}GET /transaction
Turn a card transaction descriptor into the merchant behind it — name, website, logo, processor and location. Costs 3 credits, 1 for a line seen in the last week.
curl --request GET \
--url https://api.prefetch.io/transaction \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.prefetch.io/transaction"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.prefetch.io/transaction', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.prefetch.io/transaction",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.prefetch.io/transaction"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.prefetch.io/transaction")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.prefetch.io/transaction")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"descriptor": "SQ *BLUE BOTTLE COFFE OAKLAND CA",
"kind": "merchant",
"merchant": {
"name": "Blue Bottle Coffee",
"domain": "bluebottlecoffee.com",
"url": "https://bluebottlecoffee.com",
"confidence": 0.88,
"source": "live"
},
"candidates": [
{
"name": "Blue Bottle Coffee",
"domain": "bluebottlecoffee.com",
"url": "https://bluebottlecoffee.com",
"confidence": 0.88,
"source": "live"
}
],
"payment_processor": "Square",
"location": {
"city": "Oakland",
"region": "CA",
"country": "US"
},
"category": "Coffee shop",
"logo_url": "https://logo.prefetch.io/bluebottlecoffee.com?token=pk_4f1c9e2b7a0d4c3e8b6a1f2d3c4b5a69",
"parsed_by": "model",
"warnings": []
},
"meta": {
"requestId": "6f1d2c3b-4a5e-4f60-8b7a-9c0d1e2f3a4b",
"durationMs": 1840
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}Overview
Bank statement lines are written for card networks, not people:SQ *BLUE BOTTLE COFFE OAKLAND CA, PAYPAL *SPOTIFYAB, AMZN Mktp US*2K4LX9B12. /transaction reads one and tells you who was paid:
| Descriptor | Merchant | Website | Processor | Where |
|---|---|---|---|---|
SQ *BLUE BOTTLE COFFE OAKLAND CA | Blue Bottle Coffee | bluebottlecoffee.com | Square | Oakland, CA |
PAYPAL *SPOTIFYAB | Spotify | spotify.com | PayPal | |
AMZN Mktp US*2K4LX9B12 | Amazon | amazon.com | ||
CHECKCARD 0412 STARBUCKS STORE 12345 SEATTLE WA | Starbucks | starbucks.com | Seattle, WA | |
VENMO *JOHN SMITH | — a payment to a person | Venmo | ||
MONTHLY MAINTENANCE FEE | — a bank fee |
kind: person, transfer, fee, atm or refund.
The merchant’s name is then resolved to its website exactly as /resolve does it — the name index first, then a live lookup that verifies each candidate against its own homepage, using the line’s city to tell local businesses apart. logo_url points at the merchant’s logo on the logo CDN, with your publishable token, ready for an <img> tag. include_brand=true adds the merchant’s full brand (logos, colors, fonts), as /brand returns it.
Example requests
curl -G "https://api.prefetch.io/transaction" \
--data-urlencode "descriptor=SQ *BLUE BOTTLE COFFE OAKLAND CA" \
--data-urlencode "country=US" \
-H "X-API-Key: $PREFETCH_API_KEY"
curl -X POST "https://api.prefetch.io/transaction" \
-H "X-API-Key: $PREFETCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "descriptor": "PAYPAL *SPOTIFYAB", "mcc": "5815", "include_brand": true }'
const lines = ["SQ *BLUE BOTTLE COFFE OAKLAND CA", "NETFLIX.COM 866-579-7172 CA", "VENMO *JOHN SMITH"];
for (const descriptor of lines) {
const res = await fetch("https://api.prefetch.io/transaction", {
method: "POST",
headers: { "X-API-Key": process.env.PREFETCH_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ descriptor, country: "US" }),
});
const { data } = await res.json();
console.log(descriptor, "→", data.kind === "merchant" ? `${data.merchant.name} (${data.merchant.domain ?? "no site"})` : data.kind);
}
Example response
{
"success": true,
"data": {
"descriptor": "SQ *BLUE BOTTLE COFFE OAKLAND CA",
"kind": "merchant",
"merchant": {
"name": "Blue Bottle Coffee",
"domain": "bluebottlecoffee.com",
"url": "https://bluebottlecoffee.com",
"confidence": 0.88,
"source": "live"
},
"candidates": [
{ "name": "Blue Bottle Coffee", "domain": "bluebottlecoffee.com", "url": "https://bluebottlecoffee.com", "confidence": 0.88, "source": "live" }
],
"payment_processor": "Square",
"location": { "city": "Oakland", "region": "CA", "country": "US" },
"category": "Coffee shop",
"logo_url": "https://logo.prefetch.io/bluebottlecoffee.com?token=pk_4f1c9e2b7a0d4c3e8b6a1f2d3c4b5a69",
"parsed_by": "model",
"warnings": []
},
"meta": { "requestId": "8a7b6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d", "durationMs": 1577 }
}
Reading the response
| Field | Meaning |
|---|---|
kind | merchant, or what else the line is. Only a merchant has a merchant. |
merchant.name | The trading name, even when no website was found — many local businesses have none. |
merchant.domain | The website, when one was found with confidence of at least 0.6. At 0.8 or above, treat it as the answer. Below 0.6 it is only in candidates. |
candidates | Every domain considered, best first, including low-confidence ones. |
logo_url | Null when no website was found, or for keys without a logo token (RapidAPI). |
parsed_by | rules when the language model was unavailable and the line was read by pattern alone — a less reliable reading, flagged in warnings. |
country (where the card was used) and mcc (the merchant category code from your card data) are optional hints that help with ambiguous lines.
Credits
| Outcome | Credits |
|---|---|
| A line read and resolved | 3 |
| The same line, country and MCC looked up in the last 7 days | 1 |
include_brand=true, and a brand was returned | +10 |
| Failures | 0 |
Related
Logo CDN
logo_url behind every merchant. Free, with a monthly quota.GET /resolve
Authorizations
Your Prefetch API key. Obtain one from the dashboard.
Query Parameters
The transaction line as the bank statement or card network shows it (1–200 characters).
"SQ *BLUE BOTTLE COFFE OAKLAND CA"
Two-letter code of the country the card was used in. Helps tell local merchants apart.
"US"
The four-digit merchant category code, if your card data has it.
"5814"
Also return the merchant's brand — logos, colors, fonts — exactly as GET /brand would, when its website is found. Adds the /brand price (10 credits), charged only when a brand is returned. Can take several seconds for a site not seen before. Pass "true".