# RevCent MCP Guide: `EditShippingProfile`

AI/MCP-focused guide for editing Shipping Profiles in RevCent.

This document is meant to be read by AI agents, MCP clients, automation tools, and developers that need to understand how to correctly edit a Shipping Profile, especially when modifying the `rates` array.

---

## Related Overview

Before editing a Shipping Profile, AI/MCP clients should read the Shipping Profile overview:

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

The overview explains how Shipping Profiles are used to calculate shipping rates for Sales, trial expirations, and subscription renewals involving shippable products.

Recommended related reference:

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

Use the Create guide for initial schema construction patterns. Use this Edit guide for safe modification behavior.

---

## Operation Summary

Operation:

```text
EditShippingProfile
```

Title:

```text
Edit A Shipping Profile
```

Purpose:

```text
Edit a specific Shipping Profile using the shipping_profile_id.
```

Important:

```text
EditShippingProfile is a very consequential operation and should only be performed upon explicit confirmation from the user.
```

Editing a Shipping Profile can affect:

- checkout shipping calculations,
- trial expiration shipping calculations,
- subscription renewal shipping calculations,
- shippable-product shipment creation,
- customer-facing shipping charges,
- future recurring fulfillment behavior.

Do not edit a Shipping Profile casually.

---

## Core Safety Rule

`EditShippingProfile` supports partial top-level edits.

If the user only wants to edit the name, send only:

```json
{
  "shipping_profile_id": "XXXXXXXXXXXXXXXXXXXX",
  "name": "Updated Shipping Profile Name"
}
```

If the user only wants to disable the profile, send only:

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

But:

```text
rates is different.
```

If `rates` is included, it replaces the entire rate array.

Critical rule:

```text
EditShippingProfile.rates is a full replacement array, not a patch array.
```

If the profile currently has two rates and the request includes only one rate, the profile will end up with only that one rate. The omitted rate will be removed.

---

## Required Safe Workflow for Editing Rates

Always use this workflow when modifying rates:

```text
1. Call GetShippingProfile.
2. Retrieve the current full rates array.
3. Copy all existing rates that should remain.
4. Modify only the intended rate(s).
5. Add any new rate(s), if needed.
6. Remove only the rates the user explicitly wants removed.
7. Send the full final rates array to EditShippingProfile.
8. Verify the updated profile.
```

Never send only the changed rate unless the user explicitly wants all other rates removed.

---

## Schema Overview

`EditShippingProfile` input schema:

```text
type: object
additionalProperties: false
required:
  - shipping_profile_id
```

Supported top-level fields:

| Field | Type | Required | Description |
|---|---:|---:|---|
| `shipping_profile_id` | string | Yes | 20-character Shipping Profile ID. |
| `name` | string | No | Shipping Profile name. |
| `description` | string | No | Shipping Profile description. |
| `enabled` | boolean | No | Whether the Shipping Profile is enabled. |
| `rates` | array<object> | No | Full array of shipping rates to associate with the profile. If included, replaces the profile's rates array. |

Important schema rule:

```text
Do not send unknown fields.
```

Unsupported fields should not be included.

---

## Output Schema

Successful output can include:

| Field | Type | Description |
|---|---:|---|
| `api_call_id` | string | 20-character API call ID. |
| `api_call_unix` | integer | Unix timestamp when the API call was initiated. |
| `code` | integer | API call response code. `1` indicates success. |
| `shipping_profile_id` | string | 20-character Shipping Profile ID. |
| `result` | string | Result message. |

---

## Required User Confirmation

Editing a Shipping Profile can change customer-facing shipping charges.

AI/MCP clients should confirm the user's intent before calling `EditShippingProfile`.

Confirm:

- which Shipping Profile should be edited,
- whether the profile is currently enabled,
- which fields should change,
- whether rates are being changed,
- whether any existing rates should be removed,
- whether the profile should remain enabled after the edit,
- whether the change should affect live checkout, renewals, and trials,
- whether the user understands the full replacement behavior of `rates`.

Recommended safety question before editing rates:

