publ betaReference (MCP guide)
Open publ console

publ Reference

Membership product extension and selling state

It prepares one person's action in the original console and adds no financial writer or task.

Observe and retain the selected row

An OWNER or DELEGATEE with MANAGE_MONETIZATION must use the authorized channel. Select membershipMid from the membership's mid, then request an explicit products page/filter. Copy the selected product ID as a canonical positive safe-integer string. Product and numeric membership/member IDs are different. The selected product must occur on that requested page and agree with its editor detail. If it is absent, read the correct page yourself; no automatic traversal or alternate-target fallback occurs.

products uses page 1–1,000,000, limit 15/30/50/100 and boolean isDeactivated; defaults are 1/15/false. An explicit empty object is accepted and expands to those defaults. The source UI calls false “On sale” and true “Suspended”. Filtering describes one requested state, not all products. Raw URLs, financial amounts, durations, purchase methods, bulk IDs, request IDs and task IDs are not accepted inputs for these actions.

{"channelCode":"selected-channel-code","view":{"kind":"detail","membershipMid":"returned-membership-mid","products":{"page":3,"limit":15,"isDeactivated":false},"subscriptionProductId":"123","consoleAction":"manage-extension"}}

The ordinary combined product list/detail read may observe a selected product outside that page. These three consoleAction values deliberately require the selected row on it. They cannot combine with serialKeys. Those dependencies are runtime checks beyond the exported input shape.

Choose the source action

Keep the input products.isDeactivated equal to the selected row's observed current state. The pre-action console destination preserves that filter. The output selectedProductAction.requestedIsDeactivated describes the desired resulting state; it is not an input filter. The later requiredAction.nextRead uses that desired state after the person's action.

Action Current row and input filter Desired state and remaining human step
manage-extension Keep the observed row's products.isDeactivated value. Only COUPON_ONCE_FINITE, ONCE_FINITE or COUPON_FREE_FINITE are supported. There is no requested selling state. extensionFee:null means create mode, a price means edit mode. Find the row and open its extension quick action; nextRead keeps the current filter.
activate-product, when a transition is needed The inactive row is on products.isDeactivated:true (“Suspended”). requestedIsDeactivated:false means “On sale”. Select that inactive row and choose the source bulk control for “On sale”; the later nextRead uses isDeactivated:false.
deactivate-product, when a transition is needed The active row is on products.isDeactivated:false (“On sale”). requestedIsDeactivated:true means “Suspended”. Select that active row and choose the source bulk control for “Suspended”; the later nextRead uses isDeactivated:true.

Missing extensionFee is unknown, not the create-mode null. Optional extension names, original fees, periods and purchase-method fields retain their existing null/omission meaning; the MCP invents no settings or eligibility. Source monetization and ENTERPRISE_TRIAL restrictions are still checked by the console. No pricing, duration, sale-state or purchase change is submitted by the MCP.

Selling-state guidance may return alreadyMatches:true. For example, an activation request for an already active product still uses its observed products.isDeactivated:false page; do not switch to an inactive page or select another row. A deactivation request for an already inactive product similarly keeps true. These observations remain action_required / MEMBERSHIP_CONSOLE_REQUIRED with confirmed:false. The message states that no change was performed or inferred necessary. The transition rows above do not require an unnecessary action, and no observation is a successful write receipt.

Read sequence and output

The composition reads membership, requested product page and selected editor detail; checks the selected row and common values; reads the entire projected page again; rereads the selected detail; then checks membership, channel and credentials. Page equality includes projected rows, their order and pagination, not unknown fields stripped by the schemas. These sequential observations are not an atomic snapshot. Existing strict envelope, 2 MiB membership GET bound, auth and credential checks remain.

selectedProductAction identifies the action, numeric-string product ID and title, with sourceSurface:product_list, requiresManualSelection:true and eligibilityEvaluated:false. Extension mode or requestedIsDeactivated/alreadyMatches appears according to the action. The ordinary observed membership/product data remains available. No partial handoff is returned after a failed or changed observation.

