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()
    Response

    200 OKStand-in probability1

    {
      "decision": "refund_pairing",
      "type": "choice",
      "answer": "r1",
      "probability": 0.9,
      "reasons": [
        "partial_refund",
        "name_match",
        "within_45_days",
        "rule_agrees"
      ],
      "abstain": false
    }

    Input

    • purchasetransactionrequired

      The purchase. Its amount must be positive.

      Show 6 fields
      • idstringrequired

        1 to 100 characters, unique within the list. Can’t be "none", which means “no match”.

      • merchantstringoptional

        The statement descriptor, 1 to 200 characters.

        Also accepts merchantName.

      • mccstringoptional

        The four-digit merchant category code, as a string.

        Also accepts merchantCategoryCode.

      • amountnumber or stringrequired

        US dollars: positive for a charge, negative for money back. A string such as "$1,234.56" works too.

        Also accepts usdAmount.

      • datestringrequired

        An ISO 8601 date with a zone, for example 2026-10-05T18:00:00Z.

        Also accepts createdAt.

      • statusstringoptional

        Defaults to "approved". A "declined" charge is never a receipt’s candidate.

    • transactionsarray of transactionsrequired

      The card activity to search, up to 500. The purchase may be in it.

      Show 6 fields
      • idstringrequired

        1 to 100 characters, unique within the list. Can’t be "none", which means “no match”.

      • merchantstringoptional

        The statement descriptor, 1 to 200 characters.

        Also accepts merchantName.

      • mccstringoptional

        The four-digit merchant category code, as a string.

        Also accepts merchantCategoryCode.

      • amountnumber or stringrequired

        US dollars: positive for a charge, negative for money back. A string such as "$1,234.56" works too.

        Also accepts usdAmount.

      • datestringrequired

        An ISO 8601 date with a zone, for example 2026-10-05T18:00:00Z.

        Also accepts createdAt.

      • statusstringoptional

        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

    Reason codes for Refund to purchase
    CodeWhen
    full_refundThe share returned is within 0.5% of the purchase.
    partial_refundLess than the purchase.
    refund_exceeds_purchaseMore than the purchase.
    name_matchName similarity of 0.7 or more.
    name_differsName similarity under 0.7.
    within_45_daysRefunded within 45 days of the purchase.
    over_45_daysMore than 45 days after.
    no_refundThe answer is "none".
    rule_agreesThe model’s pick equals our engine’s own pick (or both say none).
    rule_differsIt doesn’t. Review these cases first.
    rule_no_refunds_after_purchaseSettled without the model: no refund after the purchase.
    model_declinedThe 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