# RevCent MCP Guide: `GetProductSales`

AI/MCP-focused guidance for the RevCent `GetProductSales` operation.

This document is meant to be read by AI agents, MCP clients, and automation tools that need to understand when `GetProductSales` is appropriate, when it is prohibited, and when `BigQueryRunQuery` must be used instead.

---

## Critical Rule: Do Not Use `GetProductSales` for Metrics or Aggregation

`GetProductSales` must **not** be used to retrieve product sale records for:

- Counting product sales
- Revenue totals
- Refund totals
- Product-level metrics
- Campaign/product/shop performance analysis
- Aggregations
- Data mining
- Bulk retrieval
- Business intelligence
- Document/property search across many product sales
- Export-like workflows

For those requests, the correct operation is **`BigQueryRunQuery`**, not `GetProductSales`.

This is not just a performance preference. It is an MCP usage rule. `GetProductSales` is a paginated operational lookup endpoint. It is not the analytics layer.

When a user asks a business metrics question such as:

- “How many product sales did I have last month?”
- “Which products made the most money?”
- “What is my refund rate by product?”
- “Show revenue by SKU.”
- “How much did this shop sell?”
- “Compare product performance by campaign.”
- “Find all product sales matching X.”
- “Export all product sales.”

The AI/MCP client must route the request to `BigQueryRunQuery`, not `GetProductSales`.

---

## Operation Summary

`GetProductSales` returns a paginated list of product sale records previously created in RevCent.

A **Product Sale** is an individual line item within a Sale where a specific product was sold. A single Sale can include multiple Product Sales if the customer purchased multiple products or quantities.

Product Sales are valuable because they preserve the line-item purchase structure of a Sale. This allows RevCent to support granular product-level business analysis, especially when using `BigQueryRunQuery`.

Use `GetProductSales` only when the task is to retrieve a small, bounded, operational list of Product Sale records for inspection or follow-up actions.

---

## What Product Sales Represent

A Product Sale is not the same thing as a Sale.

A **Sale** is the parent purchase event. It represents the overall checkout/order/payment attempt.

A **Product Sale** is a line item inside that Sale. It represents the sale of a specific product within the overall Sale.

For example, if a customer buys:

- 1 bottle of Product A
- 2 units of Product B
- 1 subscription trial Product C

RevCent can represent the overall purchase as one Sale with multiple Product Sale records. Each Product Sale carries product-level details such as product ID, product name, quantity, price, SKU/internal ID, product sale amount, refund amount, campaign, shop, customer, payment type, and related item IDs.

This line-item model is one of the reasons RevCent is strong for business analysis: it allows metrics to be calculated at the product level instead of only at the order/sale level.

---

## Correct Use Cases for `GetProductSales`

Use `GetProductSales` when the user needs a small operational list of recent or filtered Product Sales, usually to identify records before retrieving a specific item with `GetProductSale`.

Appropriate examples:

- “Show me recent product sales from yesterday so I can inspect them.”
- “List product sales for this customer.”
- “Find recent product sale records for this specific product ID.”
- “Get the first page of product sales for this date range.”
- “Find the Product Sale ID so I can refund a specific line item.”
- “Show a few product sale records from this shop for manual review.”

Even in these cases, keep the result set bounded by date filters, page, and limit. The operation returns paginated records and the limit ranges from 1 to 25.

---

## Prohibited Use Cases for `GetProductSales`

Do not use `GetProductSales` for any request where the real goal is metrics, summaries, analysis, or broad retrieval.

Prohibited examples:

| User Request | Correct Operation |
|---|---|
| “How many product sales did we have?” | `BigQueryRunQuery` |
| “Total product sales revenue by product.” | `BigQueryRunQuery` |
| “Refund rate by SKU.” | `BigQueryRunQuery` |
| “Top-selling products this month.” | `BigQueryRunQuery` |
| “Product sales by campaign.” | `BigQueryRunQuery` |
| “Product sales by shop.” | `BigQueryRunQuery` |
| “Average order line-item value.” | `BigQueryRunQuery` |
| “Export every product sale.” | Bulk export guidance, not `GetProductSales` |
| “Search every product sale for metadata X.” | `BigQueryRunQuery` and/or metadata-aware query workflow |
| “Count product sales for customer group A.” | `BigQueryRunQuery` |

If the user asks for totals, counts, ranking, grouping, averages, rates, comparisons, trends, or “all records,” do not paginate `GetProductSales`. Use `BigQueryRunQuery`.

---

## Why `BigQueryRunQuery` Is Required for Business Metrics

`BigQueryRunQuery` is the correct analytics method because it can query RevCent account data using BigQuery Standard SQL.