The destination is /channels/{channelCode}/monetization/memberships/{membershipMid}/subs-products?page={page}&limit={limit}&isDeactivated={boolean}. The central wrapper requires productsRead:true and exactly those three query fields matching the observed page/filter; duplicate, unknown and mismatched fields are rejected. The URL selects no checkbox and opens no modal. The source extension modal is local component state, not a deep link.

Follow-up and failure handling

requiredAction.nextRead contains a memberships_get recipe without consoleAction. Extension keeps the current page/filter; selling-state follow-up starts at page 1 of the requested resulting state and retains the selected product ID. It does not guarantee that ID occurs on the first page, prove which actor changed it or establish that a purchase/extension was completed. A fresh read may fail or observe drift; do not infer success from the earlier destination.

Error Meaning
INVALID_INPUT Correct the explicit product page, canonical ID or incompatible serialKeys/action combination before another attempt.
MEMBERSHIP_PRODUCT_NOT_ON_PAGE Supply a newly observed page/filter containing that exact selected product; do not silently select another row.
MEMBERSHIP_EXTENSION_UNAVAILABLE The source quick action is unavailable for the observed product type.
MEMBERSHIP_EXTENSION_UNVERIFIED The list omitted extensionFee; creation/editing mode cannot be inferred.
MEMBERSHIP_CONTEXT_CHANGED / MONETIZATION_CONTEXT_CHANGED Discard the handoff and reread the authorized current state.
MEMBERSHIP_RESPONSE_UNVERIFIED / upstream or credential error Preserve a failed observation, not an empty page or financial action result.

Plain product pages retain their validated query, while an ordinary selected editor detail or coupon read keeps its own route. Current-page human-action recipes choose the opposite observed selling state and include extension only for a supported type with a known fee field. The read itself creates no task. Product creation uses membership_product_create, and existing edits/extension/selling state use membership_product_apply; serial-key issuance, withdrawal and redemption stay separate console work.

Direct selling-state configuration

A products read now returns productPageRevision. Copy it with the exact observed page/limit/isDeactivated and selected numeric row IDs; request false to start selling or true to suspend. The writer checks source plan/trial constraints, repeats preflight, sends only changed IDs once and independently reads every selected product. Sent/partial outcomes are never resent by resume. The original consoleAction handoffs remain optional human paths; earlier blanket “activation is console-only” wording is superseded for this action. Creation/pricing now uses membership_product_create; extension configuration uses membership_product_apply. Actual fund movement and service billing remain human-operated.

Existing product editor extension

From the same observed product page/revision, choose one subscriptionProductId and patch its trimmed alias or source-supported purchase methods. Only ordinary ONCE_FINITE / ONCE_INFINITE allow a purchase-method change; CASH_AND_CP requires fresh branding. The original title/base price/type/period remain locked and are preserved in one source PUT. Receipt and independent detail read must agree; task recovery never resends an uncertain PUT. The result links directly to the selected product editor. Creation uses membership_product_create; extension pricing uses membership_product_apply action.kind extension. Earlier edit-product consoleAction remains an optional human route, not a mandatory boundary.

Product extension configuration

Use membership_product_apply action.kind extension with one subscriptionProductId, complete settings and the observed sourcePage/productPageRevision. It configures source-supported extension availability, price, period, timing and purchase limits in one POST, then checks the exact product receipt plus independent detail/list readback. Base product fields and membership remain preserved. The exact product list page/filter link is retained; the extension modal itself has no deep link. This does not extend an actual member or charge funds. Earlier manage-extension handoffs remain optional human navigation, not a mandatory configuration boundary. Product creation now uses membership_product_create; source-locked existing base prices stay locked.

Compose a new membership product

Use membership_product_create with the current parent membership revision, title, alias and complete offer. It supports free, paid-once, recurring, coupon-paid and eligible coupon-free choices with source prices/periods and purchase restrictions. One POST, durable receipt ID and independent readback preserve the parent. taskType membership-product-create only observes on resume; no lost creation is repeated or adopted by title. There is no source product delete/reset; suspending selling retains the created record. New products inherit the parent's configured membership/access relationship; individual content connection remains a separate feature flow. See product creation.