# RevCent MCP Operation: `EditCustomerGroup`

This document explains the `EditCustomerGroup` operation in depth so MCP clients can correctly edit existing Customer Groups in RevCent.

This is not a general overview. It is an operation-specific implementation guide focused on edit behavior, fields, nested qualifier properties, qualifier-method logic, validation rules, examples, and common mistakes.

Source:
- RevCent API/MCP schema for `EditCustomerGroup`

---

## Operation Summary

`EditCustomerGroup` edits a previously created Customer Group using its 20-character `customer_group_id`.

Important edit behavior:

```text
Only include the properties you wish to modify.
```

For example:

- If only the name should change, include only `customer_group_id` and `name`.
- If only the description should change, include only `customer_group_id` and `description`.
- If only the enabled state should change, include only `customer_group_id` and `enabled`.
- If qualifier logic should change, include `qualifier_method` and/or `qualifiers` intentionally.

Do not include fields unnecessarily.

Editing a Customer Group can affect customer segmentation, reporting, filtering, and automation. If the group is active or connected to event-driven workflows, changes can cause customers to be added to or removed from the group, which can trigger automations such as AI Assistants, AI Voice Agents, Functions, Email Templates, external systems, and third-party AI Agents.

---

## Required Field

| Field | Type | Required | Description |
|---|---:|---:|---|
| `customer_group_id` | string | Yes | The 20-character Customer Group ID to edit. |

Minimal request:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX"
}
```

This request has no edit fields and should not change meaningful group settings. A real edit should include at least one optional property.

---

## Optional Editable Fields

| Field | Type | Description |
|---|---:|---|
| `name` | string | New Customer Group name. |
| `description` | string | New Customer Group description. |
| `enabled` | boolean | Whether the group is enabled. |
| `qualifier_method` | string enum | Method used to determine customer qualification. |
| `qualifiers` | object | Qualifier object. Active branch depends on `qualifier_method`. |

Allowed `qualifier_method` values:

```text
specific_values
customer_group
none
```

---

# Critical Edit Rule: Only Include Fields Being Changed

`EditCustomerGroup` is a partial-update operation.

The MCP should only send fields it intends to modify.

Correct name-only edit:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "name": "VIP Customers - Updated"
}
```

Correct enabled-only edit:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "enabled": false
}
```

Correct description-only edit:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "description": "High lifetime value customers used for VIP support and customer success workflows."
}
```

Do not send a full object unless intentionally replacing or updating all included fields.

---

## Why Partial Edits Matter

Customer Groups can be connected to customer lifecycle workflows.

Accidentally changing qualifiers can:

- Add many customers to a group.
- Remove many customers from a group.
- Trigger `customer.updated.customer_group.added` events.
- Trigger `customer.updated.customer_group.removed` events.
- Start AI Assistant workflows.
- Start AI Voice Agent calls.
- Send Email Templates.
- Trigger Functions.
- Notify external systems.
- Affect BigQuery reports.
- Change customer support queues.
- Change revenue recovery lists.
- Change risk or fraud review lists.

Because of this, MCP clients must be explicit about what is being edited.

---

# Critical Concept: `qualifier_method` Controls Which Qualifiers Matter

`qualifier_method` is the controlling switch for how the Customer Group determines membership.

The three qualifier methods are mutually exclusive in how qualification logic is interpreted.

The selected `qualifier_method` determines which branch of `qualifiers` is active.

| `qualifier_method` | Meaning | What Is Used | What Is Ignored |
|---|---|---|---|
| `none` | Manual/workflow-only group. | No qualifiers are used. Customers must be added or removed manually or by workflow. | All qualifiers, filters, specific values, subscription options, and customer-group rules are ignored. |
| `customer_group` | Group membership-based qualification. | Only `qualifiers.customer_group` is used. | `qualifiers.specific_values`, including filters, values, metadata, and subscription options, are ignored. |
| `specific_values` | Rule-based qualification from customer data. | Only `qualifiers.specific_values` is used, including filters, values, metadata, and subscription options. | `qualifiers.customer_group` is ignored. |

