# RevCent MCP Guide: `ProcessPendingSale`

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

This document is meant to be read by AI agents, MCP clients, automation tools, and developers that need to understand when and how to process payment for an existing pending Sale in RevCent.

---

## Operation Summary

`ProcessPendingSale` processes payment for an existing pending Sale using the `sale_id` of a previously created pending Sale.

A pending Sale is stored in RevCent but has not yet processed payment. It acts like a pseudo-cart or stored checkout session for a specific customer. `ProcessPendingSale` is the operation that turns that pending Sale into an actual paid Sale attempt.

The MCP operation description states that `ProcessPendingSale`:

- Processes an existing pending Sale.
- Uses the Sale ID of a previously created pending Sale.
- **Will process payment.**
- Should be used when the business is officially ready to process payment for the pending Sale.
- Can include payment information at processing time if payment information was not already provided.

This is a consequential payment operation. AI/MCP clients must treat it differently from `CreatePendingSale`, `UpdatePendingSale`, and `EstimateSale`.

---

## Related Documentation Links

AI/MCP clients should use these related markdown documents for broader Sale lifecycle and pending Sale workflow context:

| Document | URL | Purpose |
|---|---|---|
| Sales Overview | `https://revcent.com/documentation/markdown/mcp/operation/OverviewSale.md` | Explains the overall Sale object, Sale lifecycle, Product Sales, shipments, tax, discounts, refunds, subscriptions, trials, fulfillment, events, AI workflows, and reporting rules. |
| Update Pending Sale | `https://revcent.com/documentation/markdown/mcp/operation/UpdatePendingSale.md` | Explains how to modify an existing pending Sale before payment is processed. Use before `ProcessPendingSale` when products, shipping, tax, discounts, customer details, payment details, or metadata need to change. |
| Estimate Sale | `https://revcent.com/documentation/markdown/mcp/operation/EstimateSale.md` | Explains how to estimate Sale totals, products, shipping, tax, coupons, and discounts before payment is processed. Useful before `ProcessPendingSale` to show totals or validate pricing. |
| Functions Overview | `https://revcent.com/documentation/markdown/mcp/operation/OverviewFunction.md` | Explains RevCent Functions, account-event triggers, outbound requests, third-party integrations, webhook-style notifications, and secure custom automation patterns for notifying external systems. |
| AI Assistant Overview | `https://revcent.com/documentation/markdown/mcp/operation/OverviewAIAssistant.md` | Explains AI Assistant event triggers, event delay, Thread Builder, Time Delay nodes, filters, max-runs-per-item, and wait-and-continue automation patterns useful for delayed pending Sale recovery. |
| AI Voice Agent Overview | `https://revcent.com/documentation/markdown/mcp/operation/OverviewAIVoiceAgent.md` | Explains inbound/outbound AI Voice Agents, pending Sale recovery calls, declined payment recovery calls, customer consent, identity verification, system actions, call limits, and call outcome metadata. |

Recommended pending Sale reading order:

```text
OverviewSale.md
    ↓
CreatePendingSale.md
    ↓
UpdatePendingSale.md
    ↓
EstimateSale.md
    ↓
ProcessPendingSale.md

For AI/external-system workflows, also read:

OverviewFunction.md
OverviewAIAssistant.md
OverviewAIVoiceAgent.md
```

---

## Critical Payment Warning

`ProcessPendingSale` **processes payment**.

Do not call this operation unless:

- The pending Sale exists.
- The correct pending Sale `sale_id` is known.
- The cart/products/shipping/tax/discounts are final.
- The correct payment profile is known.
- The customer or authorized user has clearly approved processing payment.
- Any required card or payment information is already stored on the pending Sale or provided in the request.
- The AI/MCP client is explicitly allowed to process payment in the current workflow.

Unlike `CreatePendingSale` and `UpdatePendingSale`, this operation is not just storing or modifying a cart. It is the actual payment-processing step.

---

## When to Use `ProcessPendingSale`

Use `ProcessPendingSale` when a pending Sale is ready to be charged.

Good use cases:

