# RevCent MCP Guide: `EstimateSale`

AI/MCP-focused guide for the RevCent `EstimateSale` operation.

This document is meant to be read by AI agents, MCP clients, automation tools, and developers that need to estimate a Sale before payment is processed, especially for checkout/cart display, pending Sale workflows, upsell funnels, and customer-facing total previews.

---

## Related Documentation Link

For broader Sale lifecycle context, see the Sales Overview:

```text
https://revcent.com/documentation/markdown/mcp/operation/OverviewSale.md
```

The Sales Overview explains how Sales relate to Product Sales, shipments, tax, discounts, customers, subscriptions, trials, fulfillment, events, AI workflows, refunds, and reporting rules.

---

## Operation Summary

`EstimateSale` estimates the total cost of a Sale with itemized results.

The MCP operation description states that `EstimateSale`:

- Estimates the total cost with itemized results.
- Includes products, shipping, tax, coupons, and discounts.
- Uses the same general request object as a Sale create request.
- Does **not** process payment.
- Returns detailed information useful for displaying to a customer during checkout.
- Can show how much the customer will save due to discounts.
- Can estimate a previously created pending Sale by `sale_id`.

`EstimateSale` is a preview and calculation operation. It should be used before a customer is charged when the business needs to show totals, validate coupons, display discounts, calculate tax/shipping totals, or confirm the customer-facing checkout amount.

---

## Critical Rule: No Payment Is Processed

`EstimateSale` does **not** process payment.

It is safe to use for:

- Checkout previews
- Cart previews
- Pending Sale previews
- Coupon validation
- Discount display
- Shipping/tax display
- Final total confirmation before `CreateSale` or `ProcessPendingSale`

Do not tell the user that a Sale has been created or payment has been processed after `EstimateSale`.

---

## Why Use `EstimateSale`?

Use `EstimateSale` whenever the customer, AI workflow, frontend checkout, support rep, or voice agent needs to know what a Sale would cost before charging.

Common reasons:

| Reason | Why It Helps |
|---|---|
| Show checkout total | Lets the customer see the amount before payment. |
| Validate coupons | Shows valid and invalid coupon results. |
| Display savings | Shows discount amounts and total amount after discounts. |
| Preview shipping | Shows shipping entries and discounted shipping totals. |
| Preview tax | Shows tax itemization and total tax amount. |
| Preview products | Shows product totals, quantities, discounts, and max quantity allowed. |
| Preview pending Sale | Estimate a stored pending Sale by `sale_id`. |
| Confirm final funnel total | Useful before processing upsell/order-bump funnels. |
| Support-assisted checkout | Support can explain totals before processing payment. |
| AI Voice Agent checkout | Voice agent can read a total to the customer before asking for consent. |
| AI Assistant recovery | Assistant can estimate the recovered Sale before payment. |
| Gateway preview | Optionally request a future credit-card gateway when `include_gateway` is used. |

---

## Where `EstimateSale` Fits in the Sale Lifecycle

### Immediate Sale Flow

```text
EstimateSale
    ↓
CreateSale
```

Use this when the checkout flow needs to show the total before creating and charging a Sale immediately.

### Pending Sale Flow

```text
CreatePendingSale
    ↓
UpdatePendingSale
    ↓
EstimateSale
    ↓
ProcessPendingSale
```

Use this when a pending Sale acts like a cart and the business needs to preview totals before payment is processed.

### AI/Voice Recovery Flow

```text
GetSale or known pending sale_id
    ↓
UpdatePendingSale if needed
    ↓
EstimateSale
    ↓
Customer/user confirms
    ↓
ProcessPendingSale
```

Use this when an AI Assistant, AI Voice Agent, support rep, or recovery workflow needs to show the customer what they will pay before processing payment.

---

## Schema Summary

Operation:

```text
name: EstimateSale
title: Estimate A Sale
description: Estimate the total cost with itemized results including products, shipping, tax, coupons, and discounts.
input type: object
additionalProperties: false
```

The schema says:

```text
Provide the same request object as a normal sale, or the sale_id for a previously created pending sale.
```

Required input:

```text
product
```