```text
I retrieved the existing rates. I will send the full rates array back with only the requested changes. Please confirm these are the final rates that should remain on this Shipping Profile.
```

---

## Top-Level Partial Edit Fields

### `shipping_profile_id`

Required.

The 20-character Shipping Profile ID.

Example:

```json
{
  "shipping_profile_id": "XXXXXXXXXXXXXXXXXXXX"
}
```

Do not guess this ID.

Use `GetShippingProfiles` to locate profile IDs and `GetShippingProfile` to inspect the profile before editing.

---

### `name`

Optional.

Use to rename the Shipping Profile.

Example:

```json
{
  "shipping_profile_id": "XXXXXXXXXXXXXXXXXXXX",
  "name": "US Supplements Shipping"
}
```

This changes only the name.

Good names:

```text
US Supplements Shipping
US Free Shipping Over $75
Subscription Refills Shipping
Trial Kits Shipping
WooCommerce Renewal Shipping
Canada Apparel Shipping
```

Poor names:

```text
Shipping
Test
Profile
Rate
```

---

### `description`

Optional.

Use to update the profile description.

Example:

```json
{
  "shipping_profile_id": "XXXXXXXXXXXXXXXXXXXX",
  "description": "Shipping rates for US supplement products, including subscription renewals and trial expirations."
}
```

A good description should explain:

- what products/product groups the profile covers,
- whether it is for Sales, renewals, trials, or all shipping events,
- what countries/regions it covers,
- any thresholds or special rules,
- whether it is for a specific shop, brand, or campaign.

---

### `enabled`

Optional.

Use to enable or disable the Shipping Profile.

Example disable request:

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

Example enable request:

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

Important:

```text
Enabled Shipping Profiles can be considered by RevCent during shipping-rate calculation.
```

Disable a profile when:

- rates are being reworked,
- qualifiers may be wrong,
- provider/method IDs need verification,
- the business no longer wants the profile active,
- a safer replacement profile is being created.

Enable a profile only when:

- rates are reviewed,
- qualifiers are valid,
- provider/provider method IDs are correct,
- trial/renewal behavior is understood,
- the user explicitly wants it active.

---

## `rates` Field

Optional top-level field, but very important.

`rates` is an array of shipping rate objects.

If `rates` is provided in an edit request, it becomes the full set of rates associated with the Shipping Profile.

Critical behavior:

```text
The rates array is overwritten by the request.
```

This means:

```text
Current profile rates:
- Rate A
- Rate B

Edit request rates:
- Rate A modified

Result:
- Rate A modified
- Rate B removed
```

Correct request must include:

```text
- Rate A modified
- Rate B unchanged
```

if both should remain.

---

## Shipping Rate Object

Each rate includes:

| Field | Type | Required | Description |
|---|---:|---:|---|
| `rate` | number | Yes | Shipping amount charged to the customer. |
| `provider` | string | Yes | 20-character site shipping provider ID. |
| `provider_method` | string | Yes | 20-character site shipping provider method ID. |
| `qualifiers` | object | Yes | Rules that determine whether the rate applies. |

Conceptual meaning:

```text
Charge this shipping amount using this provider/method when these qualifiers match.
```

---

## Rate: `rate`

Required number.

This is the shipping amount charged to the customer.

Examples:

```json
"rate": 6.95
```

```json
"rate": 0
```

Use `0` for free shipping.

Do not confuse `rate` with fulfillment cost, carrier cost, product price, tax, or discount. It is the amount charged for shipping.

---

## Rate: `provider`

Required string.

A 20-character site shipping provider ID.

Correct:

```json
"provider": "XXXXXXXXXXXXXXXXXXXX"
```

Incorrect:

```json
"provider": "USPS"
```

Use RevCent shipping provider operations, such as:

```text
GetShippingProviders
GetShippingProvider
```

to retrieve real provider IDs.

Do not guess provider IDs.

---

## Rate: `provider_method`

Required string.

A 20-character site shipping provider method ID.

Correct:

```json
"provider_method": "YYYYYYYYYYYYYYYYYYYY"
```

Incorrect:

```json
"provider_method": "Priority Mail"
```