Rule:

```text
qualifier_method decides which qualifier branch is active.
```

Do not assume all objects inside `qualifiers` are evaluated.

They are not.

---

## Editing `qualifier_method`

Changing `qualifier_method` is a high-impact edit.

If the method changes, previously meaningful qualifiers may become ignored.

Example:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "none"
}
```

If the group was previously `specific_values`, this changes the group from automatic qualification to manual/workflow-only qualification.

Example:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "customer_group"
}
```

If the group previously used `specific_values`, all filters, values, metadata, and subscription options stop mattering unless the method is changed back.

Best practice:

```text
When changing qualifier_method, include the matching qualifiers branch in the same edit request unless the intent is only to switch method and leave existing stored qualifiers untouched but inactive.
```

Safer edit when changing to `none`:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "none",
  "qualifiers": {}
}
```

Safer edit when changing to `customer_group`:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "customer_group",
  "qualifiers": {
    "customer_group": {
      "in_any_customer_group": [],
      "in_all_customer_group": [
        "XXXXXXXXXXXXXXXXXXXX"
      ],
      "not_in_customer_group": []
    }
  }
}
```

Safer edit when changing to `specific_values`:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "specific_values",
  "qualifiers": {
    "specific_values": {
      "filters": {
        "campaign": [],
        "product_group": [],
        "third_party_shop": [],
        "metadata": []
      },
      "values": {
        "has_no_sales": false,
        "lifetime_value": {
          "enabled": true,
          "min": 500,
          "max": 999999
        }
      },
      "subscription_options": {
        "enabled": false,
        "status": []
      }
    }
  }
}
```

---

# `qualifier_method: "none"`

Use `none` when the group should be manual/workflow-only.

When:

```json
"qualifier_method": "none"
```

the Customer Group has no automatic qualification criteria.

Customers do not qualify based on:

- Campaign filters
- Product group filters
- Third-party shop filters
- Metadata filters
- Lifetime value
- Sales count
- Refund amount
- Chargeback count
- Fraud detections
- Subscription status
- Renewal count
- Other Customer Groups

All qualifier logic is ignored.

Customers must be added or removed by:

- Manual action
- A workflow
- A Function
- An AI Assistant action
- An AI Voice Agent workflow
- An external integration
- A third-party AI Agent
- Another automation process

Use cases:

```text
Do Not Contact
Manual Risk Review
Needs Human Support
Approved For Special Offer
Escalated Support
AI Classified Customer
```

---

## Edit to Manual Group

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "none",
  "qualifiers": {},
  "description": "Manual/workflow-only group. Customers are added or removed by support, AI review, Function, or external workflow. No qualifiers are evaluated."
}
```

Important:

Even if the group previously had `specific_values` or `customer_group` qualifiers, they should not be treated as active after `qualifier_method` becomes `none`.

Best practice:

```text
When qualifier_method = none, send qualifiers as an empty object if editing qualifiers.
```

---

# `qualifier_method: "customer_group"`

Use `customer_group` when customers should qualify based only on membership or non-membership in other Customer Groups.

When:

```json
"qualifier_method": "customer_group"
```

only this branch matters:

```json
"qualifiers": {
  "customer_group": {
    "in_any_customer_group": [],
    "in_all_customer_group": [],
    "not_in_customer_group": []
  }
}
```

This method ignores:

- Campaign filters
- Product group filters
- Third-party shop filters
- Metadata filters
- Lifetime value
- Sales count
- Refund amount
- Chargeback count
- Fraud detections
- Subscription status
- Renewal count
- Subscription options

Use cases:

```text
Customer is in VIP
Customer is in High LTV and Winback Candidate
Customer is in Payment Recovery but not Do Not Contact
Customer is in Trial User or Trial Expired
Customer is not in Manual Review
```

---

## `customer_group.in_any_customer_group`

Type:

```text
array<string>
```

Each value must be a 20-character Customer Group ID.

Meaning:

Customer must be in at least one of the selected groups.

Logic:

```text
Group A OR Group B OR Group C
```

