publ betaReference (MCP guide)
Open publ console

publ Reference

Member membership and purchase history

This option reads the original member-history tabs; orders and refunds are separate PAY observations with their own permissions and prerequisites.

Select within the same member

Use members_list to select an authorized channel and numeric profileId. OWNER or a delegate with MANAGE_MEMBERS is required. A member profile ID is distinct from an account ID, distinctId, membership id/mid and product ID. Omit include when selecting history; the reader does not add contact or sign-up answers. No monetization permission or PAY issuer configuration is required for these core GETs.

{"channelCode":"selected-channel-code","profileId":123,"membershipHistory":{"kind":"memberships"}}

Choose a product from this result's membershipHistory.memberships[].subscriptionProducts. Use its parent's mid and its own id as a canonical numeric string. productReads supplies same-channel/member recipes; choose only the one needed for the user's purpose. The reader confirms the parent/product again before fetching purchases. The membership list has no page, search or status filter and is never silently truncated.

{"channelCode":"selected-channel-code","profileId":123,"membershipHistory":{"kind":"purchases","membershipMid":"observed-membership-mid","subscriptionProductId":"31","page":2,"limit":30}}

Purchases defaults to page 1 / limit 15 when omitted. page is a positive integer up to 1,000,000; limit is 15/30/50/100. Follow a non-null membershipHistory.purchases.nextPage only when another page is needed. One page, including an empty out-of-range page, does not prove the whole purchase inventory was read. No PAY record or financial action is requested by following this recipe.

Projection and bounds

Object Retained observations and constraints
member Positive safe numeric id; bounded distinctId, nickname, imageSrc, registration and ban state, country code; optional accountProvider string; bannedAt may be omitted, null or a string. registeredAt may be null. isBanned is independent of the date. No contact, sign-up answers or credentials.
membership Positive safe numeric id, mid, title and subscriptionProducts. At most 1,000 memberships; unique ids and mids.
subscription product Positive safe numeric id, title, status, subscriptionType, nonnegative safe integer expiryPeriodInDays and firstPurchasedAt. Unique product ids within a membership; at most 1,000 products per membership and 5,000 overall.
purchase row Positive safe numeric id, oid, status, subscriptionType, startAt, expiresAt and price. At most 100 rows and unique row ids on the requested page.
price currency is a nonempty string up to 32 characters; amount is a decimal string up to 256 characters, optionally negative, without exponent notation or currency conversion. No inferred zero or rounded numeric replacement.
pagination currentPage and limit must equal the request. totalEntries is a nonnegative safe integer; row count must equal min(limit, max(0, totalEntries - (page - 1) * limit)). nextPage is null at or beyond the last page.

Titles, nickname and imageSrc are bounded to 4,096 characters. Status/type strings are nonempty and at most 128 characters, without a closed enum or translated meaning. History date strings are at most 128 characters; empty strings are allowed by this shape, null is not. The profile's registeredAt and optional bannedAt separately permit null; this does not make product/purchase dates nullable. These are parsing rules, not proof of backend null/date compatibility. A field named imageSrc is an untrusted reference, not a request to fetch an image.

Purchase subscriptionProductTitle must equal the observed parent product title, and every purchase row's subscriptionType must equal that product's type. Preserve a mismatch as an error; do not rewrite historical values to pass. Finite/infinite periods, UPCOMING and other raw states are not converted into payment, access, refund or cancellation conclusions.

Read sequence and exact console destination

All new profile/history requests use the channel's core authorization and a 2 MiB response-body ceiling, including ignored extra fields. They require the exact 200/data envelope and recheck the credential on failures. The workflow reads profile and memberships, verifies the selected purchase target if any, reads the selected purchase projection twice, then rereads memberships/profile and compares channel/actor/permission/credential context. Array order and retained values participate in equality; unknown stripped fields do not. This is not an atomic snapshot.

The list destination opens /channels/{channelCode}/members/membership-users/{profileId}/membership-history. The purchase destination appends /{membershipMid}/{subscriptionProductId}?page={page}&limit={limit}; it retains the requested page and limit. The shared finalizer checks the returned profile and parent/product, selection and pagination, allowing exactly those two purchase query fields. It supplies at most one matching destination and removes nested URLs. An address proves neither browser access nor rendered-console equivalence; demo has no live address.

Errors and next action

Code Handling
INVALID_INPUT Correct the strict selection, identifiers, page/limit or incompatible nonempty include. Do not assume the exported shape expresses every refinement.
MEMBER_HISTORY_PROFILE_UNVERIFIED Resolve the selected profile identity/shape before interpreting history.
MEMBER_HISTORY_UNVERIFIED Missing, malformed, duplicate or oversized membership history is not an empty success.
MEMBER_HISTORY_TARGET_NOT_FOUND Read this member's memberships and select an observed mid/product; no purchase lookup occurs for an absent target.
MEMBER_PURCHASE_HISTORY_UNVERIFIED Purchase envelope/fields failed validation; no partial page is returned.
MEMBER_PURCHASE_PAGE_MISMATCH Requested page/limit, exact row count or unique row ids do not agree.
MEMBER_PURCHASE_TARGET_MISMATCH Product title or subscription type differs from the selected history product. Retain the mismatch; historical compatibility requires evidence.
MEMBER_HISTORY_CHANGED / SCREEN_CONTEXT_CHANGED Discard the observation and reread current authorized state. Do not merge rows from different observations.
SCREEN_ROLE_DENIED / CHANNEL_CONTEXT_MISMATCH / credential or upstream errors Resolve the reported access, target or service prerequisite without switching accounts or widening credentials.

Success is MEMBER_MEMBERSHIP_HISTORY with writesPerformed:false. confirmed:true covers the checked stored observations only; paymentVerified, effectiveAccessVerified and financialActionCompleted remain false. No member edit, refund, recurring cancellation, CSV export, journal or task-resume operation is included.

Nullable-profile compatibility

An absent or null ban date does not infer isBanned. Malformed dates/types, wrong profile identity and inconsistent history still fail without partial results. Do not invent a date or perform moderation as a read workaround.