| Use Case | Why `ProcessPendingSale` Fits |
|---|---|
| Multi-step checkout completion | The customer finished the checkout steps and is ready to pay. |
| Upsell/order-bump funnel completion | The final cart has been assembled and the customer authorized payment. |
| Abandoned checkout recovery | A customer returns and agrees to complete payment for the existing pending Sale. |
| AI Assistant recovery | The assistant has confirmed eligibility and authorization according to workflow rules. |
| AI Voice Agent recovery | The customer verbally consents to payment during a live recovery call. |
| Support-assisted checkout | Support rep confirms the pending Sale and processes payment. |
| Saved card processing | A pending Sale already has payment info attached and is ready to charge. |
| Final quote approval | Customer approves a quote or stored order and payment should now be processed. |

Do not use `ProcessPendingSale` if the user only wants to update the cart, estimate totals, or save information.

---

## When Not to Use `ProcessPendingSale`

Do not use this operation when:

- The Sale should remain pending.
- The cart/products are still changing.
- The user only wants to preview totals.
- The user only wants to add or change products.
- The user only wants to add or change shipping/tax/discounts.
- The user only wants to update card information.
- The customer has not authorized payment.
- The workflow is not allowed to process payment.
- The pending Sale ID is unknown or uncertain.

Use:

- `UpdatePendingSale` to modify the pending Sale.
- `EstimateSale` to preview totals.
- `VoidSale` to cancel a pending Sale.
- `GetSale` to inspect a specific Sale.
- `BigQueryRunQuery` for reporting.

---

## Schema Summary

Operation:

```text
name: ProcessPendingSale
title: Process A Pending Sale
description: Process an existing pending Sale using the Sale ID of a previously created pending Sale.
input type: object
additionalProperties: false
```

Required top-level fields:

```text
payment_profile
campaign
sale_id
```

The input schema does **not** allow unknown top-level fields.

---

## Full Input Schema

| Field | Type | Required | Description |
|---|---:|---:|---|
| `campaign` | string | Yes | 20-character Campaign ID. |
| `payment_profile` | string | Yes | 20-character RevCent Payment Profile ID used to route the credit card payment request. |
| `sale_id` | string | Yes | 20-character Sale ID of the pending Sale to process. |
| `credit_card` | object | No | Optional credit card payment information to process the pending Sale. If not provided, previously saved credit card payment information attached to the pending Sale will be used. |
| `metadata` | array<object> | No | Sale-level metadata. Passed down to all items created as a result of the Sale, including customer, product sales, shipping, and tax. |

---

## Required Fields

### `campaign`

A 20-character Campaign ID.

Required even though the pending Sale already exists.

Example:

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX"
}
```

### `payment_profile`

A 20-character RevCent Payment Profile ID used for routing the credit card payment request.

Required.

Example:

```json
{
  "payment_profile": "XXXXXXXXXXXXXXXXXXXX"
}
```

### `sale_id`

A 20-character Sale ID for the pending Sale to process.

This should come from:

- `CreatePendingSale` response
- An existing pending Sale workflow
- A verified `GetSale`/search result
- A trusted internal system reference

Example:

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

Do not guess the pending Sale ID.

---

## Credit Card Behavior

`credit_card` is optional.

The schema states:

```text
If you wish to include credit card payment information to process the pending sale. Note: This is optional, and if not provided, any previously saved credit card payment information attached to the pending sale will be used.
```

This means `ProcessPendingSale` supports two payment-information patterns:

### Pattern 1: Use Previously Saved Card Information

If the pending Sale already has credit card payment information attached, the request can omit `credit_card`.

Example:

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "payment_profile": "XXXXXXXXXXXXXXXXXXXX",
  "sale_id": "XXXXXXXXXXXXXXXXXXXX"
}
```

### Pattern 2: Provide Card Information at Processing Time

If card information was not saved on the pending Sale, or the customer provides a new card at the final processing step, include `credit_card`.