Example:

```json
"in_any_customer_group": [
  "XXXXXXXXXXXXXXXXXXXX",
  "YYYYYYYYYYYYYYYYYYYY"
]
```

---

## `customer_group.in_all_customer_group`

Type:

```text
array<string>
```

Each value must be a 20-character Customer Group ID.

Meaning:

Customer must be in all selected groups.

Logic:

```text
Group A AND Group B AND Group C
```

Example:

```json
"in_all_customer_group": [
  "XXXXXXXXXXXXXXXXXXXX",
  "YYYYYYYYYYYYYYYYYYYY"
]
```

---

## `customer_group.not_in_customer_group`

Type:

```text
array<string>
```

Each value must be a 20-character Customer Group ID.

Meaning:

Customer must not be in the selected group or groups to qualify.

Use cases:

- Exclude Do Not Contact
- Exclude Manual Review
- Exclude Fraud Review
- Exclude already recovered customers
- Exclude existing VIP customers
- Exclude suppression groups

Example:

```json
"not_in_customer_group": [
  "XXXXXXXXXXXXXXXXXXXX"
]
```

---

## Edit Customer-Group-Based Qualifiers

Example:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "customer_group",
  "qualifiers": {
    "customer_group": {
      "in_any_customer_group": [],
      "in_all_customer_group": [
        "HIGH_VALUE_GROUP_ID",
        "WINBACK_GROUP_ID"
      ],
      "not_in_customer_group": [
        "DO_NOT_CONTACT_GROUP_ID"
      ]
    }
  },
  "description": "Composite group for customers in High Value and Winback Candidate who are not in Do Not Contact."
}
```

Replace placeholder IDs with real 20-character Customer Group IDs.

---

# `qualifier_method: "specific_values"`

Use `specific_values` when customers should qualify based only on customer data rules.

When:

```json
"qualifier_method": "specific_values"
```

only this branch matters:

```json
"qualifiers": {
  "specific_values": {
    "filters": {},
    "values": {},
    "subscription_options": {}
  }
}
```

This is the only method where the following are evaluated:

- Campaign filters
- Product group filters
- Third-party shop filters
- Metadata filters
- Lifetime value
- Lifetime refunded amount
- Sales count
- Average sale amount
- Days since last sale
- Successful sale count
- Upsell sale count
- Declined sale count
- Abandoned sale count
- Fraud detection count
- Chargeback amount
- Chargeback count
- PayPal dispute amount
- PayPal dispute count
- Subscription renewal behavior
- Subscription status

This method ignores `qualifiers.customer_group`.

Use cases:

```text
Customers with lifetime value >= 500
Customers with at least 1 declined sale
Customers from campaign X
Customers with metadata affiliate_id = aff_123
Customers with subscription status = overdue
Customers with no sales after 7 days
Customers who purchased Product Group A
```

---

# Important Edit Warning for `qualifiers`

When editing `qualifiers`, MCP should treat the provided qualifier branch as the desired qualifier configuration.

Do not send partial nested qualifier objects unless the platform explicitly supports nested merging.

Safer approach:

```text
When changing qualifiers, send the complete intended active qualifier branch.
```

For example, if editing a `specific_values` group and only changing `lifetime_value`, MCP should still know and preserve the other intended active filters, values, and subscription options.

Why:

A partial nested qualifier edit can accidentally remove, disable, or omit existing qualification rules if the API treats the nested object as a replacement.

Safe workflow:

1. Retrieve or know the current Customer Group configuration.
2. Build the complete desired final qualifier branch.
3. Confirm inactive branches are not being relied on.
4. Send `EditCustomerGroup`.

---

# `specific_values.filters`

Filters qualify customers based on related objects or metadata.

Shape:

```json
"filters": {
  "campaign": [],
  "product_group": [],
  "third_party_shop": [],
  "metadata": []
}
```

---

## `filters.campaign`

Type:

```text
array<string>
```

Each value must be a 20-character campaign ID.

Meaning:

Customers qualify if they are associated with one of the listed campaigns.

If empty:

```json
"campaign": []
```

there is no campaign filter.

If multiple campaign IDs are provided, a customer only needs to match one of them.

Logic:

```text
campaign A OR campaign B OR campaign C
```

---

## `filters.product_group`

Type:

```text
array<string>
```

Each value must be a 20-character product group ID.

Meaning:

Customers qualify if they have purchased a product within one of the listed product groups.

If empty, there is no product group qualification.

If multiple product group IDs are provided, a customer only needs to match one of them.

Logic:

```text
product_group A OR product_group B OR product_group C
```

---

## `filters.third_party_shop`

Type:

```text
array<string>
```

Each value must be a 20-character user shop ID.

Meaning:

Customers qualify if they made a purchase from one of the listed third-party shops.

If empty, there is no third-party shop qualification.

If multiple shop IDs are provided, a customer only needs to match one of them.

Logic:

```text
shop A OR shop B OR shop C
```

---

## `filters.metadata`

Type:

```text
array<object>
```

Each metadata filter object has:

| Field | Type | Description |
|---|---:|---|
| `name` | string | Metadata name to qualify on. |
| `value` | string | Metadata value, or `METADATA_NAME_EXISTS`. |

Example:

```json
"metadata": [
  {
    "name": "affiliate_id",
    "value": "aff_123"
  }
]
```

Special value:

```text
METADATA_NAME_EXISTS
```

Example:

```json
"metadata": [
  {
    "name": "crm_id",
    "value": "METADATA_NAME_EXISTS"
  }
]
```

Meaning:

Customer qualifies if metadata name `crm_id` exists, regardless of value.

---

## Metadata Filter Logic

If multiple metadata filters are provided, the customer must qualify for all metadata filters.

General logic:

```text
metadata filter 1 AND metadata filter 2 AND metadata filter 3
```

However, if multiple values are provided for the same metadata name, values are grouped by name and the customer must match at least one value for that name.

Example:

```json
"metadata": [
  {
    "name": "affiliate_id",
    "value": "aff_123"
  },
  {
    "name": "affiliate_id",
    "value": "aff_456"
  },
  {
    "name": "customer_tier",
    "value": "gold"
  }
]
```

Logic:

```text
(affiliate_id = aff_123 OR affiliate_id = aff_456)
AND customer_tier = gold
```

---

# `specific_values.values`

`values` contains customer metrics and numeric qualifiers.

General behavior:

- A customer must match all enabled specific values.
- If a value is not enabled, it does not affect qualification.
- If enabled, the customer must be greater than or equal to `min`.
- If enabled, the customer must be less than or equal to `max`.
- If enabled and both `min` and `max` are `0`, then the corresponding customer value must be exactly `0`.

General shape:

```json
"lifetime_value": {
  "enabled": true,
  "min": 500,
  "max": 999999
}
```

---

## Important Range Rule

For most value objects:

```json
{
  "enabled": true,
  "min": 0,
  "max": 0
}
```

means:

```text
Customer value must be exactly 0
```

This is not the same as “no max.”

If the user means no practical upper limit, MCP should use a deliberate high maximum value.

---

## `values.has_no_sales`

Type:

```text
boolean
```

Meaning:

If `true`, customer must have 0 sales on record.

Important behavior:

If `has_no_sales` is `true`, then no other `qualifiers.specific_values.values` are considered except `days_since_created`.

Recommended default:

```json
"has_no_sales": false
```

Use cases:

- Prospects
- Signups with no purchase attempts
- Leads created before checkout
- Customers who have not attempted purchases

---

## `values.days_since_created`

Fields:

| Field | Type | Notes |
|---|---:|---|
| `enabled` | boolean | Whether this qualifier is active. |
| `min` | integer | Minimum days since creation. Must be greater than 0. |
| `max` | integer | Maximum days since creation. Must be greater than 0. |

Example:

```json
"days_since_created": {
  "enabled": true,
  "min": 7,
  "max": 30
}
```

---

## `values.lifetime_value`

Uses customer lifetime value.

Example:

```json
"lifetime_value": {
  "enabled": true,
  "min": 500,
  "max": 999999
}
```

Use cases:

- VIP customers
- High-value recovery
- Customer success prioritization
- Offer eligibility

---

## `values.lifetime_refunded`

Uses lifetime sum amount of refunds.

Example:

```json
"lifetime_refunded": {
  "enabled": true,
  "min": 100,
  "max": 999999
}
```

Use cases:

- High refund risk
- Refund review
- Customer quality analysis

---

## `values.num_sale`

Uses total sales count.

Example:

```json
"num_sale": {
  "enabled": true,
  "min": 2,
  "max": 999999
}
```

---

## `values.avg_sale`

Uses average sale amount.

Example:

```json
"avg_sale": {
  "enabled": true,
  "min": 100,
  "max": 999999
}
```

---

## `values.days_last_sale`

Uses days since last sale.

Fields:

| Field | Type | Notes |
|---|---:|---|
| `enabled` | boolean | Whether active. |
| `min` | integer | Minimum days since last sale. Must be greater than 0. |
| `max` | integer | Maximum days since last sale. Must be greater than 0. |

Example:

```json
"days_last_sale": {
  "enabled": true,
  "min": 90,
  "max": 365
}
```

---

## `values.num_success_sale`

Uses number of successful sales.

Example:

```json
"num_success_sale": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

