Refund to purchase
Which transaction refunds this purchase? Decision id refund_pairing, a choice. Answers: a transaction id, or "none".
Built and tested, not yet deployed. Early access.
On this page
Example
curl "$UNDERSTANDING_API_URL/v1/understand" \ -H "Authorization: Bearer $UNDERSTANDING_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "decision": "refund_pairing", "input": { "purchase": { "id": "p1", "merchant": "EVERLANE", "amount": 128, "date": "2026-10-05T18:02:00Z" }, "transactions": [ { "id": "p1", "merchant": "EVERLANE", "amount": 128, "date": "2026-10-05T18:02:00Z" }, { "id": "r0", "merchant": "EVERLANE", "amount": -20, "date": "2026-10-01T10:00:00Z" }, { "id": "r1", "merchant": "EVERLANE", "amount": -64, "date": "2026-10-12T10:00:00Z" }, { "id": "x", "merchant": "TARGET", "amount": 9, "date": "2026-10-12T11:00:00Z" } ] } }'
const base = process.env.UNDERSTANDING_API_URL; const key = process.env.UNDERSTANDING_API_KEY; const body = { decision: "refund_pairing", input: { purchase: { id: "p1", merchant: "EVERLANE", amount: 128, date: "2026-10-05T18:02:00Z", }, transactions: [ { id: "p1", merchant: "EVERLANE", amount: 128, date: "2026-10-05T18:02:00Z", }, { id: "r0", merchant: "EVERLANE", amount: -20, date: "2026-10-01T10:00:00Z", }, { id: "r1", merchant: "EVERLANE", amount: -64, date: "2026-10-12T10:00:00Z", }, { id: "x", merchant: "TARGET", amount: 9, date: "2026-10-12T11:00:00Z", }, ], }, }; const res = await fetch(`${base}/v1/understand`, { method: "POST", headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json", }, body: JSON.stringify(body), }); const result = await res.json();
import os import requests base = os.environ["UNDERSTANDING_API_URL"] key = os.environ["UNDERSTANDING_API_KEY"] body = { "decision": "refund_pairing", "input": { "purchase": { "id": "p1", "merchant": "EVERLANE", "amount": 128, "date": "2026-10-05T18:02:00Z", }, "transactions": [ { "id": "p1", "merchant": "EVERLANE", "amount": 128, "date": "2026-10-05T18:02:00Z", }, { "id": "r0", "merchant": "EVERLANE", "amount": -20, "date": "2026-10-01T10:00:00Z", }, { "id": "r1", "merchant": "EVERLANE", "amount": -64, "date": "2026-10-12T10:00:00Z", }, { "id": "x", "merchant": "TARGET", "amount": 9, "date": "2026-10-12T11:00:00Z", }, ], }, } res = requests.post( f"{base}/v1/understand", headers={"Authorization": f"Bearer {key}"}, json=body, timeout=10, ) result = res.json()
{ "decision": "refund_pairing", "type": "choice", "answer": "r1", "probability": 0.9, "reasons": [ "partial_refund", "name_match", "within_45_days", "rule_agrees" ], "abstain": false }
Input
purchasetransactionrequiredThe purchase. Its amount must be positive.
Show 6 fields
idstringrequired1 to 100 characters, unique within the list. Can’t be
"none", which means “no match”.merchantstringoptionalThe statement descriptor, 1 to 200 characters.
Also accepts
merchantName.mccstringoptionalThe four-digit merchant category code, as a string.
Also accepts
merchantCategoryCode.amountnumber or stringrequiredUS dollars: positive for a charge, negative for money back. A string such as
"$1,234.56"works too.Also accepts
usdAmount.datestringrequiredAn ISO 8601 date with a zone, for example
2026-10-05T18:00:00Z.Also accepts
createdAt.statusstringoptionalDefaults to
"approved". A"declined"charge is never a receipt’s candidate.
transactionsarray of transactionsrequiredThe card activity to search, up to 500. The purchase may be in it.
Show 6 fields
idstringrequired1 to 100 characters, unique within the list. Can’t be
"none", which means “no match”.merchantstringoptionalThe statement descriptor, 1 to 200 characters.
Also accepts
merchantName.mccstringoptionalThe four-digit merchant category code, as a string.
Also accepts
merchantCategoryCode.amountnumber or stringrequiredUS dollars: positive for a charge, negative for money back. A string such as
"$1,234.56"works too.Also accepts
usdAmount.datestringrequiredAn ISO 8601 date with a zone, for example
2026-10-05T18:00:00Z.Also accepts
createdAt.statusstringoptionalDefaults to
"approved". A"declined"charge is never a receipt’s candidate.
What our engine adds
- Only refunds can be candidates: negative amounts dated after the purchase, other than the purchase itself.
- The 30 earliest go to the model; the rest are left out and counted.
- For each candidate: the days after the purchase, the name similarity and the share of the purchase returned.
- Our engine’s own pick, so the reasons can say whether the model agrees.
What the model is asked
- Which one transaction is a refund of this purchase: a negative amount at the same merchant, after the purchase, for all or part of it. Or
none.
Reason codes
| Code | When |
|---|---|
full_refund | The share returned is within 0.5% of the purchase. |
partial_refund | Less than the purchase. |
refund_exceeds_purchase | More than the purchase. |
name_match | Name similarity of 0.7 or more. |
name_differs | Name similarity under 0.7. |
within_45_days | Refunded within 45 days of the purchase. |
over_45_days | More than 45 days after. |
no_refund | The answer is "none". |
rule_agrees | The model’s pick equals our engine’s own pick (or both say none). |
rule_differs | It doesn’t. Review these cases first. |
rule_no_refunds_after_purchase | Settled without the model: no refund after the purchase. |
model_declined | The model declined the question. |
When a rule settles it
If no transaction is a negative amount after the purchase, the answer is "none" with rule_no_refunds_after_purchase, probability 1, with no model call.
Errors
Each is a 400 with field naming the part at fault.
input.purchase must be a transaction objectinput.purchase.amount must be positive<field> must be a transaction object<field>.id must be text of 1 to 100 characters<field>.id can't be "none"<field>.merchant must be text of 1 to 200 characters<field>.mcc must be a four-digit merchant category code<field>.amount must be an amount in US dollars<field>.date must be an ISO 8601 dateinput.transactions must be a list of up to 500 transactionsinput.transactions ids must be unique
Evaluation
The Understanding API hasn’t been run on our eval yet. Evaluation
# Refund to purchase
Which transaction refunds this purchase? Decision id `refund_pairing`, a choice. Answers: a transaction `id`, or `"none"`.
Built and tested, not yet deployed. Early access.
## Example
The request in cURL:
```bash
curl "$UNDERSTANDING_API_URL/v1/understand" \
-H "Authorization: Bearer $UNDERSTANDING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "refund_pairing",
"input": {
"purchase": {
"id": "p1",
"merchant": "EVERLANE",
"amount": 128,
"date": "2026-10-05T18:02:00Z"
},
"transactions": [
{
"id": "p1",
"merchant": "EVERLANE",
"amount": 128,
"date": "2026-10-05T18:02:00Z"
},
{
"id": "r0",
"merchant": "EVERLANE",
"amount": -20,
"date": "2026-10-01T10:00:00Z"
},
{
"id": "r1",
"merchant": "EVERLANE",
"amount": -64,
"date": "2026-10-12T10:00:00Z"
},
{
"id": "x",
"merchant": "TARGET",
"amount": 9,
"date": "2026-10-12T11:00:00Z"
}
]
}
}'
```
The request in TypeScript:
```typescript
const base = process.env.UNDERSTANDING_API_URL;
const key = process.env.UNDERSTANDING_API_KEY;
const body = {
decision: "refund_pairing",
input: {
purchase: {
id: "p1",
merchant: "EVERLANE",
amount: 128,
date: "2026-10-05T18:02:00Z",
},
transactions: [
{
id: "p1",
merchant: "EVERLANE",
amount: 128,
date: "2026-10-05T18:02:00Z",
},
{
id: "r0",
merchant: "EVERLANE",
amount: -20,
date: "2026-10-01T10:00:00Z",
},
{
id: "r1",
merchant: "EVERLANE",
amount: -64,
date: "2026-10-12T10:00:00Z",
},
{
id: "x",
merchant: "TARGET",
amount: 9,
date: "2026-10-12T11:00:00Z",
},
],
},
};
const res = await fetch(`${base}/v1/understand`, {
method: "POST",
headers: {
Authorization: `Bearer ${key}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
const result = await res.json();
```
The request in Python:
```python
import os
import requests
base = os.environ["UNDERSTANDING_API_URL"]
key = os.environ["UNDERSTANDING_API_KEY"]
body = {
"decision": "refund_pairing",
"input": {
"purchase": {
"id": "p1",
"merchant": "EVERLANE",
"amount": 128,
"date": "2026-10-05T18:02:00Z",
},
"transactions": [
{
"id": "p1",
"merchant": "EVERLANE",
"amount": 128,
"date": "2026-10-05T18:02:00Z",
},
{
"id": "r0",
"merchant": "EVERLANE",
"amount": -20,
"date": "2026-10-01T10:00:00Z",
},
{
"id": "r1",
"merchant": "EVERLANE",
"amount": -64,
"date": "2026-10-12T10:00:00Z",
},
{
"id": "x",
"merchant": "TARGET",
"amount": 9,
"date": "2026-10-12T11:00:00Z",
},
],
},
}
res = requests.post(
f"{base}/v1/understand",
headers={"Authorization": f"Bearer {key}"},
json=body,
timeout=10,
)
result = res.json()
```
Response: 200 OK (the probability is a stand-in)
```json
{
"decision": "refund_pairing",
"type": "choice",
"answer": "r1",
"probability": 0.9,
"reasons": [
"partial_refund",
"name_match",
"within_45_days",
"rule_agrees"
],
"abstain": false
}
```
## Input
- `purchase` (transaction, required): The purchase. Its amount must be positive. Also accepts `merchantName`.
- `id` (string, required): 1 to 100 characters, unique within the list. Can’t be `"none"`, which means “no match”.
- `merchant` (string, optional): The statement descriptor, 1 to 200 characters. Also accepts `merchantName`.
- `mcc` (string, optional): The four-digit merchant category code, as a string. Also accepts `merchantCategoryCode`.
- `amount` (number or string, required): US dollars: positive for a charge, negative for money back. A string such as `"$1,234.56"` works too. Also accepts `usdAmount`.
- `date` (string, required): An ISO 8601 date with a zone, for example `2026-10-05T18:00:00Z`. Also accepts `createdAt`.
- `status` (string, optional): Defaults to `"approved"`. A `"declined"` charge is never a receipt’s candidate.
- `transactions` (array of transactions, required): The card activity to search, up to 500. The purchase may be in it. Also accepts `merchantName`.
- `id` (string, required): 1 to 100 characters, unique within the list. Can’t be `"none"`, which means “no match”.
- `merchant` (string, optional): The statement descriptor, 1 to 200 characters. Also accepts `merchantName`.
- `mcc` (string, optional): The four-digit merchant category code, as a string. Also accepts `merchantCategoryCode`.
- `amount` (number or string, required): US dollars: positive for a charge, negative for money back. A string such as `"$1,234.56"` works too. Also accepts `usdAmount`.
- `date` (string, required): An ISO 8601 date with a zone, for example `2026-10-05T18:00:00Z`. Also accepts `createdAt`.
- `status` (string, optional): Defaults to `"approved"`. A `"declined"` charge is never a receipt’s candidate.
## What our engine adds
- Only refunds can be candidates: negative amounts dated after the purchase, other than the purchase itself.
- The 30 earliest go to the model; the rest are left out and counted.
- For each candidate: the days after the purchase, the name similarity and the share of the purchase returned.
- Our engine’s own pick, so the reasons can say whether the model agrees.
## What the model is asked
- Which one transaction is a refund of this purchase: a negative amount at the same merchant, after the purchase, for all or part of it. Or `none`.
## Reason codes
| Code | When |
| --- | --- |
| `full_refund` | The share returned is within 0.5% of the purchase. |
| `partial_refund` | Less than the purchase. |
| `refund_exceeds_purchase` | More than the purchase. |
| `name_match` | Name similarity of 0.7 or more. |
| `name_differs` | Name similarity under 0.7. |
| `within_45_days` | Refunded within 45 days of the purchase. |
| `over_45_days` | More than 45 days after. |
| `no_refund` | The answer is `"none"`. |
| `rule_agrees` | The model’s pick equals our engine’s own pick (or both say none). |
| `rule_differs` | It doesn’t. Review these cases first. |
| `rule_no_refunds_after_purchase` | Settled without the model: no refund after the purchase. |
| `model_declined` | The model declined the question. |
## When a rule settles it
If no transaction is a negative amount after the purchase, the answer is `"none"` with `rule_no_refunds_after_purchase`, probability 1, with no model call.
## Errors
Each is a 400 with `field` naming the part at fault.
- `input.purchase must be a transaction object`
- `input.purchase.amount must be positive`
- `<field> must be a transaction object`
- `<field>.id must be text of 1 to 100 characters`
- `<field>.id can't be "none"`
- `<field>.merchant must be text of 1 to 200 characters`
- `<field>.mcc must be a four-digit merchant category code`
- `<field>.amount must be an amount in US dollars`
- `<field>.date must be an ISO 8601 date`
- `input.transactions must be a list of up to 500 transactions`
- `input.transactions ids must be unique`
## Evaluation
The Understanding API hasn’t been run on our eval yet. [Evaluation](/api/docs/evaluation)
Source: /api/docs/decisions/refund-pairing