Example:

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "payment_profile": "XXXXXXXXXXXXXXXXXXXX",
  "sale_id": "XXXXXXXXXXXXXXXXXXXX",
  "credit_card": {
    "card_number": "<CARD_NUMBER_COLLECTED_SECURELY>",
    "exp_month": 12,
    "exp_year": 29,
    "card_code": "<CARD_CODE_COLLECTED_SECURELY>"
  }
}
```

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

---

## `credit_card` Object Schema

`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 | Credit card expiration month as one or two digit integer, e.g. `1` or `12`. |
| `exp_year` | integer | Yes | Credit card expiration year as two digit integer, e.g. `29`. |
| `card_code` | string | No | Credit card security code. Depending on card type, length can vary. |
| `three_ds` | object | No | Optional 3DS values to pass to the processor. |

---

## `credit_card.three_ds` Object Schema

`three_ds` is optional.

Use it when 3DS is used during checkout and RevCent should parse/send those 3DS values to the processor.

`three_ds` has:

```text
additionalProperties: false
```

| Field | Type | Description |
|---|---:|---|
| `enabled` | boolean | Must be true if using 3DS values. Default is false. |
| `version` | string | 3DS version, such as `2.1.0` or `2.2.0`. |
| `eci` | string | eCommerce indicator. |
| `cavv` | string | Cardholder Authentication Verification Value. |
| `xid` | string | Transaction identifier from authentication processing. |
| `directory_server_id` | string | Directory server transaction identifier. |
| `authentication_response` | string | Describes whether the customer was successfully verified or attempted. |
| `acs_transaction_id` | string | Access Control Server transaction identifier. |
| `algorithm` | string | 3DS algorithm used. |
| `directory_response` | string | 3DS directory server response. |
| `enrollment_response` | string | Verify enrollment response/status. |
| `three_ds_server_transaction_id` | string | 3DS server transaction ID. |

Do not invent 3DS values. They must come from the real 3DS checkout/authentication flow.

---

## Metadata Schema

`metadata` is optional.

Sale-level metadata provided during `ProcessPendingSale` is passed down to all items created as a result of the Sale, including:

- Customer
- Product Sales
- Shipping
- Tax

Each metadata object has:

```text
additionalProperties: false
required:
  - name
  - value
```

| Field | Type | Required | Limit |
|---|---:|---:|---|
| `name` | string | Yes | 1 to 100 characters. |
| `value` | string | Yes | 1 to 255 characters. |

Example:

```json
{
  "metadata": [
    {
      "name": "processed_by",
      "value": "ai_voice_agent"
    },
    {
      "name": "recovery_outcome",
      "value": "customer_authorized_payment"
    }
  ]
}
```

Metadata is useful for reporting and lifecycle analysis. Use clear, descriptive names.

---

## Visitor Tracking Metadata Requirement

If the Sale took place on a website and tracking-domain DNS is set up in RevCent for the website, metadata must include the following visitor/session cookie values:

```json
[
  {
    "name": "revcent_track_id",
    "value": "[the value of visitor/session cookie.revcent_track_id]"
  },
  {
    "name": "revcent_entry_id",
    "value": "[the value of visitor cookie.revcent_entry_id]"
  }
]
```

If these were not included earlier during `CreatePendingSale` or `UpdatePendingSale`, include them when processing the pending Sale.

These values help RevCent connect the processed Sale to DNS tracking, conversion attribution, URL parameter metadata, and lifecycle reporting.

---

## Offline Payment Metadata Note

The `ProcessPendingSale` schema includes the same Sale-level metadata guidance for offline payment Sales involving third-party payment processors.

For offline payment Sales involving a third-party payment processor, metadata must include:

```json
[
  {
    "name": "offline_payment_third_party",
    "value": "sezzle | afterpay | klarna | affirm | amazon_pay"
  },
  {
    "name": "offline_payment_third_party_transaction_id",
    "value": "[the transaction ID from the third party]"
  },
  {
    "name": "offline_payment_third_party_integration_id",
    "value": "[the RevCent ID of the third party integration within your account for the third party processor]"
  }
]
```

Supported values shown in the schema:

```text
sezzle
afterpay
klarna
affirm
amazon_pay
```

If these values already exist on the pending Sale, preserve them. If they are required and missing, include them before or during processing.

---

## Output Schema

The current MCP output schema for `ProcessPendingSale` is an object with no explicitly documented properties:

```json
{
  "type": "object",
  "additionalProperties": false,
  "properties": {},
  "required": []
}
```

AI/MCP clients should not assume undocumented output fields.