Important nuance:

- If `sale_id` is provided, it estimates a previously created pending Sale.
- The schema description says if `sale_id` is provided, all other properties are optional.
- If estimating a new prospective Sale rather than an existing pending Sale, provide `product` and any other Sale details needed for the estimate.

---

## Full Input Schema

| Field | Type | Required | Description |
|---|---:|---:|---|
| `sale_id` | string | No | Optional RevCent Sale ID if estimating a previously created pending Sale. If provided, all other properties are optional. |
| `campaign` | string | No | 20-character Campaign ID. |
| `iso_currency` | string | No | Three-character ISO 4217 currency code. |
| `include_gateway` | boolean | No | Only provide if a specific gateway should be returned for a future Sale request. Default is false. |
| `payment_type` | string enum | Conditional | If `include_gateway` is true, payment type must be `credit_card`. |
| `payment_profile` | string | Conditional | If `include_gateway` is true, provide a next-gen Payment Profile ID. Only next-gen profiles are supported. |
| `customer_id` | string | No | Optional RevCent Customer ID when estimating a Sale on behalf of a specific customer. |
| `credit_card` | object | Conditional | If `include_gateway` is true and not providing an existing customer ID for a customer with a saved card. |
| `customer` | object | No | Customer object. |
| `bill_to` | object | No | Billing information. If not present, `customer` is used. |
| `ship_to` | object | No | Shipping destination. If not present, `customer` or `bill_to` is used in priority order. |
| `product` | array<object> | Yes, unless `sale_id` is used | Products to include in the Sale estimate. |
| `shipping` | array<object> | No | Shipping entries to include in the estimate. |
| `tax` | array<object> | No | Tax entries to include in the estimate. |
| `coupon` | array<object> | No | Coupon codes to apply and validate in the estimate. |
| `discount` | array<object> | No | Static discount entries to apply in the estimate. |

---

## Estimating a Pending Sale With `sale_id`

Use `sale_id` when estimating a pending Sale that already exists in RevCent.

The schema says:

```text
sale_id: An optional RevCent sale ID if estimating a previously created pending sale. If provided, all other properties are optional.
```

Example:

```json
{
  "sale_id": "XXXXXXXXXXXXXXXXXXXX"
}
```

Use this after:

- `CreatePendingSale`
- `UpdatePendingSale`
- A cart/funnel update
- An AI or voice recovery update

This is the safest way to estimate the actual current state of a pending Sale before calling `ProcessPendingSale`.

---

## New Estimate Request Example

Use this when estimating a prospective Sale before creating it.

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "iso_currency": "USD",
  "customer": {
    "first_name": "Jane",
    "last_name": "Customer",
    "email": "jane@example.com"
  },
  "product": [
    {
      "id": "XXXXXXXXXXXXXXXXXXXX",
      "quantity": 2
    }
  ],
  "shipping": [
    {
      "amount": 6.95,
      "provider": "usps",
      "provider_method": "priority",
      "name": "USPS Priority"
    }
  ],
  "tax": [
    {
      "amount": 3.25,
      "name": "Sales Tax"
    }
  ],
  "coupon": [
    {
      "coupon_code": "SPRING20"
    }
  ]
}
```

---

## `include_gateway` Behavior

`include_gateway` is optional.

Use it only if the client wants `EstimateSale` to return a specific gateway to be used in a future Sale request.

The schema states:

- `include_gateway` should only be provided if you want to return a specific gateway for a future Sale request.
- `payment_type` must be `credit_card`.
- `payment_profile` must be a next-gen Payment Profile ID.
- Only next-gen profiles are supported.
- Default is `false`.

Required when `include_gateway` is true:

```json
{
  "include_gateway": true,
  "payment_type": "credit_card",
  "payment_profile": "XXXXXXXXXXXXXXXXXXXX"
}
```

If not using gateway selection/preview, omit these fields.

---

## `credit_card` Object Schema

`credit_card` is only relevant when `include_gateway` is true and the request is not using an existing customer ID with a saved card.

`credit_card` has:

```text
additionalProperties: false
required:
  - card_number
  - exp_month
  - exp_year
