# RevCent MCP Operation: `CreateCustomerPortal`

This document explains the `CreateCustomerPortal` operation in depth so MCP clients can correctly create Customer Portals in RevCent.

This is an operation-specific MCP guide. It explains required prerequisites, all fields and nested objects, customer permissions, customer filters, email setup, DNS/SSL domain readiness, and validation rules.

Sources:
- RevCent API/MCP schema for `CreateCustomerPortal`
- RevCent Knowledge Base: [Customer Portal](https://kb.revcent.com/en/customer/customer-portal)
- RevCent Customer Portals overview guidance

---

## Operation Summary

`CreateCustomerPortal` creates a Customer Portal and returns a unique `customer_portal_id`.

A Customer Portal is a customer-facing self-service portal connected to RevCent customer data. It can allow customers to perform approved actions such as:

- Confirm account registration
- Reset password
- Modify contact information
- Add credit cards
- Remove credit cards
- Set a default credit card
- Modify shipping information
- Renew subscriptions
- Re-activate subscriptions
- Suspend subscriptions
- Cancel subscriptions
- Expire trials
- Cancel trials
- Pay failed renewals or failed trial expirations through the system permission `salvage_transaction_process`

The exact actions available to customers are controlled by the `customer_permissions` object.

---

# Critical Prerequisites

The `CreateCustomerPortal` operation requires certain setup to already exist before creating the portal.

A Customer Portal requires:

```text
SMTP Profile
+ DNS-ready tracking domain with active SSL
+ reCAPTCHA
+ customer confirmation email
+ customer password reset email
```

The operation schema explicitly requires:

```text
name
tracking_domain
recaptcha
smtp_profile
customer_emails
```

Do not create a Customer Portal until these requirements are satisfied.

---

## Required: SMTP Profile

A Customer Portal requires an SMTP Profile.

The SMTP Profile is used to send portal-related emails, including:

- Customer account confirmation email
- Customer password reset email

The email `from` address in the portal email settings should match the email used in the SMTP Profile to avoid errors.

MCP should verify an SMTP Profile exists before attempting to create the portal.

---

## Required: DNS-Ready Tracking Domain With Active SSL

A Customer Portal requires a tracking domain.

The `tracking_domain` field is a required 20-character tracking domain ID.

The tracking domain must already be:

- Created
- DNS ready
- Properly configured with required DNS records
- SSL initialized
- SSL active
- Appropriate for customer-facing portal use

The operation schema states:

```text
Make sure the tracking domain is set up and has an active SSL certificate before using it in the portal.
```

A Customer Portal is customer-facing, so the domain must be secure and ready before the portal is created or enabled.

Conceptual domain readiness flow:

```text
Create tracking domain
  ↓
Configure DNS records
  ↓
Initialize DNS
  ↓
Initialize SSL
  ↓
SSL becomes active
  ↓
Use tracking_domain ID in CreateCustomerPortal
```

If the tracking domain is not DNS ready or does not have active SSL, the portal may not work correctly for customers.

---

## Required: reCAPTCHA

A Customer Portal requires reCAPTCHA settings.

The operation expects reCAPTCHA v2 “I’m Not A Robot” keys for the domain associated with the tracking domain.

Required nested fields:

```text
recaptcha.site_key
recaptcha.secret_key
```

Purpose:

```text
Prevent bots from registering for or abusing the customer portal.
```

MCP should not invent reCAPTCHA keys. The user must supply valid keys for the correct domain.

---

## Required: Customer Emails

A Customer Portal requires customer emails for:

```text
customer_account_confirm_email
customer_account_password_reset
```

Both email objects are required.

Each email requires at least:

```text
from
```

Both email templates must include:

```handlebars
{{email_code}}
```

The customer needs this code to confirm registration or reset their password.

If `{{email_code}}` is missing, the customer may be unable to complete the portal flow.

---

# Top-Level Input Fields

| Field | Type | Required | Description |
|---|---:|---:|---|
| `name` | string | Yes | Unique Customer Portal name. |
| `description` | string | No | Description of what the portal is for. |
| `enabled` | boolean | No | Whether the Customer Portal is enabled. |
| `tracking_domain` | string | Yes | 20-character tracking domain ID. Must be DNS ready with active SSL. |
| `recaptcha` | object | Yes | reCAPTCHA v2 “I’m Not A Robot” site and secret keys. |
| `display_name` | string | No | Customer-facing portal display name. If blank, portal name is used. |
| `footer_html` | string | No | Custom footer HTML for the portal. |
| `smtp_profile` | string | Yes | 20-character SMTP Profile ID used to send portal emails. |
| `customer_emails` | object | Yes | Account confirmation and password reset email settings. |
| `customer_filters` | object | No | Restricts which customers can access the portal. |
| `customer_permissions` | object | No | Controls what customers can do in the portal. |
| `create_non_existing_customer` | boolean | No | Whether non-existing customers can register. Recommended `false`. |
| `create_non_existing_customer_campaign` | string | Conditional | Campaign ID used when non-existing customer registration is enabled. |

The schema has:

```json
"additionalProperties": false
```

MCP must not send unknown fields.

---

# `name`

The `name` is the internal Customer Portal name.

Rules:

- Required.
- Must be unique from other Customer Portal names.
- Should clearly identify the portal purpose.

Good names:

```text
Main Customer Portal
Subscription Customer Portal
Payment Recovery Portal
WooCommerce Customer Portal
VIP Customer Portal
```

Poor names:

```text
Portal
Test
Customer
New Portal
```

A clear name matters because Customer Portals may be used in customer emails, AI workflows, support workflows, and operational setup.

---

# `description`

The `description` explains the purpose of the Customer Portal.

Recommended even if not required.

Good description:

```text
Customer self-service portal for existing subscription customers to update payment methods, manage contact information, and pay failed renewals or failed trial expirations.
```

A good description should explain:

- Who the portal is for
- What customers can do
- Whether it is tied to a specific brand, campaign, shop, or customer segment
- Whether it is used for payment recovery, subscriptions, trials, or account management

---

# `enabled`

`enabled` determines whether the Customer Portal is enabled.

Recommended behavior:

```text
Create disabled first when setup is still being reviewed.
Enable only after domain, SSL, SMTP, emails, reCAPTCHA, filters, permissions, and display are verified.
```

Example:

```json
"enabled": false
```

Use `true` only when the portal is ready for customers.

---

# `tracking_domain`

The `tracking_domain` field is required.

Type:

```text
string
```

Requirements:

- Must be a 20-character tracking domain ID.
- Tracking domain must already exist.
- Tracking domain must be DNS ready.
- Tracking domain must have an active SSL certificate.

Example:

```json
"tracking_domain": "XXXXXXXXXXXXXXXXXXXX"
```

Important:

```text
Do not use a tracking domain that is not fully DNS/SSL ready.
```

---

## Tracking Domain and iframe Embedding

The operation description notes that the Customer Portal can be embedded as an iframe on the merchant’s website when properly configured with the same associated tracking domain.

This means the tracking domain is important not only for routing but also for embedding the portal into the merchant’s customer-facing website.

Conceptual iframe use case:

```text
Merchant website
  ↓
Embedded Customer Portal iframe
  ↓
Customer logs in and manages approved actions
```

MCP should ensure the portal is configured for the same intended domain/tracking-domain relationship before suggesting iframe usage.

---

# `recaptcha`

The `recaptcha` object is required.

Shape:

```json
"recaptcha": {
  "site_key": "RECAPTCHA_SITE_KEY",
  "secret_key": "RECAPTCHA_SECRET_KEY"
}
```

Required fields:

| Field | Type | Required | Description |
|---|---:|---:|---|
| `site_key` | string | Yes | reCAPTCHA v2 “I’m Not A Robot” site key for the domain associated with the tracking domain. |
| `secret_key` | string | Yes | reCAPTCHA v2 “I’m Not A Robot” secret key for the domain associated with the tracking domain. |

Important:

- The keys must be valid for the portal domain.
- Do not invent keys.
- Do not use keys from another domain unless they are valid for the tracking domain.
- Use reCAPTCHA v2 “I’m Not A Robot.”

---

# `display_name`

`display_name` is the name shown to customers using the portal.

If blank, the portal `name` will be used.

Example:

```json
"display_name": "My Store Customer Portal"
```

Use a customer-friendly name.

Good display names:

```text
Acme Customer Portal
Manage Your Subscription
My Account Portal
Payment Update Portal
```

---

# `footer_html`

`footer_html` allows custom HTML in the Customer Portal footer.

Use cases:

- Support link
- Privacy policy link
- Terms link
- Contact instructions
- Brand footer
- Customer service message
- Portal usage note

Example:

```json
"footer_html": "<p>Need help? Contact support@example.com.</p>"
```

MCP should avoid overly complex or unsafe HTML. Keep footer HTML simple, clear, and customer-safe.

---

# `smtp_profile`

`smtp_profile` is required.

Type:

```text
string
```

Requirements:

- Must be a 20-character SMTP Profile ID.
- SMTP Profile must already exist.
- Used to send portal emails.

Example:

```json
"smtp_profile": "XXXXXXXXXXXXXXXXXXXX"
```

Important:

The `from` email addresses in `customer_emails` should match the email used in the SMTP Profile to avoid errors.

---

# `customer_emails`

`customer_emails` is required.

It contains two required email settings:

```text
customer_account_confirm_email
customer_account_password_reset
```

Shape:

```json
"customer_emails": {
  "customer_account_confirm_email": {},
  "customer_account_password_reset": {}
}
```

Each email object can include:

```text
to_cc
to_bcc
from
from_name
subject
html
```

The `from` field is required for each email object.

Both email HTML templates must include:

```handlebars
{{email_code}}
```

---

## `customer_account_confirm_email`

This email is sent to customers for account confirmation.

Required field:

```text
from
```

Optional fields:

```text
to_cc
to_bcc
from_name
subject
html
```

Purpose:

```text
Send the customer an email code to confirm portal registration.
```

The `html` must include:

```handlebars
{{email_code}}
```

Example:

```json
"customer_account_confirm_email": {
  "from": "support@example.com",
  "from_name": "Example Store",
  "subject": "Confirm your customer portal account",
  "html": "<p>Your confirmation code is: <strong>{{email_code}}</strong></p>"
}
```

---

## `customer_account_password_reset`

This email is sent to customers for password reset.

Required field:

```text
from
```

Optional fields:

```text
to_cc
to_bcc
from_name
subject
html
```

Purpose:

```text
Send the customer an email code to reset their portal password.
```

The `html` must include:

```handlebars
{{email_code}}
```

Example:

```json
"customer_account_password_reset": {
  "from": "support@example.com",
  "from_name": "Example Store",
  "subject": "Reset your customer portal password",
  "html": "<p>Your password reset code is: <strong>{{email_code}}</strong></p>"
}
```

---

## Email CC and BCC

Each email type can include:

```text
to_cc
to_bcc
```

Both are arrays of email addresses.

Example:

```json
"to_bcc": [
  "archive@example.com"
]
```

Use carefully. Customer portal confirmation and password reset emails are sensitive account-access emails.

---

# Critical Email Requirement: `{{email_code}}`

Both email templates must include:

```handlebars
{{email_code}}
```

Required in:

```text
customer_account_confirm_email.html
customer_account_password_reset.html
```

Why:

- The customer needs the code to confirm portal registration.
- The customer needs the code to reset password.

MCP validation should fail if either email template is missing `{{email_code}}`.

---

# `customer_filters`

`customer_filters` determines which customers can access the portal. These filters also allow a RevCent account to create multiple Customer Portals for different brands, websites, campaigns, stores, or customer purchase origins.

If no filters are set, all customers can access the portal.

Shape:

```json
"customer_filters": {
  "campaign": [],
  "third_party_shop": []
}
```

Available filters:

| Field | Type | Meaning |
|---|---:|---|
| `campaign` | array<string> | Customers associated with at least one listed campaign can access the portal. |
| `third_party_shop` | array<string> | Customers associated with at least one listed third-party shop can access the portal. |

Each ID must be 20 characters.

---

## `customer_filters.campaign`

Type:

```text
array<string>
```

Each item is a 20-character campaign ID.

Logic:

```text
Customer associated with campaign A OR campaign B OR campaign C can access.
```

If empty:

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

then campaign association is not required.

Use cases:

- Campaign-specific portal
- Brand-specific portal
- Offer-specific portal
- Website-specific portal
- Funnel-specific portal
- Customer segment based on campaign

---

## `customer_filters.third_party_shop`

Type:

```text
array<string>
```

Each item is a 20-character user shop ID.

Logic:

```text
Customer associated with shop A OR shop B OR shop C can access.
```

If empty:

```json
"third_party_shop": []
```

then third-party shop association is not required.

Use cases:

- WooCommerce-specific portal
- Shopify/store-specific portal
- Store-specific portal
- Website-specific portal
- Brand-specific portal
- Multi-shop customer access control

---

---

# Multiple Portals Using Campaign and Shop Filters

Campaign and third-party shop filters are not only access-control settings.

They make it possible to create multiple Customer Portals for different brands, websites, stores, campaigns, or customer origins within the same RevCent account.

This is important for accounts that manage multiple ecommerce businesses, brands, shops, or websites.

Examples:

```text
Brand A Customer Portal
Brand B Customer Portal
WooCommerce Store Portal
Shopify Store Portal
Campaign-Specific Subscription Portal
Payment Recovery Portal for Website A
```

Each portal can have its own:

- Name
- Display name
- Description
- Footer HTML
- SMTP email copy
- Customer permissions
- Customer filters
- Embedded iframe placement
- Customer-facing support links
- Payment recovery strategy
- Subscription/trial self-service strategy

This allows customers to see a portal experience that matches the brand, website, or store where they purchased or originated.

---

## Campaign Filters as Portal Segmentation

Use `customer_filters.campaign` when portal access should be limited to customers associated with one or more campaigns.

This is useful when campaigns represent:

- Brands
- Websites
- Offers
- Funnels
- Product lines
- Customer acquisition sources
- Affiliate or partner campaigns

Example:

```json
"customer_filters": {
  "campaign": [
    "BRAND_A_CAMPAIGN_ID"
  ],
  "third_party_shop": []
}
```

Meaning:

```text
Only customers associated with Brand A campaign can access this portal.
```

Use cases:

```text
Brand A customers receive Brand A portal.
Brand B customers receive Brand B portal.
Subscription campaign customers receive subscription-specific portal.
Payment recovery campaign customers receive payment-update-focused portal.
```

---

## Third-Party Shop Filters as Portal Segmentation

Use `customer_filters.third_party_shop` when portal access should be limited to customers associated with one or more third-party shops.

This is useful when RevCent is connected to multiple ecommerce stores or websites.

Example:

```json
"customer_filters": {
  "campaign": [],
  "third_party_shop": [
    "STORE_A_SHOP_ID"
  ]
}
```

Meaning:

```text
Only customers associated with Store A can access this portal.
```

Use cases:

```text
WooCommerce Store A customers receive Store A portal.
Shopify Store B customers receive Store B portal.
Different websites receive different portal branding and permissions.
Different brands share one RevCent account but have separate customer-facing portals.
```

---

## Multiple Portal Strategy

For multi-brand or multi-store accounts, MCP should consider whether the user needs one global portal or multiple filtered portals.

Single portal strategy:

```text
One portal
No campaign/shop filters
All customers can access
```

Good for:

```text
Single brand
Single website
Single customer experience
```

Multiple portal strategy:

```text
Portal A filtered by Campaign A or Shop A
Portal B filtered by Campaign B or Shop B
Portal C filtered by Campaign C or Shop C
```

Good for:

```text
Multiple brands
Multiple websites
Multiple third-party shops
Different subscription policies
Different support links
Different customer-facing branding
Different payment recovery flows
```

---

## MCP Guidance for Brand/Website-Specific Portals

Before creating a Customer Portal, MCP should determine:

1. Is this portal for all customers or only customers from a specific brand, website, campaign, or shop?
2. Does the RevCent account contain customers from multiple brands or websites?
3. Should campaign filters be used?
4. Should third-party shop filters be used?
5. Should separate portals be created for each brand or store?
6. Should each portal have different display names, footers, permissions, or email copy?
7. Should the portal be embedded on the same website/domain where the customer purchased?
8. Should portal permissions differ by brand, shop, or customer origin?

Important:

```text
If no customer_filters are set, all customers can access the portal.
```

For multi-brand or multi-shop RevCent accounts, no filters may create a generic portal experience that is not ideal for all customers.

---

## Example: Brand A Portal

```json
{
  "name": "Brand A Customer Portal",
  "description": "Customer self-service portal for Brand A customers only.",
  "enabled": false,
  "tracking_domain": "XXXXXXXXXXXXXXXXXXXX",
  "recaptcha": {
    "site_key": "RECAPTCHA_SITE_KEY",
    "secret_key": "RECAPTCHA_SECRET_KEY"
  },
  "display_name": "Brand A Customer Portal",
  "smtp_profile": "YYYYYYYYYYYYYYYYYYYY",
  "customer_emails": {
    "customer_account_confirm_email": {
      "from": "support@brand-a.example",
      "from_name": "Brand A",
      "subject": "Confirm your Brand A portal account",
      "html": "<p>Your confirmation code is: <strong>{{email_code}}</strong></p>"
    },
    "customer_account_password_reset": {
      "from": "support@brand-a.example",
      "from_name": "Brand A",
      "subject": "Reset your Brand A portal password",
      "html": "<p>Your password reset code is: <strong>{{email_code}}</strong></p>"
    }
  },
  "customer_filters": {
    "campaign": [
      "BRAND_A_CAMPAIGN_ID"
    ],
    "third_party_shop": []
  },
  "customer_permissions": {
    "contact_modify": true,
    "credit_card_add": true,
    "credit_card_remove": true,
    "credit_card_set_default": true,
    "shipping_modify_ship_to": true,
    "subscription_renew": true,
    "subscription_activate": true,
    "subscription_suspend": false,
    "subscription_cancel": false,
    "trial_expire": false,
    "trial_cancel": false,
    "salvage_transaction_process": true
  },
  "create_non_existing_customer": false
}
```

---

## Example: Store-Specific Portal

```json
{
  "name": "Store A Customer Portal",
  "description": "Customer self-service portal for customers who purchased through Store A.",
  "enabled": false,
  "tracking_domain": "XXXXXXXXXXXXXXXXXXXX",
  "recaptcha": {
    "site_key": "RECAPTCHA_SITE_KEY",
    "secret_key": "RECAPTCHA_SECRET_KEY"
  },
  "display_name": "Store A Account Portal",
  "smtp_profile": "YYYYYYYYYYYYYYYYYYYY",
  "customer_emails": {
    "customer_account_confirm_email": {
      "from": "support@store-a.example",
      "from_name": "Store A",
      "subject": "Confirm your Store A portal account",
      "html": "<p>Your confirmation code is: <strong>{{email_code}}</strong></p>"
    },
    "customer_account_password_reset": {
      "from": "support@store-a.example",
      "from_name": "Store A",
      "subject": "Reset your Store A portal password",
      "html": "<p>Your password reset code is: <strong>{{email_code}}</strong></p>"
    }
  },
  "customer_filters": {
    "campaign": [],
    "third_party_shop": [
      "STORE_A_SHOP_ID"
    ]
  },
  "customer_permissions": {
    "contact_modify": true,
    "credit_card_add": true,
    "credit_card_remove": true,
    "credit_card_set_default": true,
    "shipping_modify_ship_to": true,
    "subscription_renew": true,
    "subscription_activate": true,
    "subscription_suspend": false,
    "subscription_cancel": false,
    "trial_expire": false,
    "trial_cancel": false,
    "salvage_transaction_process": true
  },
  "create_non_existing_customer": false
}
```


# `customer_permissions`

`customer_permissions` determines what customers can do in the portal.

Only enable permissions that should actually be available to customers.

If a permission is not desired, set it to `false` or omit it according to the intended API behavior.

Recommended best practice:

```text
Be explicit and set each relevant permission to true or false.
```

This avoids ambiguity.

---

## Permission Summary

| Permission | Customer-facing meaning |
|---|---|
| `contact_modify` | Customer can modify contact information. |
| `credit_card_add` | Customer can add a payment card. |
| `credit_card_remove` | Customer can remove a payment card. |
| `credit_card_set_default` | Customer can set a default payment card. |
| `shipping_modify_ship_to` | Customer can modify shipping information. |
| `subscription_renew` | Customer can renew subscriptions. |
| `subscription_activate` | Customer can re-activate subscriptions. |
| `subscription_suspend` | Customer can suspend subscriptions. |
| `subscription_cancel` | Customer can cancel subscriptions. |
| `trial_expire` | Customer can expire trials. |
| `trial_cancel` | Customer can cancel trials. |
| `salvage_transaction_process` | Customer can pay failed renewals or failed trial expirations through the portal. |

---

## `contact_modify`

Allows customers to modify contact information in the portal.

Useful for:

- Updating email
- Updating phone
- Updating name/contact details
- Keeping customer records current

Example:

```json
"contact_modify": true
```

---

## `credit_card_add`

Allows customers to add credit cards/payment cards through the portal.

Useful for:

- Failed payment recovery
- Card replacement
- Subscription renewal continuity
- Trial expiration billing
- Payment method updates

Example:

```json
"credit_card_add": true
```

---

## `credit_card_remove`

Allows customers to remove credit cards/payment cards through the portal.

Useful for:

- Customer payment method self-service
- Removing outdated cards
- Cleaning up stored payment methods

Example:

```json
"credit_card_remove": true
```

---

## `credit_card_set_default`

Allows customers to set a default credit card/payment card.

Useful for:

- Subscription renewals
- Trial expiration billing
- Failed renewal recovery
- Future billing predictability

Example:

```json
"credit_card_set_default": true
```

---

## `shipping_modify_ship_to`

Allows customers to modify shipping information.

Useful for:

- Address correction
- Fulfillment accuracy
- Reducing shipping-related support tickets
- Preventing delivery issues

Example:

```json
"shipping_modify_ship_to": true
```

---

## `subscription_renew`

Allows customers to renew subscriptions.

Useful for:

- Subscription self-service
- Recurring revenue retention
- Customer-driven renewal management

Example:

```json
"subscription_renew": true
```

---

## `subscription_activate`

Allows customers to re-activate subscriptions.

Useful for:

- Retention workflows
- Subscription recovery
- Customer self-service reactivation

Example:

```json
"subscription_activate": true
```

---

## `subscription_suspend`

Allows customers to suspend subscriptions.

Useful for businesses that prefer a pause option instead of immediate cancellation.

Example:

```json
"subscription_suspend": true
```

---

## `subscription_cancel`

Allows customers to cancel subscriptions.

Enable only if the business wants customers to cancel subscriptions directly through the portal.

If the business wants cancellation to require support, retention review, or AI Voice Agent save workflow, keep this false.

Example:

```json
"subscription_cancel": false
```

---

## `trial_expire`

Allows customers to expire trials.

Enable only if customers should be able to take this action themselves.

Example:

```json
"trial_expire": true
```

---

## `trial_cancel`

Allows customers to cancel trials.

Enable only if customers should be able to cancel trials directly.

Example:

```json
"trial_cancel": true
```

---

## `salvage_transaction_process`

This field is a RevCent system term.

Customer-facing meaning:

```text
Customer can pay failed renewals or failed trial expirations through the portal.
```

Use cases:

- Failed renewal payment recovery
- Failed trial expiration recovery
- Customer self-service payment resolution
- Revenue recovery without manual support intervention

Example:

```json
"salvage_transaction_process": true
```

Important:

Do not describe this to end customers as “process salvage transaction.” That is a system term. Use customer-friendly wording such as:

```text
Pay failed renewal
Resolve failed trial expiration
Complete overdue payment
Update payment and retry billing
```

---

# `create_non_existing_customer`

`create_non_existing_customer` determines whether non-existing customers can register for the portal.

Type:

```text
boolean
```

Schema recommendation:

```text
Recommended set to false.
```

Recommended default:

```json
"create_non_existing_customer": false
```

Most Customer Portals should be for existing customers only.

Enable only if the business intentionally wants non-existing customers to register through the portal.

---

# `create_non_existing_customer_campaign`

If `create_non_existing_customer` is true, this field determines the campaign ID assigned to non-existing customers who register through the portal.

Type:

```text
string
```

Requirements:

- 20-character campaign ID.
- Only relevant when `create_non_existing_customer` is true.

Example:

```json
"create_non_existing_customer": true,
"create_non_existing_customer_campaign": "XXXXXXXXXXXXXXXXXXXX"
```

Important:

If allowing non-existing customer registration, MCP should ensure the user intentionally selects the campaign for these new customers.

---

# Recommended MCP Preflight Checklist

Before calling `CreateCustomerPortal`, MCP should verify:

1. The user knows the portal purpose.
2. The portal name is unique.
3. A tracking domain exists.
4. The tracking domain is DNS ready.
5. The tracking domain has active SSL.
6. An SMTP Profile exists.
7. The SMTP Profile ID is known.
8. reCAPTCHA v2 site key exists for the portal domain.
9. reCAPTCHA v2 secret key exists for the portal domain.
10. Customer confirmation email is drafted.
11. Customer password reset email is drafted.
12. Both email templates include `{{email_code}}`.
13. Sender email matches or is compatible with SMTP Profile.
14. Customer filters are intentional.
15. Customer permissions are intentional.
16. `subscription_cancel` is true only if customers should self-cancel.
17. `salvage_transaction_process` is true only if customers should pay failed renewals/failed trial expirations.
18. `create_non_existing_customer` is false unless intentionally needed.
19. If non-existing registration is true, a campaign ID is supplied.
20. The portal should probably start disabled until reviewed.

---

# Recommended Default Strategy

For most customer portals:

```json
"enabled": false
```

during creation.

Why:

- DNS/SSL should be verified.
- Emails should be reviewed.
- Permissions should be reviewed.
- Portal display should be reviewed.
- iframe embedding should be tested if used.
- Customer access filters should be verified.

Enable the portal after configuration has been reviewed.

---

# Full Example: Basic Existing-Customer Portal

```json
{
  "name": "Main Customer Portal",
  "description": "Customer self-service portal for existing customers to manage contact details, payment methods, and subscription recovery actions.",
  "enabled": false,
  "tracking_domain": "XXXXXXXXXXXXXXXXXXXX",
  "recaptcha": {
    "site_key": "RECAPTCHA_SITE_KEY",
    "secret_key": "RECAPTCHA_SECRET_KEY"
  },
  "display_name": "Customer Portal",
  "footer_html": "<p>Need help? Contact support@example.com.</p>",
  "smtp_profile": "YYYYYYYYYYYYYYYYYYYY",
  "customer_emails": {
    "customer_account_confirm_email": {
      "from": "support@example.com",
      "from_name": "Example Store",
      "subject": "Confirm your customer portal account",
      "html": "<p>Your confirmation code is: <strong>{{email_code}}</strong></p>"
    },
    "customer_account_password_reset": {
      "from": "support@example.com",
      "from_name": "Example Store",
      "subject": "Reset your customer portal password",
      "html": "<p>Your password reset code is: <strong>{{email_code}}</strong></p>"
    }
  },
  "customer_filters": {
    "campaign": [],
    "third_party_shop": []
  },
  "customer_permissions": {
    "contact_modify": true,
    "credit_card_add": true,
    "credit_card_remove": true,
    "credit_card_set_default": true,
    "shipping_modify_ship_to": true,
    "subscription_renew": true,
    "subscription_activate": true,
    "subscription_suspend": false,
    "subscription_cancel": false,
    "trial_expire": false,
    "trial_cancel": false,
    "salvage_transaction_process": true
  },
  "create_non_existing_customer": false
}
```

---

# Full Example: Payment Recovery Portal

This portal is focused on payment method updates and failed renewal/failed trial expiration recovery.

```json
{
  "name": "Payment Recovery Portal",
  "description": "Customer self-service portal for updating payment methods and paying failed renewals or failed trial expirations.",
  "enabled": false,
  "tracking_domain": "XXXXXXXXXXXXXXXXXXXX",
  "recaptcha": {
    "site_key": "RECAPTCHA_SITE_KEY",
    "secret_key": "RECAPTCHA_SECRET_KEY"
  },
  "display_name": "Update Payment",
  "footer_html": "<p>Need help resolving your payment? Contact support@example.com.</p>",
  "smtp_profile": "YYYYYYYYYYYYYYYYYYYY",
  "customer_emails": {
    "customer_account_confirm_email": {
      "from": "support@example.com",
      "from_name": "Example Store",
      "subject": "Confirm your payment portal account",
      "html": "<p>Your confirmation code is: <strong>{{email_code}}</strong></p>"
    },
    "customer_account_password_reset": {
      "from": "support@example.com",
      "from_name": "Example Store",
      "subject": "Reset your payment portal password",
      "html": "<p>Your password reset code is: <strong>{{email_code}}</strong></p>"
    }
  },
  "customer_permissions": {
    "contact_modify": false,
    "credit_card_add": true,
    "credit_card_remove": false,
    "credit_card_set_default": true,
    "shipping_modify_ship_to": false,
    "subscription_renew": true,
    "subscription_activate": true,
    "subscription_suspend": false,
    "subscription_cancel": false,
    "trial_expire": false,
    "trial_cancel": false,
    "salvage_transaction_process": true
  },
  "create_non_existing_customer": false
}
```

---

# Full Example: Subscription Management Portal

```json
{
  "name": "Subscription Portal",
  "description": "Customer self-service portal for existing subscription customers to manage payment methods and allowed subscription actions.",
  "enabled": false,
  "tracking_domain": "XXXXXXXXXXXXXXXXXXXX",
  "recaptcha": {
    "site_key": "RECAPTCHA_SITE_KEY",
    "secret_key": "RECAPTCHA_SECRET_KEY"
  },
  "display_name": "Manage Subscription",
  "footer_html": "<p>Questions about your subscription? Contact support@example.com.</p>",
  "smtp_profile": "YYYYYYYYYYYYYYYYYYYY",
  "customer_emails": {
    "customer_account_confirm_email": {
      "from": "support@example.com",
      "from_name": "Example Store",
      "subject": "Confirm your subscription portal account",
      "html": "<p>Your confirmation code is: <strong>{{email_code}}</strong></p>"
    },
    "customer_account_password_reset": {
      "from": "support@example.com",
      "from_name": "Example Store",
      "subject": "Reset your subscription portal password",
      "html": "<p>Your password reset code is: <strong>{{email_code}}</strong></p>"
    }
  },
  "customer_permissions": {
    "contact_modify": true,
    "credit_card_add": true,
    "credit_card_remove": true,
    "credit_card_set_default": true,
    "shipping_modify_ship_to": true,
    "subscription_renew": true,
    "subscription_activate": true,
    "subscription_suspend": true,
    "subscription_cancel": false,
    "trial_expire": false,
    "trial_cancel": false,
    "salvage_transaction_process": true
  },
  "create_non_existing_customer": false
}
```

---

# Output Schema

Successful response:

```json
{
  "api_call_id": "XXXXXXXXXXXXXXXXXXXX",
  "api_call_unix": 1740000000,
  "code": 1,
  "customer_portal_id": "YYYYYYYYYYYYYYYYYYYY",
  "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_portal_id` | 20-character Customer Portal ID created by the operation. |
| `result` | Human-readable result message. |

---

# Common Mistakes

## Mistake: Creating Portal Before Domain Is Ready

Wrong:

```text
Create Customer Portal using a tracking domain that does not have active SSL.
```

Correct:

```text
Wait until the tracking domain is DNS ready and SSL active.
```

---

## Mistake: Missing `{{email_code}}`

Wrong:

```html
<p>Thanks for registering.</p>
```

Correct:

```html
<p>Your confirmation code is {{email_code}}</p>
```

Both confirmation and password reset email templates need `{{email_code}}`.

---

## Mistake: Enabling Too Many Permissions

Wrong:

```text
Enable every permission because more features seem better.
```

Correct:

```text
Only enable the actions customers should actually be allowed to perform.
```

---

## Mistake: Enabling Subscription Cancellation Accidentally

If the business does not want customers to self-cancel subscriptions, keep:

```json
"subscription_cancel": false
```

---

## Mistake: Misunderstanding `salvage_transaction_process`

Wrong customer-facing explanation:

```text
Customer can process a salvage transaction.
```

Correct customer-facing explanation:

```text
Customer can pay failed renewals or failed trial expirations through the portal.
```

---

## Mistake: Allowing Non-Existing Customers Without Intent

Recommended default:

```json
"create_non_existing_customer": false
```

Only enable if the business intentionally wants non-existing customers to register.

---

## Mistake: Using a Sender That Does Not Match SMTP Profile

The portal email `from` address should match the SMTP Profile email to avoid errors.

---

# MCP Validation Checklist

Before submitting `CreateCustomerPortal`:

1. `name` is present and unique.
2. `tracking_domain` is present and 20 characters.
3. Tracking domain is DNS ready.
4. Tracking domain SSL is active.
5. `smtp_profile` is present and 20 characters.
6. reCAPTCHA object is present.
7. `recaptcha.site_key` is present.
8. `recaptcha.secret_key` is present.
9. `customer_emails.customer_account_confirm_email` is present.
10. `customer_emails.customer_account_password_reset` is present.
11. Both email objects include `from`.
12. Confirmation email HTML includes `{{email_code}}`.
13. Password reset email HTML includes `{{email_code}}`.
14. Sender email matches or is compatible with SMTP Profile.
15. Customer permissions are intentionally selected.
16. `subscription_cancel` is enabled only if direct customer cancellation is desired.
17. `salvage_transaction_process` is enabled only if customers should pay failed renewals or failed trial expirations.
18. Customer filters are intentionally empty or contain valid 20-character IDs.
19. For multi-brand or multi-shop accounts, campaign/shop filters have been considered so customers see the portal for the brand, website, or shop where they purchased/originated.
20. `create_non_existing_customer` is false unless intentionally needed.
21. If `create_non_existing_customer` is true, `create_non_existing_customer_campaign` is present and 20 characters.
22. Portal starts disabled unless the setup has already been reviewed.
23. Display name and footer HTML are customer-safe.
24. No unknown fields are included.

---

# Quick Reference

Required minimum structure:

```json
{
  "name": "Customer Portal Name",
  "tracking_domain": "XXXXXXXXXXXXXXXXXXXX",
  "recaptcha": {
    "site_key": "RECAPTCHA_SITE_KEY",
    "secret_key": "RECAPTCHA_SECRET_KEY"
  },
  "smtp_profile": "YYYYYYYYYYYYYYYYYYYY",
  "customer_emails": {
    "customer_account_confirm_email": {
      "from": "support@example.com",
      "html": "<p>Your confirmation code is {{email_code}}</p>"
    },
    "customer_account_password_reset": {
      "from": "support@example.com",
      "html": "<p>Your password reset code is {{email_code}}</p>"
    }
  }
}
```

Most important MCP rules:

```text
Do not create a Customer Portal before the tracking domain is DNS ready and SSL active.
An SMTP Profile is required.
reCAPTCHA v2 site and secret keys are required.
Both customer emails must include {{email_code}}.
Only enable customer permissions intentionally.
Use campaign/shop filters when creating separate portals for different brands, websites, stores, or customer purchase origins.
salvage_transaction_process means customers can pay failed renewals or failed trial expirations.
create_non_existing_customer should usually be false.
Create disabled first unless the portal is already fully reviewed.
```

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