If details are needed after processing, use follow-up Sale lookup workflows such as `GetSale`, `SearchSales`, or known internal references.

---

## Minimal Process Request Using Stored Card

Use this when the pending Sale already has saved credit card information.

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "payment_profile": "XXXXXXXXXXXXXXXXXXXX",
  "sale_id": "XXXXXXXXXXXXXXXXXXXX"
}
```

---

## Process Request With New Card Information

Use this when payment details need to be provided at the time of processing.

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "payment_profile": "XXXXXXXXXXXXXXXXXXXX",
  "sale_id": "XXXXXXXXXXXXXXXXXXXX",
  "credit_card": {
    "card_number": "<CARD_NUMBER_COLLECTED_SECURELY>",
    "exp_month": 12,
    "exp_year": 29,
    "card_code": "<CARD_CODE_COLLECTED_SECURELY>"
  }
}
```

---

## Process Request With Recovery Metadata

Use metadata to preserve why/how the pending Sale was processed, especially for AI, voice, support, or abandoned checkout recovery.

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "payment_profile": "XXXXXXXXXXXXXXXXXXXX",
  "sale_id": "XXXXXXXXXXXXXXXXXXXX",
  "metadata": [
    {
      "name": "recovery_channel",
      "value": "ai_voice_agent"
    },
    {
      "name": "recovery_outcome",
      "value": "customer_authorized_payment"
    },
    {
      "name": "payment_authorization_source",
      "value": "live_phone_call"
    }
  ]
}
```

---

## Process Request With Tracking Metadata

```json
{
  "campaign": "XXXXXXXXXXXXXXXXXXXX",
  "payment_profile": "XXXXXXXXXXXXXXXXXXXX",
  "sale_id": "XXXXXXXXXXXXXXXXXXXX",
  "metadata": [
    {
      "name": "revcent_track_id",
      "value": "visitor-session-track-id"
    },
    {
      "name": "revcent_entry_id",
      "value": "visitor-entry-id"
    },
    {
      "name": "utm_source",
      "value": "google"
    },
    {
      "name": "utm_campaign",
      "value": "spring_sale"
    }
  ]
}
```

---

## Lifecycle Chart

```text
CreatePendingSale
├─ Creates pending Sale
├─ Stores customer/cart/payment context
└─ Returns sale_id

UpdatePendingSale
├─ Optional
├─ Changes products, shipping, tax, discounts, addresses, payment info, metadata
└─ Does not process payment

EstimateSale
├─ Optional but recommended before charging
├─ Previews totals, shipping, tax, discounts, coupons
└─ Does not process payment

ProcessPendingSale
├─ Requires campaign
├─ Requires payment_profile
├─ Requires sale_id
├─ Uses saved card or provided credit_card
├─ Processes payment
├─ Creates paid Sale outcome
├─ Creates Product Sales and related Sale items as applicable
├─ Can trigger fulfillment, emails, events, AI, voice, functions, and webhooks
└─ Enables downstream reporting with BigQueryRunQuery
```

---

## What Can Happen After Processing

After `ProcessPendingSale` successfully processes payment, the pending Sale becomes a paid Sale outcome.

Depending on Sale contents and account configuration, processing can lead to:

- Payment transaction creation
- Product Sale line item creation
- Shipping item creation
- Fulfillment notification for shippable products
- Tax item creation
- Discount records
- Subscription creation if products have subscription profiles
- Trial creation if products have trial settings
- Email Template triggers
- AI Assistant triggers
- AI Voice Agent workflows
- Function triggers
- Webhook/integration events
- Notes/metadata workflows
- BigQuery reporting and lifecycle attribution

For broader lifecycle details, see the Sales Overview:

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

---

## Best Practice: Wait Before Processing Pending Sales With AI or External Automation

When pending Sales are being recovered or processed by AI Assistants, AI Voice Agents, or external systems, it is generally best practice to wait before attempting to process payment.

Do **not** immediately retry or process every pending Sale as soon as it becomes available for recovery.

A wait period gives the customer time for funds to become available, card limits to reset, bank holds to clear, or temporary issuer/gateway issues to resolve. Immediate retries often repeat the same decline condition and can waste recovery attempts.

Recommended approach:

```text
Pending Sale exists or payment attempt failed
    ↓