---

## `values.num_upsell_sale`

Uses number of upsell sales.

Example:

```json
"num_upsell_sale": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

---

## `values.num_pending_declined_sale`

Uses number of declined sales.

Example:

```json
"num_pending_declined_sale": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

Use cases:

- Decline recovery
- Payment update outreach
- Failed sale recovery
- High-value payment salvage

---

## `values.num_pending_abandoned_sale`

Uses number of abandoned sales.

Example:

```json
"num_pending_abandoned_sale": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

Use cases:

- Abandoned cart/sale recovery
- High-intent customer recovery
- Email reminder workflows
- AI Voice Agent follow-up

---

## `values.num_fraud_detection`

Uses fraud detection count.

Example:

```json
"num_fraud_detection": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

---

## `values.lifetime_chargeback`

Uses lifetime sum amount of chargebacks.

Example:

```json
"lifetime_chargeback": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

---

## `values.num_chargeback`

Uses number of chargebacks.

Example:

```json
"num_chargeback": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

To require zero chargebacks:

```json
"num_chargeback": {
  "enabled": true,
  "min": 0,
  "max": 0
}
```

---

## `values.lifetime_paypal_dispute`

Uses lifetime sum amount of PayPal disputes.

Example:

```json
"lifetime_paypal_dispute": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

---

## `values.num_paypal_dispute`

Uses number of PayPal disputes.

Example:

```json
"num_paypal_dispute": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