```

| Field | Type | Required | Description |
|---|---:|---:|---|
| `card_number` | string | Yes | Full credit card number. |
| `exp_month` | integer | Yes | Expiration month as one or two digit integer. |
| `exp_year` | integer | Yes | Expiration year as two digit integer. |
| `card_code` | string | No | Credit card code. Length varies by card type. |

Credit card data is sensitive. AI/MCP clients should only pass card data through secure, approved payment collection workflows.

---

## Customer and Address Objects

### `customer`

`customer` has:

```text
additionalProperties: false
required when object is provided:
  - first_name
  - last_name
  - email
```

Fields:

| Field | Type | Required |
|---|---:|---:|
| `first_name` | string | Yes |
| `last_name` | string | Yes |
| `email` | string/email | Yes |
| `address_line_1` | string | No |
| `address_line_2` | string | No |
| `city` | string | No |
| `state` | string | No |
| `zip` | string | No |
| `country` | string | No |
| `company` | string | No |
| `phone` | string | No |

### `bill_to`

Use `bill_to` when billing details differ from the customer object. If not present, `customer` is used.

Required if provided:

```text
first_name
last_name
email
```

### `ship_to`

Use `ship_to` when shipping details differ from customer or billing details. If not present, `customer` or `bill_to` is used in priority order.

Required if provided:

```text
first_name
last_name
email
```

---

## Product Array Schema

`product` is required when estimating a new Sale and not using `sale_id`.

Each product object has:

```text
additionalProperties: false
required:
  - id
```

| Field | Type | Required | Description |
|---|---:|---:|---|
| `id` | string | Yes | 20-character Product ID. |
| `quantity` | integer | No | Quantity being purchased. Default is 1. |
| `price` | number | No | Price to charge if different from the product default price in RevCent. |

Example:

```json
{
  "product": [
    {
      "id": "XXXXXXXXXXXXXXXXXXXX",
      "quantity": 2
    },
    {
      "id": "YYYYYYYYYYYYYYYYYYYY",
      "quantity": 1,
      "price": 19.95
    }
  ]
}
```

---

## Shipping Array Schema

`shipping` is optional.

Each shipping object has:

```text
additionalProperties: false
required:
  - amount
```

| Field | Type | Required | Description |
|---|---:|---:|---|
| `amount` | number | Yes | Amount to charge for the shipping entry. Can be 0. |
| `provider` | string | No | Shipping provider. |
| `provider_method` | string | No | Shipping provider method corresponding to the provider. |
| `name` | string | No | Optional shipping entry name. |
| `description` | string | No | Optional shipping entry description. |

Example:

```json
{
  "shipping": [
    {
      "amount": 6.95,
      "provider": "usps",
      "provider_method": "priority",
      "name": "USPS Priority"
    }
  ]
}
```

---

## Tax Array Schema

`tax` is optional.

Each tax object has:

```text
additionalProperties: false
required:
  - amount
```

| Field | Type | Required | Description |
|---|---:|---:|---|
| `amount` | number | Yes | Amount to charge for the tax entry. |
| `name` | string | No | Optional tax entry name. |
| `description` | string | No | Optional tax entry description. |

Example:

```json
{
  "tax": [
    {
      "amount": 3.25,
      "name": "Sales Tax",
      "description": "NY sales tax"
    }
  ]
}
```

---

## Coupon Array Schema

`coupon` is optional.

Each coupon object has:

```text
additionalProperties: false
required:
  - coupon_code
```

| Field | Type | Required | Description |
|---|---:|---:|---|
| `coupon_code` | string | Yes | Coupon code that exists in RevCent. |

Example:

```json
{
  "coupon": [
    {
      "coupon_code": "SPRING20"
    }
  ]
}
```

`EstimateSale` is especially useful for coupon validation because the response includes valid and invalid coupon breakdowns.

---

## Discount Array Schema

`discount` is optional.

Each discount object has:

```text
additionalProperties: false
required:
  - discount_value
  - discount_type