Use real RevCent provider method IDs.

Do not guess provider method IDs.

---

## Rate: `qualifiers`

Required object.

Qualifiers determine whether a rate applies.

Qualifier groups:

| Group | Purpose |
|---|---|
| `products` | Match specific products and quantity rules. |
| `product_groups` | Match Product Groups. |
| `countries` | Match destination countries. |
| `revenue_rules` | Match purchase amount thresholds. |

Critical rule:

```text
Every shipping rate must contain at least one enabled qualifier within products, product_groups, countries, or revenue_rules.
```

A shipping rate cannot contain zero enabled qualifiers.

At least one of these arrays must contain an object with `enabled: true`:

```text
qualifiers.products
qualifiers.product_groups
qualifiers.countries
qualifiers.revenue_rules
```

---

## Qualifier Matching Concept

RevCent analyzes enabled Shipping Profiles and their rates, then finds the best matching shipping rate based on the number of matched qualifiers.

More specific rates can win over generic rates when they match more qualifier dimensions.

Example:

| Rate | Qualifiers | Match Count |
|---|---|---:|
| Generic USA rate | country = USA | 1 |
| Supplement USA rate | product group = Supplements, country = USA | 2 |
| Supplement USA free shipping over $75 | product group = Supplements, country = USA, revenue rule >= 75 | 3 |

If all qualify, the most specific rate is expected to be selected because it has the most matched qualifiers.

AI/MCP clients should preserve and edit rates so this specificity remains intentional.

---

## `qualifiers.products`

Product qualifiers apply rates to specific Product IDs.

Schema:

| Field | Type | Required | Description |
|---|---:|---:|---|
| `id` | string | Yes | 20-character Product ID. |
| `enabled` | boolean | Yes | Whether this product qualifier is enabled. |
| `quantity_rule` | enum | Yes | Quantity comparison rule. |
| `quantity_value` | integer | Yes | Quantity value used with the rule. |

Allowed `quantity_rule` values:

```text
any
equal_to
greater_than
greater_than_equal_to
less_than
less_than_equal_to
```

Example:

```json
{
  "id": "AAAAAAAAAAAAAAAAAAAA",
  "enabled": true,
  "quantity_rule": "any",
  "quantity_value": 0
}
```

Use product qualifiers when a rate should apply to specific products.

Best practice:

```text
Use Product Group qualifiers when possible; use Product qualifiers only when rate behavior truly depends on a specific Product ID or quantity.
```

---

## Product Quantity Rules

Quantity rules determine whether the Product qualifier passes.

Examples:

| Rule | Meaning |
|---|---|
| `any` | Product only needs to be present. |
| `equal_to` | Quantity must equal `quantity_value`. |
| `greater_than` | Quantity must be greater than `quantity_value`. |
| `greater_than_equal_to` | Quantity must be greater than or equal to `quantity_value`. |
| `less_than` | Quantity must be less than `quantity_value`. |
| `less_than_equal_to` | Quantity must be less than or equal to `quantity_value`. |

Example:

```json
{
  "id": "AAAAAAAAAAAAAAAAAAAA",
  "enabled": true,
  "quantity_rule": "greater_than_equal_to",
  "quantity_value": 2
}
```

This qualifier applies when the product quantity is at least 2.

---

## `qualifiers.product_groups`

Product Group qualifiers apply rates to Product Groups.

Schema:

| Field | Type | Required | Description |
|---|---:|---:|---|
| `id` | string | Yes | 20-character Product Group ID. |
| `enabled` | boolean | Yes | Whether this Product Group qualifier is enabled. |

Example:

```json
{
  "id": "PPPPPPPPPPPPPPPPPPPP",
  "enabled": true
}
```

Product Group qualifiers are often the best option for ecommerce shipping rules because they are easier to maintain.

Examples:

- Supplements
- Apparel
- Heavy Items
- Starter Kits
- Trial Kits
- Subscription Refills
- WooCommerce Shop Products
- US Warehouse Products
- EU Warehouse Products

Best practice:

```text
For a shop's products, use Product Groups to organize products and create Shipping Profile rates around those groups.
```