---

# `specific_values.subscription_options`

Subscription options qualify customers based on subscription behavior.

Shape:

```json
"subscription_options": {
  "enabled": true,
  "days_last_renewal": {},
  "num_renewal": {},
  "num_success_renewal": {},
  "num_overdue_renewal": {},
  "status": []
}
```

If `subscription_options.enabled` is not true, subscription options should not be treated as active qualification criteria.

---

## `subscription_options.days_last_renewal`

Fields:

```text
enabled, min, max
```

Uses days since the customer’s last subscription renewal.

Example:

```json
"days_last_renewal": {
  "enabled": true,
  "min": 30,
  "max": 90
}
```

---

## `subscription_options.num_renewal`

Uses number of subscription renewals completed.

Example:

```json
"num_renewal": {
  "enabled": true,
  "min": 3,
  "max": 999999
}
```

---

## `subscription_options.num_success_renewal`

Uses number of successful subscription renewals.

Example:

```json
"num_success_renewal": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

---

## `subscription_options.num_overdue_renewal`

Uses number of overdue subscription renewals.

Example:

```json
"num_overdue_renewal": {
  "enabled": true,
  "min": 1,
  "max": 999999
}
```

Use cases:

- Subscription payment recovery
- Overdue renewal outreach
- AI Voice Agent recovery calls
- High-value subscription save workflows

---

## `subscription_options.status`

Type:

```text
array<string>
```

Allowed statuses:

```text
active
trial
overdue
occurrence_limit
suspended
cancelled
```

If empty:

```json
"status": []
```

there is no subscription status qualification.

If multiple statuses are provided, a customer only needs to match one of them.

Logic:

```text
status active OR status trial OR status overdue
```

---

# OR vs AND Logic Guidance

MCP must be careful with qualification logic.

## OR-Like Behavior

These arrays are OR-style within their category:

```text
campaign
product_group
third_party_shop
subscription_options.status
customer_group.in_any_customer_group
```

Examples:

```text
campaign A OR campaign B
```

```text
status trial OR overdue
```

---

## AND-Like Behavior

These are generally AND-style:

```text
multiple enabled specific_values.values
multiple metadata names
in_all_customer_group
filters combined with values/subscription options
```

Examples:

```text
lifetime_value >= 500
AND days_last_sale >= 90
```

```text
affiliate_id = aff_123
AND customer_tier = gold
```

---

## Mixed Metadata Behavior

Multiple values for the same metadata name are grouped OR-style, while different metadata names are AND-style.

Example:

```text
(affiliate_id = aff_123 OR affiliate_id = aff_456)
AND customer_tier = gold
```

---

# Handling Edits That Need Both Specific Values and Group Membership

Because `specific_values` and `customer_group` are separate methods, MCP clients should not try to combine both branches in one group.

If the business needs logic like:

```text
Lifetime value >= 500
AND customer is not in Do Not Contact
```

do not create/edit one group with:

```text
qualifier_method = specific_values
+ qualifiers.customer_group.not_in_customer_group
```

Instead, use a layered group strategy.

Recommended approach:

1. Create or maintain a `specific_values` group:

```text
High Value Customers
= lifetime_value >= 500
```

2. Create or edit a `customer_group` composite group:

```text
High Value Outreach Eligible
= in High Value Customers
AND not in Do Not Contact
```

This keeps qualification logic clear and avoids relying on ignored branches.

---

# High-Risk Edits

The following edits are high impact:

- Changing `qualifier_method`.
- Changing `qualifiers`.
- Enabling a previously disabled group.
- Changing a broad group’s description if automations depend on descriptions.
- Changing metadata filters.
- Changing lifetime value thresholds.
- Changing payment recovery qualifiers.
- Changing subscription status or overdue renewal qualifiers.
- Changing suppression group logic.
- Removing `not_in_customer_group` suppression.
- Broadening a group connected to AI Voice Agent or email outreach.
- Editing a group that triggers external AI Agents or Functions.

For high-risk edits, MCP should consider:

```text
Disable group → edit qualifiers → review expected membership impact → re-enable intentionally
```

---

# Customer Group Events and Edit Consequences

Editing a Customer Group can cause customers to be added to or removed from the group.

Important event notations:

```text
customer.updated.customer_group.added
customer.updated.customer_group.removed
```

These events can trigger automation.

Examples:

- AI Assistant runs when customer enters `High Value Recovery`.
- AI Voice Agent calls when customer enters `Payment Recovery`.
- Function updates CRM when customer enters `VIP`.
- External AI Agent reviews risk when customer enters `Fraud Review`.
- Email Template sends winback message when customer enters `Winback Candidates`.

Before editing qualifiers, MCP should determine whether group added/removed events are connected to automation.

If they are, MCP should be especially careful with broadening or narrowing the group.

---

# Safe Edit Workflow

Recommended workflow:

1. Identify the `customer_group_id`.
2. Determine exactly which fields need to change.
3. Do not include unrelated fields.
4. If editing name/description only, do not include qualifiers.
5. If editing `enabled`, do not include qualifiers unless also intentionally changing them.
6. If editing `qualifier_method`, identify the active qualifier branch.
7. If editing `qualifiers`, build the complete intended active branch.
8. Verify inactive qualifier branches are not being relied on.
9. Confirm AND/OR behavior.
10. Confirm all IDs are real 20-character IDs.
11. Consider disabling first if the group is active and automation is connected.
12. Submit `EditCustomerGroup`.
13. Verify the edited group behaves as intended.
14. Monitor group membership and event-triggered workflows if high impact.

---

# MCP Questions Before Editing

Before calling `EditCustomerGroup`, MCP should ask:

1. Which Customer Group should be edited?
2. What fields should be changed?
3. Is this a name/description-only edit?
4. Is the enabled state changing?
5. Are qualifiers changing?
6. Is `qualifier_method` changing?
7. If `qualifier_method` is changing, what should the new active qualifier branch be?
8. Should this group be manual/workflow-only, based on other groups, or based on specific customer values?
9. If manual, should qualifiers be cleared/ignored?
10. If based on other groups, which groups should be included/excluded?
11. If based on specific values, which filters/values/subscription options should be active?
12. Does the desired logic require AND or OR?
13. Would layered groups be safer?
14. Is this group currently enabled?
15. Are group added/removed events connected to automation?
16. Could editing this group trigger AI Assistants, AI Voice Agents, Email Templates, Functions, or external tools?
17. Should the group be disabled before editing?
18. Should the edited group remain disabled for review/testing?

---

# Validation Checklist

Before submitting `EditCustomerGroup`:

1. `customer_group_id` is present and is a 20-character ID.
2. Only intended fields are included.
3. No unknown fields are included.
4. If only name changes, qualifiers are omitted.
5. If only description changes, qualifiers are omitted.
6. If only enabled changes, qualifiers are omitted.
7. `qualifier_method`, if included, is one of `specific_values`, `customer_group`, or `none`.
8. The selected `qualifier_method` has only one active qualifier branch.
9. Inactive qualifier branches are not relied on.
10. If `qualifier_method` is `none`, all qualifiers are treated as ignored/manual-only.
11. If `qualifier_method` is `customer_group`, only `qualifiers.customer_group` is treated as active.
12. If `qualifier_method` is `specific_values`, only `qualifiers.specific_values` is treated as active.
13. If `qualifiers` is included, it represents the complete intended active qualifier branch.
14. All 20-character IDs are real IDs, not placeholders.
15. Empty arrays are intentional.
16. Metadata filters use correct name/value pairs.
17. `METADATA_NAME_EXISTS` is used only when existence is intended.
18. Numeric ranges are intentional.
19. No enabled range accidentally uses min `0` and max `0` unless exact zero is intended.
20. `has_no_sales` is true only when zero sales is intended.
21. If `has_no_sales` is true, other value qualifiers except `days_since_created` are understood to be ignored.
22. Subscription options are enabled only when subscription qualification is intended.
23. Subscription statuses are valid enum values.
24. OR vs AND logic has been reviewed.
25. Complex OR logic is split into separate groups if needed.
26. Event-triggered automation implications are understood.
27. Group is disabled first if broad qualifier edits could trigger many workflows.

---

# Example: Rename Only

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "name": "VIP Customers - 2026"
}
```

