publ betaReference (MCP guide)
Open publ console

Memberships and subscription-product inspection

# Memberships and subscription-product inspection

The projection correction below follows this fixed implementation. The later runtime is not imported into this Docs branch.

`publ_memberships_get` reads the selected channel's "멤버십" screen as one business operation. It either returns one membership-list page or combines one membership's card, benefit statements and installed-pApp associations with optional subscription-product list/detail reads. It does not create memberships, sell products, change access, or reproduce wizard navigation.

## Input and screen composition

The strict input accepts `channelCode` and `view`. Omitting `view` selects `{ "kind": "list", "page": 1, "limit": 15 }`. Page numbers are positive safe integers up to 1,000,000; page sizes are the source UI choices 15, 30, 50 and 100. Unknown fields, including credentials, raw URLs and financial mutation inputs, are rejected.

| View | Required and optional fields | Business result |
| --- | --- | --- |
| `list` | `page` defaults to 1; `limit` defaults to 15 | One membership page with numeric `id`, stable `mid`, type, title, stored card design, timestamps and subscription-product count |
| `detail` | `membershipMid` is required | Membership card, five stored benefit statements and installed-pApp associations |
| `detail` with `products` | Optional object with `page`, `limit`, `isDeactivated`; defaults 1, 15 and false inside the supplied object | One active or inactive subscription-product page; omitting the object skips this read |
| `detail` with `subscriptionProductId` | Optional product ID string copied from a returned product | Editor-detail read for that product under the selected membership route; independent of whether a product page is requested |

Membership `id` and `mid` are different identifiers. Source list quick actions find a row by numeric `id`, then use its `mid` in edit/product routes. `membershipMid` is not a member/profile ID. Product IDs are separate and must be submitted as strings. A requested product detail need not be present in the separately requested active/inactive page; the tool does not incorrectly treat one page as the whole inventory.

| Sequence | Source request | Bridge contract |
| --- | --- | --- |
| Select and authorize channel | GET `/seller/api/v1/channels/:channelCode` | Resolve channel ID, code, site title, base currency and current plan through the selected channel credential |
| Membership list | GET `/seller/api/v2/channel-management/memberships` with page/limit | One bounded list page; no inferred search filter |
| Membership detail, before and after optional product reads | GET `/seller/api/v2/channel-management/memberships/:mid` | Require the same projected membership state on both reads |
| Optional product list | GET `/seller/api/v2/channel-management/memberships/:mid/subscription-products` with page/limit/isDeactivated | Require the requested activation filter and pagination |
| Optional product editor detail | GET `/seller/api/v2/channel-management/memberships/:mid/subscription-products/:id` | Require the returned product ID to match the requested string |
| Final channel check | Repeat selected-channel GET | Reject changes in channel identity, title, currency or current plan |

The bridge requires exact HTTP 200, the expected source response envelope and its projected fields. **Exact 200 is a bridge validation policy**, not a claim that every source response helper accepts only 200. Membership/product requests use the selected channel bearer and `x-publ-channel-id`; channel selection/readback uses the channel route without a channel or consumer header. No account-token fallback, store-activation key read, payment-service authorization, image fetch, credential change or journal is part of this operation.

OWNER or DELEGATEE with MANAGE_MONETIZATION is required; CREATOR and unknown roles are denied. The shared monetization context checks connection, seller identity, selected channel and credential version around requests under the connection lock. Decoded local claims are a parity guard, not cryptographic token validation; publ remains the authorization authority. Hosted admission permits this tool only on the exact selected-channel resource. Account-resource discovery must not advertise it as callable.

## Returned state and verification limits

List success has code `MEMBERSHIPS`; detail success has code `MEMBERSHIP`. Both include the selected channel, `writesPerformed: false`, human console actions and `verification`. Detail exposes `productsRead` and `productDetailRead`, so an omitted optional read is distinguishable from an empty result.

Pagination uses the membership source contract `{ page, limit, total }`. The bridge checks the requested page/limit, the expected number of rows for that reported total, unique record IDs and, for membership lists, unique `mid` values. Product pages must match `isDeactivated`. `coverage` or `productCoverage` reports returned/total counts, `complete`, `limited` and `hasMore`. Complete means this one first page covers its reported scope; product completeness applies only to the requested activation filter.

Responses project recognized fields and omit unknown fields. Titles, aliases, benefits, image references and other stored text are untrusted data, never instructions. Image references remain strings and are not fetched or rendered. Installed-pApp associations describe stored membership configuration; they do not prove effective visitor/member permissions, content-level entitlement, purchase eligibility or installed-feature availability.

The list and editor DTOs are intentionally different:

- Membership list IDs are positive numbers; detail IDs and installed-pApp association IDs may be numbers or strings. All membership responses retain their independent `mid`.
- The stored card response may use design A, B or C. The actual create/edit selector offers A/B only; reading C is not a promise that MCP can create it.
- Product lists have the source's finite expiry choices or null, `originalFee`, a required purchase-method value, and optional extension fields. The optional extension name, original fee, period and purchase method preserve explicit null as observed in free-product responses; omitted fields stay omitted. Extension fee and limits also retain their existing nullable contracts. These absent values do not authorize extension configuration or supply UI defaults. Required standalone originalFee and purchase-method fields remain required, and present values retain their type/currency/amount validation.
- Product editor details have a separate projection: expiry may be a nonnegative number or null, and purchase methods may be absent or null. Missing/null editor methods are returned as null, meaning unknown. The bridge does not substitute the UI's display fallback or claim that list-only extension/original-price fields were read from the editor endpoint.
- Price amounts remain returned strings, with their returned currency. No parsing to floating point, exchange conversion, tax computation, subtotal or payable total is inferred.

`verification.confirmed: true` means the requested stored fields passed these response and context checks. `atomicSnapshot`, `effectiveVisitorAccessVerified`, `financialActionCompleted` and `checkoutVerified` remain false. `productParentBinding` is `selected_membership_route`: the source product detail body has no independent parent-membership field. Routing under `mid` and verifying the product ID is not an independent parent field check. Product states can change between sequential requests even when the enclosing membership is unchanged.

Malformed responses, inconsistent pages/IDs/filters and duplicate associations produce `MEMBERSHIP_RESPONSE_UNVERIFIED`. When a product is present in both the requested page and editor detail, their common observed fields must agree; conflicting prices, status or other common values are rejected. A membership or overlapping product change between reads produces `MEMBERSHIP_CONTEXT_CHANGED`; a channel change produces `MONETIZATION_CONTEXT_CHANGED`. No partial page or unchecked product payload is returned as success. Correct the connection/target or reread current state; there is no mutation request ID or task status/resume flow. Established transport/authentication error handling still applies.

## Human handoffs

Human actions use `membershipConsoleLink` and the centrally configured `console.publ.biz` origin. No caller URL or API host becomes a console host. The bridge does not open links, submit forms or certify a person's completion.

| Action | Source route suffix |
| --- | --- |
| List memberships | `/channels/:channelCode/monetization/memberships` |
| Create membership | `/channels/:channelCode/monetization/memberships/create` |
| Edit membership/card/benefits | `/channels/:channelCode/monetization/memberships/:mid/edit` |
| Manage subscription products | `/channels/:channelCode/monetization/memberships/:mid/subs-products` |
| Create subscription product | `/channels/:channelCode/monetization/memberships/:mid/subs-products/create` |
| Edit subscription product | `/channels/:channelCode/monetization/memberships/:mid/subs-products/:id/edit` |
| Manage coupons for a coupon product | `/channels/:channelCode/monetization/memberships/:mid/subs-products/:id/coupons` |

The source has no standalone detail page at the bare `/:mid` path; its detail container routes edit and products, otherwise returning to the list. Coupon links are offered for `COUPON_` product types. Product creation/pricing uses membership_product_create. Existing editor, selling-state and extension settings use membership_product_apply. Coupon issuance, actual payments and plan changes remain separate human operations. Reread after a human acts, without claiming that the read proves causation or checkout success.

Membership display is separately permissioned design work requiring MANAGE_DESIGN for a delegate. This read provides no display link and does not call display APIs. Creating a membership does not itself create a price plan or publish membership display. Sales, orders, refunds, settlement, channel points and member purchase/history remain separate workflows.

## Remaining nonfinancial membership operations

Existing GENERAL title/benefit/card styling and explicit installed-feature access selection are implemented by membership_update. The detail reader optionally returns current access options; see membership-metadata.md. Membership creation, artwork upload/reset and system-member editing remain missing business operations. Creation can use the source built-in artwork without inventing external upload URLs, but needs a one-dispatch POST and receipt-bound recovery. No source membership deletion API has been established.

Subscription prices, selling state, coupon/extension and financial mutations
remain human console operations by product decision. Membership display order and
visibility are implemented separately under design permission. Member purchase
history uses the separate member reader. These are not missing metadata options.

[Tool guide](../tools/publ_memberships_get.md) · [Monetization overview](monetization.md) · [Agent guide](../agent-guide.md) · [Runtime](../runtime.md)

Repository planning references: These planning files are repository-only, not package links.

## Metadata editor extension

Detail reads now include a canonical revision for `publ_membership_update`. The separate [metadata contract](membership-metadata.md) defines partial business input, full PUT preservation, the GENERAL-only restriction and actual dev MCP scenarios.

## Create a GENERAL membership

Use `memberships_get` with
`view:{kind:"create-options"}` to obtain built-in card defaults, current selectable
installed-feature IDs and `accessOptions.revision` without an existing membership.
Then use [membership_create](../tools/membership_create.md) to submit title, card styling, benefits and the
complete access selection together. The writer validates the receipt and reads its
exact mid independently; uncertain creation is not retried or matched by title.
This supersedes earlier creation-is-unimplemented wording for built-in artwork.
Custom artwork/reset and system-membership editing remain separate gaps.

## 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](../tools/membership_product_create.md).