Wait X days according to business policy
    ↓
Re-check the Sale and customer/payment context
    ↓
EstimateSale if totals should be confirmed
    ↓
ProcessPendingSale only if still eligible and authorized
```

The exact wait period should be determined by the business. Examples:

| Scenario | Example Wait Strategy |
|---|---|
| Abandoned checkout | Wait 1 to 3 days before automated recovery processing or outreach. |
| Declined pending Sale retry | Wait 1 to 3 days before retrying, unless the customer explicitly asks for immediate retry. |
| Customer says funds will be available later | Wait until the customer-provided date or expected funding window. |
| AI Assistant recovery | Use an event delay or Time Delay node before attempting processing. |
| External recovery automation | Schedule processing X days after event notification, then re-check Sale state. |
| High-value pending Sale | Consider manual review or customer contact before processing. |

AI/MCP clients should not hard-code a universal wait period. Use the account's business policy, product type, decline context, customer history, recovery channel, and authorization rules.

### AI Assistant Wait Options

AI Assistants can introduce wait periods in two major ways:

1. **Initial event delay on trigger**  
   Configure the assistant to wait before it begins after the relevant Sale/pending-Sale event.

2. **Time Delay node in the Thread Builder**  
   Let the assistant inspect the pending Sale first, branch based on context, then wait before attempting recovery or processing.

Example AI Assistant pattern:

```text
Sale/pending-Sale event occurs
    ↓
AI Assistant starts after initial delay, or starts immediately and evaluates context
    ↓
Assistant determines whether recovery is appropriate
    ↓
Time Delay node waits X days if needed
    ↓
Assistant re-checks Sale/customer/payment state
    ↓
Assistant uses EstimateSale if totals must be confirmed
    ↓
Assistant calls ProcessPendingSale only if authorized and still eligible
```

For AI Assistant details, see:

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

### External System Wait Pattern

External systems should also follow a wait-before-processing policy.

Correct external flow:

```text
RevCent Function/account-event notification sends sale_id to external system
    ↓
External system stores sale_id and event_id
    ↓
External system waits X days according to recovery policy
    ↓
External system calls GetSale to re-check current Sale state
    ↓
External system calls EstimateSale if totals need confirmation
    ↓
External system calls ProcessPendingSale only if payment is authorized and the Sale is eligible
```

External systems should not poll operational listing endpoints to discover pending Sales, and they should not immediately process pending Sales without a business reason or customer authorization.

### Wait-Then-Recheck Rule

After any wait period, the AI Assistant or external automation must re-check the pending Sale before processing.

Before calling `ProcessPendingSale`, re-check:

- Sale status and pending eligibility
- Customer identity and status
- Payment authorization
- Payment method availability
- Latest payment/retry outcome
- Cart/products/shipping/tax/discounts
- Whether `EstimateSale` should be shown again
- Recovery metadata
- Business retry limits
- Whether the customer has opted out, cancelled, or already completed payment elsewhere

Do not assume the pending Sale is still eligible after the delay.

---

## External Systems Must Not Poll for Pending Sales

External systems should **not** poll operational listing endpoints to discover pending Sales that are ready to process.

Polling for pending Sales or payment-ready Sales is the wrong integration pattern because:

- Operational listing endpoints are not event feeds.
- Polling creates unnecessary API load.
- Polling can miss records if pagination, filters, date windows, or timing are wrong.
- Polling encourages bulk-retrieval patterns that should be avoided.
- Event-driven automation is more reliable and scalable.
- The external system should receive the exact Sale ID from RevCent when the relevant event occurs.

Correct pattern:

```text
Relevant RevCent account event occurs
    ↓
RevCent Function runs from the account-event trigger
    ↓
Function receives event.data.item_id and event.data.item_details
    ↓
Function sends an HTTP POST to the external system
    ↓
External system stores the sale_id and event_id
    ↓
External system performs its own workflow
    ↓
External system calls GetSale to re-check the Sale if needed
    ↓