---

## `qualifiers.countries`

Country qualifiers match the shipment destination country.

Schema:

| Field | Type | Required | Description |
|---|---:|---:|---|
| `iso_code` | string | Yes | ISO3 country code. |
| `enabled` | boolean | Yes | Whether this country qualifier is enabled. |

Example:

```json
{
  "iso_code": "USA",
  "enabled": true
}
```

Behavior:

```text
The shipment destination country must match at least one enabled country code in the array.
```

The schema says:

```text
Leave empty to apply to all countries.
```

Use ISO3 codes:

```text
USA
CAN
GBR
AUS
```

Do not use two-letter country codes.

---

## `qualifiers.revenue_rules`

Revenue rules allow rates to apply based on amount thresholds.

Schema:

| Field | Type | Required | Description |
|---|---:|---:|---|
| `enabled` | boolean | Yes | Whether this revenue rule is enabled. |
| `source` | enum | Yes | Which amount to evaluate. |
| `rule` | enum | Yes | Comparison operator. |
| `rule_value` | number | Yes | Amount used for comparison. |

Allowed `source` values:

```text
total_amount
transaction_amount
shippable_products
```

Allowed `rule` values:

```text
equal_to
greater_than
greater_than_equal_to
less_than
less_than_equal_to
```

Example:

```json
{
  "enabled": true,
  "source": "shippable_products",
  "rule": "greater_than_equal_to",
  "rule_value": 75
}
```

Use revenue rules for:

- free shipping thresholds,
- discounted shipping thresholds,
- rate changes based on shippable product amount,
- subscription renewal shipping tiers,
- trial expiration shipping tiers.

---

## Choosing the Right Revenue Source

| Source | Meaning |
|---|---|
| `total_amount` | Total amount of the associated purchase. |
| `transaction_amount` | Transaction amount of the associated purchase. |
| `shippable_products` | Total amount for shippable products in the transaction. |

Use `shippable_products` when the shipping threshold should only consider physical goods.

Example:

```text
Free shipping when shippable product subtotal is at least $75.
```

Use `total_amount` when the full purchase total should qualify.

Use `transaction_amount` when the actual payment/transaction amount should qualify.

---

## Safe Simple Edit Examples

### Rename Profile

```json
{
  "shipping_profile_id": "XXXXXXXXXXXXXXXXXXXX",
  "name": "US Supplements Shipping"
}
```

### Update Description

```json
{
  "shipping_profile_id": "XXXXXXXXXXXXXXXXXXXX",
  "description": "Shipping rates for US supplement products, including renewals and trial expirations."
}
```

### Disable Profile

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

### Enable Profile

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

These are safe partial edits because they do not include `rates`.

---

## Unsafe Rate Edit Example

Current profile has two rates:

```text
Rate A: $6.95 below $75
Rate B: free shipping at $75+
```

User wants to change Rate A to $7.95.

Unsafe request:

```json
{
  "shipping_profile_id": "XXXXXXXXXXXXXXXXXXXX",
  "rates": [
    {
      "rate": 7.95,
      "provider": "XXXXXXXXXXXXXXXXXXXX",
      "provider_method": "YYYYYYYYYYYYYYYYYYYY",
      "qualifiers": {
        "products": [],
        "product_groups": [
          {
            "id": "PPPPPPPPPPPPPPPPPPPP",
            "enabled": true
          }
        ],
        "countries": [
          {
            "iso_code": "USA",
            "enabled": true
          }
        ],
        "revenue_rules": [
          {
            "enabled": true,
            "source": "shippable_products",
            "rule": "less_than",
            "rule_value": 75
          }
        ]
      }
    }
  ]
}
```

Why unsafe:

```text
Rate B will be removed because rates is a replacement array.
```

---

## Safe Rate Edit Example

Current profile has two rates:

```text
Rate A: $6.95 below $75
Rate B: free shipping at $75+
```

User wants to change Rate A to $7.95.

Safe request includes both final rates:

```json
{
  "shipping_profile_id": "XXXXXXXXXXXXXXXXXXXX",
  "rates": [
    {
      "rate": 7.95,
      "provider": "XXXXXXXXXXXXXXXXXXXX",
      "provider_method": "YYYYYYYYYYYYYYYYYYYY",
      "qualifiers": {
        "products": [],
        "product_groups": [
          {
            "id": "PPPPPPPPPPPPPPPPPPPP",
            "enabled": true
          }
        ],
        "countries": [
          {
            "iso_code": "USA",
            "enabled": true
          }
        ],
        "revenue_rules": [
          {
            "enabled": true,
            "source": "shippable_products",
            "rule": "less_than",
            "rule_value": 75
          }
        ]
      }
    },
    {
      "rate": 0,
      "provider": "XXXXXXXXXXXXXXXXXXXX",
      "provider_method": "YYYYYYYYYYYYYYYYYYYY",
      "qualifiers": {
        "products": [],
        "product_groups": [
          {
            "id": "PPPPPPPPPPPPPPPPPPPP",
            "enabled": true
          }
        ],
        "countries": [
          {
            "iso_code": "USA",
            "enabled": true
          }
        ],
        "revenue_rules": [
          {
            "enabled": true,
            "source": "shippable_products",
            "rule": "greater_than_equal_to",
            "rule_value": 75
          }
        ]
      }
    }
  ]
}
```

Result:

```text
Rate A updated to $7.95.
Rate B remains on the profile.
```

---

## Example: Add a New Rate

To add a new rate, first retrieve existing rates with `GetShippingProfile`, then include existing rates plus the new rate.

Conceptual workflow:

```text
Current rates:
- US rate
- Canada rate

User wants to add UK rate.

EditShippingProfile request must include:
- US rate unchanged
- Canada rate unchanged
- UK rate new
```

Do not send only the UK rate unless the user wants the US and Canada rates removed.

---

## Example: Remove a Rate

To remove a rate, retrieve existing rates, remove only the intended rate, and send the remaining full array.

Conceptual workflow:

```text
Current rates:
- US rate
- Canada rate
- UK rate

User wants to remove UK rate.

EditShippingProfile request includes:
- US rate unchanged
- Canada rate unchanged
```

This intentionally removes UK rate.

Confirm with the user before removal.

---

## Third-Party Shop Guidance

For third-party shops such as WooCommerce:

```text
Initial Sale shipping may already be calculated by the shop and sent in the Sale request.
```

If the initial Sale API request includes a predefined shipping entry, RevCent uses that entry instead of calculating a new Shipping Profile rate.

However:

```text
Subscription renewals and trial expirations still require matching enabled Shipping Profile rates when shippable products need to ship.
```

This applies even when the product originally came from WooCommerce or another third-party shop.

RevCent does not use the initial Sale shipping amount as the rate source for future subscription renewals or trial expirations.

When editing Shipping Profiles for third-party shop products, verify:

- shop shipping methods are mapped in RevCent for initial Sales,
- subscription products have matching renewal rates,
- trial products have matching trial expiration rates,
- Product Groups are used where possible,
- third-party shop products have correct `internal_id` and `third_party_shop` mappings,
- shippable products have Fulfillment Accounts.

---

## Required Pre-Checks Before Calling `EditShippingProfile`

Before editing a Shipping Profile, verify:

- User explicitly confirmed the edit.
- `shipping_profile_id` is correct.
- `GetShippingProfile` has been used to inspect the current profile.
- Profile enabled state is understood.
- Only intended top-level fields are included.
- If editing `rates`, the full final rates array is included.
- Existing rates that should remain are preserved.
- Rates the user wants removed are intentionally omitted.
- Each remaining/new rate has `rate`, `provider`, `provider_method`, and `qualifiers`.
- Every remaining/new rate has at least one enabled qualifier.
- Provider IDs are real.
- Provider method IDs are real.
- Product IDs are real.
- Product Group IDs are real.
- Country codes are ISO3.
- Revenue rules use correct source/rule/value.
- Overlapping rate specificity is intentional.
- Renewal/trial shipping behavior is understood.
- Third-party shop initial Sale vs renewal/trial shipping behavior is understood.