```

| Field | Type | Required | Description |
|---|---:|---:|---|
| `discount_value` | number | Yes | Discount value relative to `discount_type`. |
| `discount_type` | string enum | Yes | Either `percent` or `amount`. |
| `name` | string | No | Optional discount name. |
| `description` | string | No | Optional discount description. |
| `apply_to_product` | boolean | No | Whether discount applies to products purchased. Default is true. |
| `apply_to_shipping` | boolean | No | Whether discount applies to shipping. Default is true. |

Allowed values for `discount_type`:

```json
[
  "percent",
  "amount"
]
```

Example:

```json
{
  "discount": [
    {
      "discount_value": 10,
      "discount_type": "percent",
      "name": "Checkout Discount",
      "apply_to_product": true,
      "apply_to_shipping": false
    }
  ]
}
```

---

## Output Schema Overview

The response is designed to be useful for customer-facing checkout display.

Major output sections include:

| Output Field | Purpose |
|---|---|
| `api_call_id` | API call ID. |
| `api_call_unix` | Unix timestamp of API call. |
| `code` | API response code. |
| `coupons` | Breakdown of valid and invalid coupon codes. |
| `discounts` | Itemized discount entries that would be created if the Sale is processed. |
| `products` | Itemized product entries that would be created if the Sale is processed. |
| `shipping` | Itemized shipping entries and discounted shipping totals. |
| `tax` | Itemized tax entries. |
| `totals` | Summed total amounts across products, shipping, discounts, and tax. |

The exact response may vary depending on the request contents.

---

## Checkout Display: Most Useful Response Sections

### `products`

Use `products` to display product line items to the customer.

Useful fields include:

| Field | Display Use |
|---|---|
| `uuid` | Internal response correlation ID for matching related discounts/shipping. |
| `id` | Product ID. |
| `name` | Product name. |
| `description` | Product description. |
| `quantity` | Quantity being purchased. |
| `price` | Product unit price. |
| `total_amount` | Product total before discounts. |
| `is_trial` | Whether product will create a trial when sold. |
| `is_trial_ship_now` | Whether trial product ships immediately. |
| `is_free_product` | Whether product is free. |
| `discount_uuid` | Discount UUIDs linked to the product. |
| `discount_amount` | Product discount amount. |
| `discount_multiplier` | Discount multiplier. |
| `discount_percent` | Discount percent. |
| `total_amount_with_discount` | Product total after discounts. |
| `max_quantity_allowed` | Max quantity customer may purchase based on product settings. |

Good customer-facing displays:

```text
Product name
Quantity
Price
Discount
Final product total
Trial/free status if relevant
```

---

## Checkout Display: `shipping`

Use `shipping` to display shipping charges.

Useful fields include:

| Field | Display Use |
|---|---|
| `uuid` | Internal response correlation ID. |
| `amount` | Shipping amount before discounts. |
| `products` | Products associated with the shipping item. |
| `provider` | Shipping provider. |
| `provider_method` | Shipping provider method. |
| `total_amount_with_discount` | Shipping total after discounts. |

Good customer-facing displays:

```text
Shipping method
Shipping amount
Shipping discount if any
Final shipping amount
```

---

## Checkout Display: `tax`

Use `tax` to show tax itemization.

Useful fields include:

| Field | Display Use |
|---|---|
| `rate` | Calculated tax rate. |
| `amount` | Total tax amount. |

Good customer-facing displays:

```text
Tax amount
Tax rate, if appropriate
```

---

## Checkout Display: `coupons`

Use `coupons` to show coupon validation feedback.

The response can include:

```text
coupons.valid
coupons.invalid
```

### Valid Coupons

Useful fields include:

| Field | Display Use |
|---|---|
| `uuid` | Internal response correlation ID. |
| `coupon_code` | Submitted coupon code. |
| `coupon_id` | RevCent coupon ID. |
| `coupon_profile_id` | Related coupon profile ID. |
| `discount` | Potential discount created by the coupon. |

### Invalid Coupons

Useful fields include:

| Field | Display Use |
|---|---|
| `uuid` | Internal response correlation ID. |
| `coupon_code` | Submitted coupon code. |
| `errors` | Array of error messages explaining why the coupon is invalid. |

Customer-facing use:

```text
Coupon SPRING20 applied successfully.
Coupon EXPIRED10 is invalid: [error message].
```

---

## Checkout Display: `discounts`

Use `discounts` to display savings.

Useful fields include:

| Field | Display Use |
|---|---|
| `uuid` | Internal response correlation ID. |
| `discount_amount` | Discount amount. |
| `discount_percent` | Discount percentage rounded to max two decimals. |
| `discount_multiplier` | Mathematical discount multiplier. |
| `discount_type` | Discount type relative to discount value. |
| `discount_value` | Discount value. |
| `is_coupon` | Whether discount came from a coupon code. |
| `coupon_id` | Coupon ID if coupon-generated. |
| `coupon_uuid` | Link to coupon item in `coupons` array. |
| `products` | Product entries the discount applies to. |
| `shipping` | Shipping entries the discount applies to. |

Discount product/shipping sub-entries may include:

- `id`
- `uuid`
- `discount_amount`
- `discount_multiplier`
- `discount_percent`
- `total_amount_with_discount`

Good customer-facing displays:

```text
Discount name/code
Amount saved
Products/shipping affected
Total after discount
```

---

## Checkout Display: `totals`

Use `totals` as the primary checkout summary object.

The schema describes `totals` as:

```text
The totals object, containing the sum of all related products, shipping, discounts and tax. Ultimate amounts are based on any delayed trial amounts, which the customer will not pay immediately.
```

Use `totals` to display:

- Product subtotal
- Shipping total
- Tax total
- Discount total
- Customer savings
- Amount due now
- Any delayed/remaining/trial-related amounts when applicable
- Final estimated checkout total

Because the schema notes delayed trial amounts, AI/MCP clients should distinguish between:

```text
amount customer pays immediately
```

and:

```text
ultimate amount or delayed amount related to trials
```

Do not assume all estimated totals are due immediately if trials or delayed billing are involved.

---

## Display Strategy for Customer Checkout

Recommended display order:

```text
Products
    ↓