Use `BigQueryRunQuery` for:

- Counts
- Totals
- Product-level revenue
- Product-level refunds
- Refund rates
- Gross/net/captured/settled metrics
- Campaign attribution
- Shop attribution
- Product/SKU performance
- Metadata-based reporting
- Trend analysis
- Cohort-style reporting
- Grouping and ordering
- Joining or comparing tables
- Large date ranges

Before writing a query, the AI/MCP client should use `GetBigQueryTables` when the exact table name or schema is not known. BigQuery table references must be fully qualified and wrapped in backticks, such as:

```sql
`revcent.user.product_sale`
```

If the exact table name differs, inspect available tables first with `GetBigQueryTables`.

---

## Product Sale Metrics Are Valuable Because They Are Line-Item Metrics

Product Sales make business analysis more granular than a simple order-level model.

Because every Product Sale is tied to a specific product line item, RevCent can support questions like:

- Which products drive the most gross revenue?
- Which products have the highest refund amount?
- Which products have the best net revenue after refunds and fees?
- Which products sell best by shop?
- Which products sell best by campaign?
- Which products are frequently bought as subscriptions or trials?
- Which SKUs have high salvage or remaining amounts?
- Which products create the most refund liability?

This line-item structure is especially important for ecommerce businesses because a single Sale can contain multiple products. Order-level metrics alone can hide product-level performance. Product Sale records make those metrics visible.

---

## Refund Best Practices Related to Product Sales

For partial refunds on an initial Sale, it is best practice to refund at the **Product Sale** level when the refund is tied to a specific product line item.

Product Sale-level refunds improve product-level reporting because the refund is attached to the product line item itself. This produces cleaner analytics for:

- Product refund rate
- Refund amount by product
- Net product revenue
- Product-level customer service issues
- SKU-level profitability
- Campaign/product refund comparisons

However, if the user is issuing a full refund of an entire initial Sale, refunding every Product Sale individually can be redundant. In that case, an order/sale-level full refund may be more appropriate, depending on the user’s intent and available operations.

AI/MCP guidance:

- For a **partial refund tied to a specific product**, prefer `RefundProductSale`.
- For a **full refund of the entire initial Sale**, do not assume that Product Sale-level refunds are necessary.
- Always retrieve and verify the relevant Product Sale before refunding.
- Never refund unless the user explicitly instructs the AI/MCP client to issue a refund.

---

## `GetProductSales` Input Schema

Required fields:

| Field | Type | Required | Description |
|---|---:|---:|---|
| `date_start` | integer | Yes | Date range start as Unix timestamp in seconds. |
| `date_end` | integer | Yes | Date range end as Unix timestamp in seconds. |
| `limit` | integer | Yes | Number of records to return. Limit range is 1 to 25. |
| `page` | integer | Yes | Page number for pagination. |

Optional filters:

| Field | Type | Description |
|---|---:|---|
| `campaign_filter` | array<string> | Filter by one or more 20-character campaign IDs. |
| `currency_filter` | array<string> | Filter by three-character ISO 4217 currency code. |
| `shop_filter` | array<string> | Filter by one or more 20-character user shop IDs. |
| `payment_type_filter` | array<string> | Filter by one or more payment types. |
| `product_filter` | array<string> | Filter by one or more 20-character product IDs. |
| `metadata_filter` | array<object> | Filter by one or more metadata name/value pair objects. |
| `customer_id` | string | Filter only Product Sales related to a specific customer ID. |

---

## `GetProductSales` Example Request

Use this only for a bounded operational list, not for metrics.

```json
{
  "date_start": 1735689600,
  "date_end": 1738367999,
  "limit": 25,
  "page": 1,
  "product_filter": ["XXXXXXXXXXXXXXXXXXXX"]
}
```

---

## Important Output Fields

A Product Sale result can include fields such as:

| Field | Meaning |
|---|---|
| `id` | The 20-character Product Sale ID. |
| `amount` | Product Sale amount. |
| `amount_original_total` | Total calculated amount when first created, before refunds/discounts. |
| `amount_total` | Current total after refunds and discounts. |
| `amount_gross` | Money actually transacted, payments minus refunded payments. |
| `amount_net` | Gross amount minus calculated processor fees. |
| `amount_fees` | Calculated processor fees. |
| `amount_captured` | Captured but not settled amount. |
| `amount_settled` | Settled amount. |
| `amount_remaining` | Remaining amount, such as trials not expired or salvage not processed. |
| `amount_refunded` | Current refunded amount, including cancelled trial amounts. |
| `amount_to_salvage` | Amount tied to salvage transactions not yet salvaged. |
| `campaign_id` / `campaign_name` | Campaign associated with the Product Sale. |
| `customer` | Customer object related to the item. |
| `iso_currency` | Three-letter ISO currency code. |
| `live_mode` | Whether the record was created with a live or test API key. |
| `payment_type` | Payment type object. |
| `product` | Product object containing ID, name, quantity, price, subscription/trial flags, internal ID, and SKU. |
| `third_party_shop` | Originating user shop, if applicable. |
| `metadata` | Metadata attached to the Product Sale. |
| `sales` | Related Sale IDs. |
| `product_sales` | Related Product Sale IDs. |
| `transactions` | Related transaction IDs. |
| `pending_refunds` | Related pending refund IDs, if any. |