---

## Best Practices

1. Always retrieve the profile before editing.
2. Use partial edits for simple fields.
3. Do not include `rates` unless changing rates.
4. Treat `rates` as a full replacement array.
5. Preserve all existing rates that should remain.
6. Confirm before removing any rate.
7. Prefer Product Group qualifiers over many Product qualifiers.
8. Use ISO3 country codes.
9. Do not guess provider/provider method IDs.
10. Disable profiles while making major changes if needed.
11. Test rate calculation after editing.
12. Verify subscription renewal and trial expiration shipping after changes.
13. Use clear names and descriptions.
14. Avoid overlapping rates unless best-match behavior is intentional.

---

## Common Mistakes to Avoid

Do not:

- edit rates without first calling `GetShippingProfile`,
- send only the changed rate when other rates should remain,
- accidentally remove rates by omitting them from the replacement array,
- include `rates` in a simple name/description/enabled edit,
- create a rate with zero enabled qualifiers,
- use provider names instead of provider IDs,
- use provider method names instead of provider method IDs,
- use two-letter country codes instead of ISO3 country codes,
- confuse Shipping Profiles with Fulfillment Accounts,
- confuse Shipping Profiles with third-party shop shipping-method mapping,
- expect Shipping Profiles to override an initial Sale request that already includes shipping,
- rely on initial Sale shipping for future renewals/trial expirations,
- edit an enabled live profile without understanding customer-facing impact,
- use unsupported fields in the request body.

---

## Troubleshooting After Editing

If expected shipping calculation does not occur after editing, check:

- Is the Shipping Profile enabled?
- Was the correct profile edited?
- Did the rates array accidentally remove a needed rate?
- Does the rate have at least one enabled qualifier?
- Does the product/Product Group match?
- Does the country qualifier match destination ISO3 country?
- Does the quantity rule pass?
- Does the revenue rule pass?
- Are provider/provider method IDs valid?
- Did another enabled rate match more qualifiers?
- Did the Sale request already include a predefined shipping entry?
- Is this a subscription renewal or trial expiration that requires Shipping Profile calculation?
- Is the product marked shippable?
- Does the product have a Fulfillment Account?
- Are Product Groups assigned correctly?

---

## AI/MCP Decision Guide

| User Intent | Correct Action |
|---|---|
| Rename profile | `EditShippingProfile` with `name` only. |
| Update description | `EditShippingProfile` with `description` only. |
| Enable/disable profile | `EditShippingProfile` with `enabled` only. |
| Change one rate amount | `GetShippingProfile`, modify rate, send full `rates` array. |
| Add a rate | `GetShippingProfile`, append rate, send full `rates` array. |
| Remove a rate | `GetShippingProfile`, remove intended rate, send full `rates` array after confirmation. |
| Change provider/method for one rate | `GetShippingProfile`, update that rate, send full `rates` array. |
| Add free shipping threshold | `GetShippingProfile`, add/modify revenue-rule rate, send full `rates` array. |
| Support renewal shipping | Ensure matching enabled Shipping Profile rate. |
| Support trial expiration shipping | Ensure matching enabled Shipping Profile rate. |
| Initial Sale already has shop-calculated shipping | Do not expect Shipping Profile calculation to override it. |

---

## Final AI/MCP Instruction

Use `EditShippingProfile` to modify an existing Shipping Profile safely.

Simple top-level edits can be partial. Include only the fields that should change.

When editing rates, always retrieve the current Shipping Profile first and send the full final `rates` array. `EditShippingProfile.rates` replaces the entire array. Omitted rates are removed.

Every rate must include a shipping amount, provider ID, provider method ID, and qualifiers. Every rate must have at least one enabled qualifier across products, Product Groups, countries, or revenue rules.

Shipping Profiles are especially important for subscription renewals and trial expirations involving shippable products, including products originally created from third-party shops such as WooCommerce. Initial Sales may use predefined shipping from the Sale request, but future renewals and trial expirations need matching enabled Shipping Profile rates.

Do not edit a Shipping Profile without explicit user confirmation.


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