Shipping
    ↓
Tax
    ↓
Coupons / discounts
    ↓
Savings
    ↓
Total due now
    ↓
Delayed/trial-related amounts if applicable
```

Example customer-facing summary:

```text
Items:
- Product A x 2: $40.00
- Product B x 1: $19.95

Shipping:
- USPS Priority: $6.95

Tax:
- Sales Tax: $3.25

Discounts:
- SPRING20: -$10.00

Total due today:
$60.15
```

AI/MCP clients should use exact response values rather than recalculating totals manually whenever possible.

---

## Example: Estimate a Pending Sale

```json
{
  "sale_id": "XXXXXXXXXXXXXXXXXXXX"
}
```

Use this before `ProcessPendingSale` to confirm what the pending Sale will cost.

---

## Example: Estimate With Coupon

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "iso_currency": "USD",
  "customer": {
    "first_name": "Jane",
    "last_name": "Customer",
    "email": "jane@example.com"
  },
  "product": [
    {
      "id": "XXXXXXXXXXXXXXXXXXXX",
      "quantity": 1
    }
  ],
  "coupon": [
    {
      "coupon_code": "SPRING20"
    }
  ]
}
```

Use the response `coupons.valid`, `coupons.invalid`, `discounts`, `products`, and `totals` to display whether the coupon applied and how much the customer saves.

---

## Example: Estimate With Shipping and Tax

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "iso_currency": "USD",
  "customer": {
    "first_name": "Jane",
    "last_name": "Customer",
    "email": "jane@example.com"
  },
  "ship_to": {
    "first_name": "Jane",
    "last_name": "Customer",
    "email": "jane@example.com",
    "address_line_1": "123 Main St",
    "city": "New York",
    "state": "NY",
    "zip": "10001",
    "country": "USA"
  },
  "product": [
    {
      "id": "XXXXXXXXXXXXXXXXXXXX",
      "quantity": 1
    }
  ],
  "shipping": [
    {
      "amount": 6.95,
      "provider": "usps",
      "provider_method": "priority",
      "name": "USPS Priority"
    }
  ],
  "tax": [
    {
      "amount": 3.25,
      "name": "Sales Tax"
    }
  ]
}
```

---

## Example: Estimate With Static Discount

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "iso_currency": "USD",
  "product": [
    {
      "id": "XXXXXXXXXXXXXXXXXXXX",
      "quantity": 1
    }
  ],
  "discount": [
    {
      "discount_value": 10,
      "discount_type": "percent",
      "name": "10 Percent Off",
      "apply_to_product": true,
      "apply_to_shipping": false
    }
  ]
}
```