External system calls ProcessPendingSale only when payment is authorized and the Sale is still eligible
```

Use Functions for external notifications instead of polling.

For broader Function guidance, see:

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

---

## Correct External Notification Pattern: Account-Event Function

If an external system needs to know when a pending Sale exists, changes, becomes recoverable, or is ready for payment processing, configure a RevCent Function using an account-event trigger.

The exact event notation should match the business workflow being automated.

Examples of event-driven pending Sale workflows:

| External Need | Correct Pattern |
|---|---|
| Notify an external checkout system that a pending Sale was created | Account-event Function sends the Sale ID to the external system. |
| Notify an external recovery system that a Sale failed or remains pending | Account-event Function sends the Sale/customer context to the external recovery system. |
| Notify an external system after a pending Sale is updated | Account-event Function sends the updated Sale ID/context. |
| Notify an external system after a Sale is processed successfully or fails | Account-event Function sends the resulting Sale/payment context. |

The external system should store the `sale_id`, then call targeted operations such as `GetSale`, `UpdatePendingSale`, `EstimateSale`, or `ProcessPendingSale` only when needed.

Do not poll broad listing operations to find work.

### Example Function Code: Notify External System About a Sale Event

This is example Function code for an account-event Function. Configure the Function trigger to the specific Sale/pending-Sale event notation that matches the business workflow.

Replace the webhook URL and authorization token with the secure configuration pattern used in the RevCent account, such as encrypted values, key values, or other approved secret/config storage.

```javascript
// RevCent Function trigger: account_event
// Purpose:
// Notify an external system about a Sale-related event.
// Do not poll operational listing endpoints to discover pending Sales.

const EXTERNAL_WEBHOOK_URL = "https://example.com/revcent/sale-event";
const EXTERNAL_WEBHOOK_TOKEN = "REPLACE_WITH_SECURE_STORED_SECRET";

