> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/sdgm/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/sdgm/_mcp/server.

# Payback Abuse Detection Solution

Payback abuse happens on buy-now-pay-later platforms when a customer places an order on credit and never repays the balance. This example scores existing orders using resolved abuse labels, predicts unpaid balances conditional on a future ledger entry, and flags accounts likely to place an abusive order. Kumo Engine learns from the order or account details and connected payment history.

## Data and relationships

The example assumes a prepared Kumo Engine `graph`, a matching `snapshot`, and these tables:

| Table      | Required columns                                                                                 | Purpose                                                                                                                                                           |
| ---------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `orders`   | `order_id` as the primary key, plus `account_id`, `order_date`, `order_value`, and `fraud_label` | The credit orders. `fraud_label` records a resolved order's outcome, where `1` means abusive and `0` means repaid.                                                |
| `payments` | `payment_id` as the primary key, plus `order_id`, `payment_date`, and `outstanding_amt`          | The repayment ledger. Each order starts with a record whose `outstanding_amt` equals the order value, and later records lower it toward `0` as the customer pays. |
| `accounts` | `account_id` as the primary key                                                                  | The account each order belongs to, and the entity the account-level query scores.                                                                                 |

Connect `payments.order_id` to `orders.order_id` and `orders.account_id` to `accounts.account_id`. Mark `order_date` as the time column of the orders table and `order_id` as its primary key, and mark `payment_date` as the time column of the payments table. These time columns place every row in time, so each prediction is trained and scored using only information recorded before the point it looks ahead from. `fraud_label` is the value the first and third queries predict, so it is a label rather than a feature. There is no direct foreign key from `payments` to `accounts`, so a payment-ledger query has to run over orders rather than over accounts.

## Score each order for payback abuse

This query scores each order for whether it is abusive using a label your team has already resolved. The target `orders.fraud_label = 1` turns the recorded outcome into a yes or no label, and `FOR EACH orders.order_id` produces one prediction per order. Because the orders table is anchored at `order_date`, the model learns from the account and payment history that exists when the order is placed. Predict the comparison `fraud_label = 1` rather than the raw `fraud_label` column, which Kumo Engine reads as a numeric target and scores as a regression.

```python
from kumo.engine import PredictiveQuery

query_text = (
    "PREDICT orders.fraud_label = 1 "
    "FOR EACH orders.order_id"
)
query = PredictiveQuery(graph, query_text)
query.validate()
print(query.get_task_type())  # binary_classification
```

## Predict the last recorded balance status

This query predicts whether the last balance recorded in the next 30 days is nonzero, conditional on a ledger entry in that window. Orders with no future entry supply no training label; an initial balance at or before scoring is not enough.

```python
query_text = (
    "PREDICT LAST(payments.outstanding_amt, 0, 30, days) != 0 "
    "FOR EACH orders.order_id"
)
query = PredictiveQuery(graph, query_text)
query.validate()
print(query.get_task_type())  # binary_classification
```

## Predict future abuse risk for an account

Scoring an order helps once it exists, but teams also want to set credit limits and hold reviews before an account places its next order. This query looks ahead for each account and predicts whether it will place an abusive order in the next 30 days. `SUM(orders.fraud_label, 0, 30, days)` adds up the abuse labels of the orders the account places over the 30 days that follow the scoring time, and `> 0` turns that into a yes or no label. Because repaid orders carry a label of `0`, only an abusive one moves the sum above zero.

```python
query_text = (
    "PREDICT SUM(orders.fraud_label, 0, 30, days) > 0 "
    "FOR EACH accounts.account_id"
)
query = PredictiveQuery(graph, query_text)
query.validate()
print(query.get_task_type())  # binary_classification
```

## Reading the predictions

The order-scoring query estimates abuse probability for review prioritization. The balance query estimates whether the last future ledger entry shows money owed; it does not cover nonpayment with no future entry. The account-level query estimates future abuse risk to inform credit limits and verification.

All three are estimates from past behavior, not guarantees. The order score is anchored at the moment each order is placed, and the two forward-looking queries are anchored at the time you run them, so in every case the model uses only information recorded before that anchor and never sees the outcome it predicts. The 30-day window on the forward-looking queries is a starting point; widen or narrow the number of days to match how far ahead your team needs to act. Refresh the predictions as new orders and payments arrive so each decision reflects the latest history.