Because `qualifiers` is omitted, existing qualifier configuration is not intentionally changed.

---

# Example: Update Description Only

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "description": "Customers with lifetime value of at least 1000. Used for VIP support, customer success workflows, and VIP reporting."
}
```

---

# Example: Disable Group

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "enabled": false
}
```

Use this before a risky qualifier edit if automation is connected.

---

# Example: Enable Group

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "enabled": true
}
```

Only enable after qualifiers and automation effects are understood.

---

# Example: Convert Group to Manual

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "none",
  "qualifiers": {},
  "description": "Manual/workflow-only group. Customers are added or removed by support, AI review, Function, or external workflow. No qualifiers are evaluated."
}
```

---

# Example: Edit to Specific Values

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "specific_values",
  "qualifiers": {
    "specific_values": {
      "filters": {
        "campaign": [],
        "product_group": [],
        "third_party_shop": [],
        "metadata": []
      },
      "values": {
        "has_no_sales": false,
        "lifetime_value": {
          "enabled": true,
          "min": 500,
          "max": 999999
        },
        "days_last_sale": {
          "enabled": true,
          "min": 90,
          "max": 365
        }
      },
      "subscription_options": {
        "enabled": false,
        "status": []
      }
    }
  },
  "description": "Customers with lifetime value of at least 500 who have not purchased in 90 to 365 days. Used for winback workflows."
}
```

---

# Example: Edit to Customer-Group Composite

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "customer_group",
  "qualifiers": {
    "customer_group": {
      "in_any_customer_group": [],
      "in_all_customer_group": [
        "HIGH_VALUE_GROUP_ID",
        "WINBACK_GROUP_ID"
      ],
      "not_in_customer_group": [
        "DO_NOT_CONTACT_GROUP_ID"
      ]
    }
  },
  "description": "Composite group for customers in both High Value and Winback Candidate groups, excluding Do Not Contact."
}
```