async function notifyExternalSystem(event, context, callback) {
  try {
    const data = event.data || {};
    const item = data.item_details || {};

    const payload = {
      source: "revcent",
      event_id: data.event_id || null,
      event_date: data.event_date || null,
      event_trigger: data.event_trigger || null,
      event_notations: data.event_notations || null,

      item_type: data.item_type || "sale",
      item_id: data.item_id || item.id || null,
      sale_id: data.item_id || item.id || null,

      customer_id: item.customer && item.customer.id ? item.customer.id : null,
      campaign_id: item.campaign_id || null,
      campaign_name: item.campaign_name || null,

      status: item.status || null,
      payment_status: item.payment_status || null,

      sales: item.sales || [],
      product_sales: item.product_sales || [],
      shipping: item.shipping || [],
      tax: item.tax || [],
      discounts: item.discounts || [],
      subscriptions: item.subscriptions || [],
      trials: item.trials || [],

      metadata: item.metadata || []
    };

    if (!payload.sale_id) {
      callback(null, {
        success: false,
        reason: "Missing sale_id from event payload"
      });
      return;
    }

    const response = await fetch(EXTERNAL_WEBHOOK_URL, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${EXTERNAL_WEBHOOK_TOKEN}`,
        "Idempotency-Key": payload.event_id || payload.sale_id
      },
      body: JSON.stringify(payload)
    });

    const responseText = await response.text();

    if (!response.ok) {
      callback(null, {
        success: false,
        status: response.status,
        response: responseText
      });
      return;
    }

    callback(null, {
      success: true,
      status: response.status,
      sale_id: payload.sale_id
    });
  } catch (error) {
    callback(null, {
      success: false,
      error: error && error.message ? error.message : String(error)
    });
  }
}

notifyExternalSystem(event, context, callback);
```

### External System Responsibilities

The external system should:

1. Receive and authenticate the Function POST.
2. Use `event_id` or `sale_id` as an idempotency key.
3. Store the `sale_id`.
4. Re-check the Sale using `GetSale` before taking consequential actions.
5. Use `EstimateSale` if totals need to be displayed or confirmed.
6. Use `UpdatePendingSale` if the cart/customer/payment context must change.
7. Use `ProcessPendingSale` only when payment is authorized and the pending Sale is eligible.
8. Store outcomes and retry history.
9. Use `BigQueryRunQuery` for reporting and metrics, not operational listing endpoints.

The external system should not assume a pending Sale is still eligible to process when it receives or later acts on the event. It should re-check current state first.

---

## AI/MCP Workflow Guidance

### AI and Voice Reference Links

For AI-driven or voice-driven pending Sale processing/recovery, use these overview files:

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

AI Assistants are best for automated reasoning, delayed recovery, event-triggered workflows, and background processing logic. AI Voice Agents are best when a live phone conversation is useful to verify the customer, answer questions, collect consent, update payment information, or complete a pending Sale.

### External System Processing

External systems should use RevCent Functions to receive Sale/pending-Sale notifications instead of polling operational endpoints.

Best practice: external systems should wait X days before processing or retrying a pending Sale, unless the customer explicitly authorizes immediate processing or the business has a specific immediate-processing policy.

Correct external workflow:

```text
RevCent account-event Function notifies external system
    ↓
External system stores sale_id
    ↓
External system waits X days according to business policy
    ↓
External system re-checks current Sale state with GetSale
    ↓
External system updates or estimates if needed
    ↓
External system calls ProcessPendingSale only after authorization
```

Do not build an external system that repeatedly polls list operations to discover pending Sales to process.

### Multi-Step Checkout

Use `ProcessPendingSale` only at the final payment step.

Recommended flow:

```text
CreatePendingSale
UpdatePendingSale as needed
EstimateSale to preview final totals
ProcessPendingSale after customer authorizes payment
```

### Upsell / Order Bump Funnel

Do not process the pending Sale until all accepted upsells, order bumps, downsells, discounts, tax, and shipping have been finalized.

Use `UpdatePendingSale` first if the cart changed.

Use `EstimateSale` if the final total needs to be shown.

Then call `ProcessPendingSale`.

### Abandoned Checkout Recovery

An abandoned checkout can be recovered by processing the existing pending Sale only after the customer authorizes payment.

Recovery channels may include:

- Email Template recovery
- AI Assistant recovery
- AI Voice Agent recovery
- Support-assisted recovery
- Customer returning to checkout

Add clear metadata such as:

```json
{
  "name": "recovery_channel",
  "value": "email"
}
```

or:

```json
{
  "name": "recovery_channel",
  "value": "ai_voice_agent"
}
```

### AI Voice Agent Recovery

For AI Voice Agent overview context, see:

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

An AI Voice Agent may process a pending Sale live with a customer only when:

- The customer is verified.
- The customer clearly consents to payment.
- The voice agent is configured with the required system actions.
- The business rules allow the action.
- Retry limits and safety rules are followed.

For delayed pending Sale recovery, an outbound AI Voice Agent should generally wait X days before calling unless the business has an immediate-call policy or the customer explicitly requested follow-up. The agent should explain the reason for the call, verify identity, answer questions, and only call `ProcessPendingSale` when the customer clearly authorizes payment.

### AI Assistant Recovery

For AI Assistant overview context, see:

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

An AI Assistant should only process a pending Sale when explicitly designed and permitted to do so.

Best practice: when an AI Assistant is being used to recover or process pending Sales, introduce a wait period before calling `ProcessPendingSale`. This can be done through an initial event delay on the assistant trigger or a Time Delay node inside the assistant thread. After the wait period, the assistant should re-check Sale eligibility before processing.

Recommended safeguards:

- Use event filters.
- Use max-runs-per-item limits.
- Use an initial wait period or Time Delay node before automated processing.
- Re-check Sale/customer/payment state after waiting.
- Use metadata to record outcomes.
- Use policy/eligibility logic.
- Avoid payment retry loops.
- Require explicit customer or user authorization where applicable.

---

## Validation Checklist Before Calling `ProcessPendingSale`

Before calling `ProcessPendingSale`, verify:

- The `sale_id` belongs to the correct pending Sale.
- The pending Sale has not already been processed, voided, or made ineligible.
- The customer/cart/funnel should now be charged.
- The customer or authorized user has approved payment.
- The Campaign ID is correct.
- The Payment Profile ID is correct.
- The cart products are final.
- Shipping is final.
- Tax is final.
- Discounts/coupons are final.
- `EstimateSale` has been used if totals need confirmation.
- Credit card information is present on the pending Sale or provided in the request.
- Any provided card data was collected securely.
- 3DS data, if provided, is real and from the actual checkout flow.
- Visitor tracking metadata is preserved when applicable.
- Offline third-party metadata is preserved when applicable.
- Recovery/AI/voice/support metadata is included when useful for reporting.
- The workflow is allowed to process payment.
- The source decline reason has been reviewed when this is a recovery/retry flow.
- Hard-decline logic does not indicate the same card/payment method is unlikely to succeed.
- If an external system is involved, it received the Sale ID through a RevCent Function/event notification instead of polling operational endpoints.
- If an external system is involved, it re-checked current Sale state before calling `ProcessPendingSale`.
- If AI or external automation is processing the pending Sale, the business-defined wait period has passed unless immediate processing is explicitly authorized.
- If AI or external automation waited before processing, the Sale/customer/payment state was re-checked after the wait.

---

## Common Mistakes to Avoid

Do not:

- Call `ProcessPendingSale` when the user only wants to update the cart.
- Call `ProcessPendingSale` when the user only wants an estimate.
- Process payment without clear authorization.
- Guess the `sale_id`.
- Guess the `payment_profile`.
- Use the wrong Campaign ID.
- Forget that this operation actually processes payment.
- Omit card information when the pending Sale does not already have saved payment information.
- Collect card data through an insecure channel.
- Invent 3DS values.
- Lose visitor tracking metadata.
- Lose offline third-party metadata.
- Process a pending Sale before upsells/order bumps are finalized.
- Process a pending Sale before showing totals when the workflow requires total confirmation.
- Assume output fields that are not documented in the schema.
- Use operational endpoints for metrics instead of `BigQueryRunQuery`.
- Retry a hard-decline payment method without checking decline reason.
- Use AI Voice Agent recovery calls when the decline reason indicates the call is likely futile unless the goal is to collect a new payment method or route to support.
- Poll operational listing endpoints from an external system to discover pending Sales.
- Build an external pending-Sale workflow without a RevCent Function/event notification pattern.
- Let AI Assistants or external systems immediately process/retry pending Sales without a wait period, customer authorization, or business-defined immediate-processing rule.
- Wait X days but then process without re-checking current Sale eligibility.

---

## Reporting and Metrics

Do not use operational listing endpoints for reporting. External systems should also not poll operational listing endpoints to discover pending Sales; use RevCent Functions and account-event notifications instead.

Use `BigQueryRunQuery` for:

- Pending-to-paid conversion rate
- Abandoned checkout recovery
- Processed pending Sale revenue
- Failed processing attempts
- AI Assistant recovery performance
- AI Voice Agent recovery performance
- Recovery channel analysis
- Product-level revenue from recovered pending Sales
- Upsell/order-bump performance
- Refund rates by recovery channel
- Trial/subscription creation from processed pending Sales
- DNS tracking attribution
- Customer lifetime value after recovery

Use metadata to make these reports granular.

Delayed processing and recovery outcomes should be tracked with metadata such as `recovery_wait_days`, `recovery_channel`, `recovery_attempt_number`, and `payment_authorization_source` so BigQuery can measure whether wait periods improve pending-Sale recovery.

Useful metadata examples:

- `recovery_channel`
- `recovery_outcome`
- `payment_authorization_source`
- `ai_assistant_id`
- `ai_voice_agent_id`
- `funnel_id`
- `checkout_stage`
- `revcent_track_id`
- `revcent_entry_id`

---

## Final AI/MCP Instruction

Use `ProcessPendingSale` only when an existing pending Sale is ready to be charged.

This operation processes payment. It requires `campaign`, `payment_profile`, and `sale_id`. It can use previously saved card information on the pending Sale or accept `credit_card` details at processing time.

Before processing, use `UpdatePendingSale` to finalize cart changes and `EstimateSale` to preview totals when needed. If AI Assistants or external systems are processing/retrying pending Sales, it is best practice to wait X days according to business policy, review the source decline reason, then re-check Sale eligibility before calling `ProcessPendingSale`. External systems should be notified of pending Sale work through RevCent Functions/account events, not by polling operational endpoints. After processing, use Sale lifecycle tools and `BigQueryRunQuery` for follow-up analysis and reporting.


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