---

## AI/MCP Decision Guide

| User Intent | Recommended Operation |
|---|---|
| Preview checkout total | `EstimateSale` |
| Validate coupon before payment | `EstimateSale` |
| Show customer savings | `EstimateSale` |
| Preview pending Sale before charging | `EstimateSale` with `sale_id` |
| Modify pending Sale first | `UpdatePendingSale` |
| Process payment for pending Sale | `ProcessPendingSale` |
| Create paid Sale immediately | `CreateSale` |
| Report on Sales metrics | `BigQueryRunQuery` |
| Retrieve a specific Sale after creation | `GetSale` |

---

## AI Voice Agent Use

AI Voice Agents can use `EstimateSale` to tell a customer what they will pay before processing payment.

Example voice flow:

```text
Get or create pending Sale
Update pending Sale if needed
EstimateSale
Read total and savings to customer
Ask for explicit consent
ProcessPendingSale only if customer agrees
```

Voice agents must not process payment until the customer clearly consents.

---

## AI Assistant Use

AI Assistants can use `EstimateSale` to:

- Validate a recovery offer.
- Determine if a coupon is valid.
- Estimate a recovered pending Sale.
- Compare discounts or cart options.
- Prepare a customer-facing email summary.
- Decide whether a recovery workflow should continue.

AI Assistants should use `EstimateSale` before any payment-processing operation when totals need to be known or shown.

---

## Reporting Rule

Do not use `EstimateSale` for reporting, metrics, aggregation, or data mining.

`EstimateSale` is for operational checkout calculation and preview.

Use `BigQueryRunQuery` for:

- Sales metrics
- Revenue reporting
- Coupon performance
- Discount performance
- Funnel conversion
- Recovery performance
- Product-level reports
- Refund analysis
- Subscription/trial reporting

---

## Validation Checklist Before Calling `EstimateSale`

Before calling `EstimateSale`, verify:

- The user wants a preview/estimate, not payment processing.
- If estimating a pending Sale, the correct `sale_id` is known.
- If estimating a new Sale, at least one product is provided.
- Product IDs are valid.
- Product quantities are intentional.
- Override prices are intentional.
- Shipping entries are correct if provided.
- Tax entries are correct if provided.
- Coupon codes are correct if provided.
- Static discounts are intentional.
- Customer/billing/shipping details are sufficient for the estimate.
- `include_gateway` is only used for credit-card gateway preview with a next-gen Payment Profile.
- The response should be used for display instead of manually recalculating totals.

---

## Common Mistakes to Avoid

Do not:

- Tell the customer payment has been processed.
- Use `EstimateSale` when the user wants to charge immediately.
- Use `ProcessPendingSale` without estimating first when the customer needs final total confirmation.
- Ignore invalid coupon messages.
- Manually recalculate totals when the response already provides calculated values.
- Assume all totals are due immediately when trial/delayed amounts may be involved.
- Use `include_gateway` without `payment_type: "credit_card"` and a next-gen `payment_profile`.
- Invent credit card or 3DS values.
- Use `EstimateSale` for analytics instead of `BigQueryRunQuery`.

---

## Final AI/MCP Instruction

Use `EstimateSale` to calculate and preview Sale totals before payment.

It does not process payment. It is especially useful for checkout display, coupon validation, discount/savings presentation, pending Sale review, upsell/order-bump funnel confirmation, AI recovery, and AI Voice Agent payment-consent workflows.

Use the response products, shipping, tax, coupons, discounts, and totals sections to display a clear customer-facing summary before calling `CreateSale` or `ProcessPendingSale`.


---
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.