Replace placeholder IDs with real 20-character group IDs.

---

# Common Mistakes

## Mistake: Including `qualifiers` in a Name-Only Edit

Wrong:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "name": "Updated Name",
  "qualifiers": {
    "specific_values": {}
  }
}
```

Correct:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "name": "Updated Name"
}
```

---

## Mistake: Relying on Inactive Qualifier Branches

Wrong expectation:

```text
qualifier_method = customer_group
but lifetime_value should also apply
```

Correct understanding:

```text
customer_group only evaluates qualifiers.customer_group.
```

---

## Mistake: Changing Method Without Updating Qualifiers

Potentially risky:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "specific_values"
}
```

This may activate existing stored `specific_values` qualifiers if they exist, or leave the group without the intended active branch.

Safer:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "qualifier_method": "specific_values",
  "qualifiers": {
    "specific_values": {
      "filters": {
        "campaign": [],
        "product_group": [],
        "third_party_shop": [],
        "metadata": []
      },
      "values": {
        "has_no_sales": false
      },
      "subscription_options": {
        "enabled": false,
        "status": []
      }
    }
  }
}
```

---

## Mistake: Using `0` Max as “No Limit”

Wrong assumption:

```json
"lifetime_value": {
  "enabled": true,
  "min": 500,
  "max": 0
}
```