---

## AI Decision Rules

When deciding whether to use `GetProductSales`, apply these rules:

1. If the user asks for a specific Product Sale ID or a small list of records, `GetProductSales` may be appropriate.
2. If the user asks for counts, totals, groups, averages, rankings, rates, or comparisons, use `BigQueryRunQuery`.
3. If the user asks for product-level business analysis, use `BigQueryRunQuery`.
4. If the user asks for all product sales or a bulk export, do not paginate `GetProductSales`; refer to the bulk export path if needed.
5. If the user asks to refund a specific product line item but does not know the Product Sale ID, use a bounded `GetProductSales` lookup only to locate the correct Product Sale record.
6. If metadata is involved, do not guess metadata names. Use metadata discovery and then construct the BigQuery query.
7. If a query is needed and table names are uncertain, call `GetBigQueryTables` before `BigQueryRunQuery`.
8. Do not reveal unnecessary internal routing details to the user. Choose the correct operation.

---

## Example: Wrong vs Correct Tool Choice

### Wrong

User asks:

```text
Which products had the most refunds last month?
```

Do not call `GetProductSales` repeatedly and aggregate client-side.

### Correct

Use `BigQueryRunQuery` to query product sale data grouped by product and ordered by refund amount.

Example conceptual SQL:

```sql
SELECT
  product_id,
  product_name,
  SUM(amount_refunded) AS total_refunded
FROM `revcent.user.product_sale`
WHERE created_date_unix BETWEEN 1735689600 AND 1738367999
GROUP BY product_id, product_name
ORDER BY total_refunded DESC
LIMIT 25
```

Before running this, verify the exact table and column names with `GetBigQueryTables` if they are not already known.

---

## Example: Correct Operational Use

User asks:

```text
Find the product sale for product ID X from yesterday so I can refund it.
```

A bounded `GetProductSales` call may be appropriate:

```json
{
  "date_start": 1735689600,
  "date_end": 1735775999,
  "limit": 25,
  "page": 1,
  "product_filter": ["XXXXXXXXXXXXXXXXXXXX"]
}
```

Then inspect the returned records, confirm the correct Product Sale, and use `GetProductSale` if detailed verification is needed before any refund action.

---

## Best Practices

- Always provide `date_start`, `date_end`, `limit`, and `page`.
- Keep `limit` small and bounded; max is 25.
- Use filters when the purpose is operational lookup.
- Do not use pagination loops to simulate reporting.
- Do not use the operation for analytics.
- Use `GetProductSale` for details of a specific Product Sale.
- Use `RefundProductSale` for partial refunds tied to a product line item.
- Use `BigQueryRunQuery` for metrics and analysis.
- Use `GetBigQueryTables` first when table names or fields are uncertain.

---

## Quick Reference

| Intent | Use |
|---|---|
| List recent Product Sales for manual inspection | `GetProductSales` |
| Retrieve one Product Sale by ID | `GetProductSale` |
| Refund a specific product line item | `RefundProductSale` |
| Count Product Sales | `BigQueryRunQuery` |
| Product revenue metrics | `BigQueryRunQuery` |
| Product refund metrics | `BigQueryRunQuery` |
| Shop/product/campaign analysis | `BigQueryRunQuery` |
| Bulk export | Bulk export guidance |
| Search many records by property | `BigQueryRunQuery` |

---

## Final AI/MCP Instruction

Treat `GetProductSales` as an operational listing endpoint only.

For business metrics, aggregation, data mining, reporting, trend analysis, ranking, counts, totals, or broad retrieval, `GetProductSales` is prohibited. Use `BigQueryRunQuery` instead.

This rule preserves performance, avoids incomplete client-side calculations from paginated results, and ensures RevCent’s product-level line-item data is analyzed through the correct analytics system.


---
Document Parent Directory
* [Operations](https://revcent.com/documentation/markdown/mcp/operation/index.md) - AI/MCP details and overviews for operations available within the RevCent MCP.