This should not be used to mean “500 or higher.”

---

## Mistake: Forgetting `has_no_sales` Overrides Other Value Qualifiers

If this is true:

```json
"has_no_sales": true
```

then other `specific_values.values` are ignored except `days_since_created`.

---

## Mistake: Broadening an Active Group Connected to Automation

If a group triggers AI Voice Agent calls, Email Templates, Functions, or external tools, broadening its qualifiers can trigger many automations.

Safer approach:

```text
Disable → edit → review → enable intentionally
```

---

# Output Schema

Successful response:

```json
{
  "api_call_id": "XXXXXXXXXXXXXXXXXXXX",
  "api_call_unix": 1740000000,
  "code": 1,
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "result": "..."
}
```

| Field | Description |
|---|---|
| `api_call_id` | 20-character API call ID. |
| `api_call_unix` | Unix timestamp when the call was initiated. |
| `code` | API response code. `1` indicates success. |
| `customer_group_id` | 20-character Customer Group ID edited by the operation. |
| `result` | Human-readable result message. |

---

# Quick Reference

Minimum request:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX"
}
```

Name-only edit:

```json
{
  "customer_group_id": "XXXXXXXXXXXXXXXXXXXX",
  "name": "Updated Group Name"
}
```

Qualifier methods:

```text
none = manual/workflow-only membership; all qualifiers ignored
specific_values = only qualifiers.specific_values is active; filters, values, metadata, subscription options
customer_group = only qualifiers.customer_group is active; membership/non-membership in other groups
```

Most important MCP rule:

```text
EditCustomerGroup is a partial-update operation. Only include fields being changed, and never rely on an inactive qualifier branch.
```

High-impact edit rule:

```text
If changing qualifier_method, qualifiers, or enabled state on a group connected to automation, consider disabling first, editing carefully, reviewing the expected membership impact, and enabling intentionally.
```


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