{"ok":true,"version":"agent-action-contracts.v1","generatedAt":"2026-05-30T06:51:32.080Z","surface":{"id":"action-contracts","artistId":"laurel","safeForAgent":true,"browserAutomationRequired":false,"relatedIssues":[608,611,612,671,672,673,674,704,757,799,810,811,812,818,819,873,895,986,1078,1112,1113,1114,1192,1260,1282,1291,1292,1298,1299,1359,1546,1681,1692,1702,1710,1794,1795]},"communityMode":{"version":"fanful-community-mode.v1","contractDoc":"docs/platform/fanful-community-mode-contract.md","relatedIssues":[560,1075,1078],"source":"agent-action-contracts","selectedCommunity":{"id":"laurel","slug":"laurel-harned","name":"Laurel Harned","role":"first-default-community","isDefault":true,"artistSite":"https://docs.fanful.net/","rawDatabaseIdsRedacted":true},"activeMode":"fan","availableModes":[{"id":"fan","status":"available","summary":"Listen, watch, chat, support, buy, and participate as a fan of the selected community.","requiredAuthorization":"Public or signed-in listener context for private fan state."},{"id":"publisher","status":"authorization-required","summary":"Administer creator/community commerce, live rooms, messaging, moderation, and settings.","requiredAuthorization":"Server-confirmed creator/admin authorization for selectedCommunity.id.","blockedUnless":"Do not expose or execute publisher actions until the backend resolves creator/admin authorization for this selected community."}],"modeSwitching":{"oneAccount":true,"requiresSignOut":false,"preservesPlayerSession":true,"preservesListenerIdentity":true,"authorizationBoundary":"Switching into publisher mode never grants authority by itself; each creator/admin action must still pass server-side scope and role checks for the selected community."},"agentInstructions":["Display selectedCommunity.name and activeMode before proposing community-scoped actions.","Offer fan actions by default; offer publisher actions only when publisher mode is available or when asking the human to authorize it.","Do not assume Laurel-only global context when future communities are added; carry selectedCommunity.id through proposals and confirmations."],"redactedFields":["community.databaseId","artist.internalId","admin.grantId","agentBearerToken"]},"agentAuthorization":{"id":"scoped-delegated-grants","designDoc":"docs/agent/agent-authorization-model.md","status":"selected-storage-pending","credentialPolicy":"Opaque bearer credentials must stay in HTTP Authorization headers or MCP client transport configuration, never prompt-visible tool input.","principalClasses":["guest","listener","creator_admin","owner","approved_automation"],"principalResolutionOrder":["scoped-agent-bearer-token","first-party-better-auth-session","env-gated-dev-operator-admin-token","guest"],"scopeFamilies":["public:read","listener:profile:read","listener:profile:write","listener:preferences:read","listener:preferences:write","listener:entitlements:read","listener:checkout:preview","listener:checkout:start","listener:listen-along:read","listener:listen-along:write","listener:community:post","listener:community:react","listener:ideas:read","listener:ideas:write","creator:<artistId>:read","creator:<artistId>:analytics:read","creator:<artistId>:email:read","creator:<artistId>:email:write","creator:<artistId>:commerce:preview","creator:<artistId>:commerce:write","creator:<artistId>:media:read","creator:<artistId>:media:write","creator:<artistId>:live:read","creator:<artistId>:live:write","creator:<artistId>:community:moderate","creator:<artistId>:community:speak","creator:<artistId>:rooms:read","creator:<artistId>:rooms:write","agent:workflow-triggers:read","agent:workflow-triggers:subscribe","agent:sessions:read","agent:sync-jobs:read","platform:ops:read"],"implementationBlockers":[]},"authModes":[{"id":"guest","summary":"Public manifest reads only. No private listener, creator, provider, or payment state."},{"id":"optional-session","summary":"Public reads plus signed-in listener summaries when a first-party session is present."},{"id":"signed-in-listener","summary":"Private listener reads and reversible listener-scoped writes."},{"id":"confirmed-listener","summary":"Listener-initiated purchase or public-content writes after explicit confirmation."},{"id":"artist-admin-or-approved-automation","summary":"Creator/admin reads and writes using first-party admin auth, a scoped delegated grant, or the current env-gated dev/operator fallback."},{"id":"platform-owner","summary":"Mark/platform-owner-only provider and workspace changes."},{"id":"scoped-agent-grant","summary":"Selected #810 model: a Better Auth human session delegates named scopes to an agent client; bearer credentials stay in transport headers and resolve server-side to a principal."}],"writeEnvelope":{"requiredBeforeMutatingMcpTools":true,"validationEndpoint":{"href":"https://docs.fanful.net/api/agent/action-contracts/envelope","method":"POST","auth":"guest","description":"Validate and normalize the shared confirmed-write envelope without executing a mutation."},"contract":"agent-write-envelope.v1","fields":["resolvedPrincipal","actor","client","grantId","matchedScope","action","target","dryRun","confirmation","idempotencyKey","reason","auditCorrelationId"],"confirmation":"Any destructive, externally visible, billing-impacting, moderation, creator-speech, checkout, or provider mutation needs an explicit user confirmation that repeats the exact target and consequence.","audit":"Every creator/admin/platform write needs durable audit attribution. Listener public writes need visible user attribution plus agent-client metadata.","idempotency":"Every agent write should accept or derive a stable idempotency key so MCP/CLI/ChatGPT retries cannot duplicate charges, posts, go-live transitions, or provider changes."},"workflowTriggers":{"endpoint":{"href":"https://docs.fanful.net/api/agent/workflow-triggers","method":"GET","auth":"guest","description":"Read the signed webhook trigger catalog for event-driven agent workflows."},"resourceUri":"fanful://agent/workflow-triggers/manifest","contract":"agent-workflow-triggers.v1","status":"manifest-ready-delivery-planned","issue":"#1112","policy":"Webhook payloads are redacted prompts to read current Fanful manifests before acting. They never authorize a write by themselves; mutating agent actions still require the shared write envelope and a ready action contract."},"agentSessions":{"endpoint":{"href":"https://docs.fanful.net/api/agent/sessions","method":"GET","auth":"guest","description":"Read the external agent session and event-stream contract for multi-step agent runs."},"resourceUri":"fanful://agent/sessions/manifest","contract":"agent-sessions.v1","status":"manifest-ready-storage-planned","issue":"#1113","policy":"Agent sessions are redacted run histories and pending-approval records. They do not replace current MCP/action contracts, and pending approvals still require the shared write envelope before execution."},"syncJobs":{"endpoint":{"href":"https://docs.fanful.net/api/agent/sync-jobs","method":"GET","auth":"guest","description":"Read the cursor-based sync job and checkpoint contract for imported creator/catalog data."},"resourceUri":"fanful://agent/sync-jobs/manifest","contract":"agent-sync-jobs.v1","status":"manual-run-ready","issue":"#1114/#1224","policy":"Sync jobs report redacted source/target/cursor/checkpoint state and can now run the first-party Stripe catalog app-reference drift worker with scoped/admin credentials. They never accept provider credentials or raw payment/media ids as tool input, and drift reports do not authorize writes without a ready action contract."},"filters":{"audience":null,"domain":null,"returned":35,"total":35},"contracts":[{"id":"platform.community-mode.context","domain":"platform","audiences":["creator","listener","fan","operator"],"status":"ready","summary":"Read the selected Fanful community and active fan/publisher mode context that every agent proposal should carry.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/action-contracts","method":"GET","auth":"guest","description":"Cross-surface action contract manifest."},{"href":"https://docs.fanful.net/api/agent/listener-experience","method":"GET","auth":"optional-session","description":"Listener/fan manifest with community mode context."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Creator commerce manifest with publisher authorization context."}],"futureToolName":"fanful_agent_manifest_read","confirmation":{"required":false,"kind":"none","prompt":null},"audit":{"required":false,"currentRecord":null,"requiredBeforeExecutable":null,"attribution":"Read-only context. Publisher actions still need server-confirmed creator/admin authorization and their own audit paths."},"idempotency":{"requiredForWrites":false,"keyScope":"not applicable"},"rateLimit":{"scope":"ip-or-session","expectation":"Use normal manifest read limits; this route does not mutate state."},"blockers":[],"relatedIssues":["#560","#1075","#1078"],"modelVisibleBoundaries":["Always carry selectedCommunity.id and activeMode before proposing actions.","Do not offer publisher writes unless publisher mode is available or the human explicitly authorizes the required creator/admin scope.","Mode switching must preserve listener session, player state, and authorization boundaries."]},{"id":"creator.community.channel-create","domain":"community","audiences":["creator","operator"],"status":"ready","summary":"Create one additional Fanful community channel, including optional membership-tier access metadata, through a confirmed audited write.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/community-chat","method":"GET","auth":"optional-session","description":"Agent-safe community channel manifest."},{"href":"https://docs.fanful.net/api/admin/community-chat","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed creator community channel creation wrapper."}],"futureToolName":"fanful_creator_community_channel_create","confirmation":{"required":true,"kind":"moderation","prompt":"Confirm channel name, optional description, access mode, membership tier ids, observed channel ids, idempotency key, audit correlation id, and listener-facing impact."},"audit":{"required":true,"currentRecord":"community_chat_channels + community_chat_admin_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute channel creation to the artist admin or approved automation identity, including agent client, channel access summary, observed channel ids, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + channel name/access + observed channel ids"},"rateLimit":{"scope":"artist-admin-or-automation + community-channel-create","expectation":"Reject duplicate idempotency keys, stale channel reads, locked channel controls, over-limit creates, invalid membership tiers, and ambiguous access metadata before mutating."},"blockers":[],"relatedIssues":["#573","#616","#810","#921","#1371","#1545"],"modelVisibleBoundaries":["Do not expose private member directories, listener membership ids, payment identifiers, hidden messages, or notification recipient lists.","This wrapper creates one community_chat_channels row and optional access metadata only.","This wrapper never creates membership tiers, changes prices, grants memberships, sends notifications, or edits chat messages."]},{"id":"creator.community.channel-update","domain":"community","audiences":["creator","operator"],"status":"ready","summary":"Update one non-default Fanful community channel's title, description, archive state, or access metadata through a confirmed audited write.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/community-chat","method":"GET","auth":"optional-session","description":"Agent-safe community channel manifest."},{"href":"https://docs.fanful.net/api/admin/community-chat","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Confirmed creator community channel settings wrapper."}],"futureToolName":"fanful_creator_community_channel_update","confirmation":{"required":true,"kind":"moderation","prompt":"Confirm channel id, title/description/archive/access changes, stale-state updated_at value, idempotency key, audit correlation id, and listener-facing impact."},"audit":{"required":true,"currentRecord":"community_chat_channels + community_chat_admin_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute channel settings changes to the artist admin or approved automation identity, including agent client, before/after channel summaries, stale-state guard, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + community-channel-id + requested fields + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + community-channel-id","expectation":"Reject duplicate idempotency keys, stale channel state, default #general rename/archive/access changes, no-op updates, and invalid membership-tier references before mutating."},"blockers":[],"relatedIssues":["#573","#616","#810","#921","#1371","#1545"],"modelVisibleBoundaries":["Do not expose private member directories, listener membership ids, payment identifiers, hidden messages, or notification recipient lists.","This wrapper updates only community_chat_channels public settings and access metadata.","This wrapper never creates membership tiers, changes prices, grants memberships, sends notifications, or edits chat messages."]},{"id":"creator.analytics.summary.read","domain":"analytics","audiences":["creator","operator"],"status":"ready","summary":"Read aggregate creator analytics for Laurel without exposing raw listener rows, private identifiers, or exportable audience data.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/artist-analytics","method":"GET","auth":"artist-admin-or-approved-automation","description":"Agent-safe artist analytics manifest with aggregate summary when authorized."},{"href":"https://docs.fanful.net/api/admin/analytics","method":"GET","auth":"artist-admin-or-approved-automation","description":"First-party admin analytics source."}],"futureToolName":"fanful_creator_analytics_read","confirmation":{"required":false,"kind":"none","prompt":null},"audit":{"required":false,"currentRecord":null,"requiredBeforeExecutable":null,"attribution":"Read-only aggregate analytics are gated by creator/admin/scoped creator credentials. Exports, audience targeting, and analytics writes need separate contracts."},"idempotency":{"requiredForWrites":false,"keyScope":"not applicable"},"rateLimit":{"scope":"creator-admin-or-scoped-agent","expectation":"Use normal private manifest read limits; analytics export jobs are not available through this contract."},"blockers":[],"relatedIssues":["#115","#1192"],"modelVisibleBoundaries":["Return aggregate source funnels, top content outcomes, listener cohorts, and recent signal types only.","Do not expose listener.userId, anonymousId, sessionId, deviceName, userAgent, IP hash, raw referrer query strings, or raw listener rows.","Do not use this read contract to send email, target audiences, export CSVs, or infer private listener identities."]},{"id":"creator.email.broadcast-send","domain":"email","audiences":["creator","operator"],"status":"preview-ready","summary":"Read campaign state and generate a non-mutating recipient preview for a creator broadcast. The agent route never sends email; final external sends stay behind the human/admin campaign confirmation path.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/email-campaigns","method":"GET","auth":"artist-admin-or-approved-automation","description":"Read the agent-safe email campaign manifest, campaign status summary, and redacted audience readiness."},{"href":"https://docs.fanful.net/api/agent/email-campaigns","method":"POST","auth":"artist-admin-or-approved-automation","description":"Preview a broadcast send request without saving, scheduling, or sending email."},{"href":"https://docs.fanful.net/api/agent/action-contracts/envelope","method":"POST","auth":"guest","description":"Validate the shared agent-write envelope and exact confirmation text before any future executable wrapper."},{"href":"https://docs.fanful.net/api/admin/email-campaigns","method":"POST","auth":"artist-admin-or-approved-automation","description":"Existing first-party admin draft, preview, schedule, and confirmed-list send path."}],"futureToolName":"fanful_creator_email_broadcast_send","confirmation":{"required":true,"kind":"creator-email","prompt":"Confirm the campaign subject, audience label, redacted recipient counts, suppression/unsubscribe recheck, delivery timing, idempotency key, audit correlation id, and that email will be externally visible."},"audit":{"required":true,"currentRecord":"email_campaigns + email_messages + email_events for human/admin sends; agent preview is no-write","requiredBeforeExecutable":"Dedicated executable agent wrapper must persist agent client, grant/session, confirmation envelope, recipient preview snapshot, idempotency key, and final delivery result before any direct agent send is enabled.","attribution":"Attribute every preview to the artist admin, approved automation, or scoped creator grant. Attribute any future send to the same principal plus the agent client and human confirmation evidence."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + campaign-subject-or-id + audience + confirmed preview snapshot + agent client"},"rateLimit":{"scope":"artist-admin-or-automation + campaign","expectation":"Throttle preview retries and reject any future duplicate idempotency key before delivery or scheduling."},"blockers":["Direct agent execution remains disabled; agents may read campaign state and generate recipient previews only.","Any future executable agent send must reuse server-side suppression, unsubscribe, and preference checks at send time and must not accept arbitrary uploaded recipient lists."],"relatedIssues":["#1260","#1349","#1352","#1356","#1358","#1359"],"modelVisibleBoundaries":["Do not expose raw subscriber emails, Better Auth ids, listener ids, suppression notes, inbound message bodies, provider event payloads, or raw email content from prior campaigns.","Preview responses may include campaign id, subject, status, redacted recipient counts, suppression counts, pending/unsubscribed counts, confirmation copy, and blocked executable-send guidance.","The agent endpoint never saves a draft, schedules a campaign, processes due campaigns, or sends external email.","Use /api/admin/email-campaigns for current human/admin sends; agents must not drive that route through hidden browser automation."]},{"id":"creator.media.upload-provenance","domain":"media","audiences":["creator","operator"],"status":"ready","summary":"Create confirmed artist media upload/provenance sessions with agent attribution, while keeping binary media and artwork transfer outside model-visible tool input.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/action-contracts?audience=creator&domain=media","method":"GET","auth":"guest","description":"Agent-safe upload/provenance contract and handoff manifest."},{"href":"https://docs.fanful.net/api/agent/media-upload-sessions","method":"GET","auth":"artist-admin-or-approved-automation","description":"Read the agent media upload-session manifest, policy, and handoff boundaries."},{"href":"https://docs.fanful.net/api/agent/media-upload-sessions","method":"POST","auth":"artist-admin-or-approved-automation","description":"Preview or create a confirmed upload-session record with agent-write-envelope.v1, idempotency, and audit attribution."},{"href":"https://docs.fanful.net/api/uploads/sign","method":"POST","auth":"artist-admin-or-approved-automation","description":"Authenticated upload handoff helper that currently points callers at the Worker multipart route."},{"href":"https://docs.fanful.net/api/admin/uploads","method":"POST","auth":"artist-admin-or-approved-automation","description":"Current admin multipart upload route for audio/video, artwork, visibility, and provenance fields."},{"href":"https://docs.fanful.net/admin#tracks","method":"GET","auth":"artist-admin-or-approved-automation","description":"Current creator web upload surface."}],"futureToolName":"fanful_creator_media_upload_session_create","confirmation":{"required":true,"kind":"media-upload","prompt":"Confirm the artist, track title, visibility, media provenance, source/credit/license fields, replacement status, file descriptors, duration, idempotency key, audit correlation id, and out-of-model binary upload handoff before creating an upload session."},"audit":{"required":true,"currentRecord":"agent_media_upload_sessions + agent_write_idempotency_keys; tracks rows after multipart completion","requiredBeforeExecutable":null,"attribution":"Attribute upload-session creation to the artist admin or approved automation identity, including agent client, operator reason, source/provenance fields, idempotency key, and upload-session correlation."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + normalized title + media content hash or upload-session id + provenance version"},"rateLimit":{"scope":"artist-admin-or-automation + upload-session","expectation":"Reject retry storms, oversized files, unsupported media/artwork MIME types, stale upload sessions, duplicate idempotency keys, and repeated failed provenance submissions."},"blockers":["Large-file direct-to-R2/S3 upload credentials are still future work; /api/uploads/sign currently returns a Worker multipart handoff rather than a presigned R2 URL.","The confirmed agent session creates the audited handoff; the later binary multipart upload must happen outside model-visible input and include agentUploadSessionId to link the track back to the session."],"relatedIssues":["#1260","#1282","#1291","#1292","#1298","#1299"],"modelVisibleBoundaries":["Agents may create a confirmed upload-session record, then hand binary upload to a non-model client through /api/admin/uploads with agentUploadSessionId.","Do not ask the model to hold raw media bytes, artwork bytes, raw R2 keys, private media URLs, stream URLs, or storage credentials in prompt-visible tool input.","Model-visible output may name required fields and file descriptors: title, subtitle, composer, album, durationSeconds, visibility, mediaProvenance, mediaCredit, mediaSourceUrl, mediaLicense, replacementStatus, replacementNote, filename, contentType, sizeBytes, and sha256.","Unsupported MIME type, file-size, expired session, duplicate idempotency key, missing MEDIA binding, and failed publish states must be returned as explicit structured errors instead of falling back to browser automation."]},{"id":"listener.account.state","domain":"account","audiences":["listener","fan"],"status":"ready","summary":"Read public fan state and signed-in listener account summaries without exposing raw internal ids or private media URLs.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/listener-experience","method":"GET","auth":"optional-session","description":"Agent-safe listener manifest."},{"href":"https://docs.fanful.net/api/listener-state","method":"GET","auth":"optional-session","description":"First-party listener state used by web."},{"href":"https://docs.fanful.net/api/mobile/bootstrap","method":"GET","auth":"optional-session","description":"Native listener bootstrap source."}],"futureToolName":"fanful_listener_account_read","confirmation":{"required":false,"kind":"none","prompt":null},"audit":{"required":false,"currentRecord":null,"requiredBeforeExecutable":null,"attribution":"Read-only account summaries are scoped to the first-party session and redact Better Auth ids, listener ids, device ids, and payment identifiers."},"idempotency":{"requiredForWrites":false,"keyScope":"not applicable"},"rateLimit":{"scope":"session-or-ip","expectation":"Use the same read rate limits as listener account/mobile bootstrap endpoints."},"blockers":[],"relatedIssues":["#608","#673"],"modelVisibleBoundaries":["Do not reveal raw Better Auth user ids, listener ids, device ids, push tokens, stream URLs, offline URLs, invite tokens, purchase ids, or payment ids."]},{"id":"listener.profile.display-name.update","domain":"account","audiences":["listener","fan"],"status":"ready","summary":"Update the signed-in listener's display name for future account chrome, chat, community, and comment attribution.","existingEndpoints":[{"href":"https://docs.fanful.net/api/account/profile","method":"GET","auth":"signed-in-listener","description":"Existing signed-in listener profile read route."},{"href":"https://docs.fanful.net/api/account/profile","method":"PATCH","auth":"signed-in-listener","description":"Existing signed-in listener display-name update route."},{"href":"https://docs.fanful.net/api/agent/listener-experience","method":"GET","auth":"optional-session","description":"Agent-safe listener manifest with current profile read status."},{"href":"https://docs.fanful.net/api/agent/listener-experience","method":"POST","auth":"confirmed-listener","description":"Confirmed listener display-name update wrapper."}],"futureToolName":"fanful_listener_display_name_update","confirmation":{"required":true,"kind":"account-preference","prompt":"Confirm the exact new display name and that future public chat, community, and comment posts will use it."},"audit":{"required":true,"currentRecord":"user.name + listener_profile_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the signed-in listener session or scoped listener grant plus the calling agent client, previous and next display names, confirmation evidence, idempotency key, audit correlation id, and reason."},"idempotency":{"requiredForWrites":true,"keyScope":"listener-id + client-id + normalized display name"},"rateLimit":{"scope":"signed-in-listener","expectation":"Throttle repeated profile writes and reject empty or over-limit display names with the shared profile validation copy."},"blockers":[],"relatedIssues":["#608","#673","#873","#892","#895","#1715"],"modelVisibleBoundaries":["Do not change email addresses, passwords, login credentials, newsletter consent, payment identity, or historical chat/comment display-name snapshots.","Display names are externally visible on future listener-originated public posts; confirmation must repeat the exact visible name and the stale-state observed display name before writing.","Use signed-in-listener in model-visible actor/target ids; do not expose Better Auth user ids, listener ids, raw session tokens, or scoped grant bearer tokens."]},{"id":"listener.account.preferences.update","domain":"account","audiences":["listener","fan"],"status":"contract-only","summary":"Update notification and account preferences for the signed-in listener through a reversible agent write.","existingEndpoints":[{"href":"https://docs.fanful.net/api/account/notification-preferences","method":"PATCH","auth":"signed-in-listener","description":"Existing preference update route."},{"href":"https://docs.fanful.net/api/account/password","method":"POST","auth":"signed-in-listener","description":"Existing password/account route."}],"futureToolName":"fanful_listener_preferences_update","confirmation":{"required":true,"kind":"account-preference","prompt":"Confirm the exact preference fields and new values before writing."},"audit":{"required":true,"currentRecord":"listener_notification_preferences","requiredBeforeExecutable":"Agent client attribution in preference writes.","attribution":"Attribute writes to the signed-in listener session plus the calling agent client."},"idempotency":{"requiredForWrites":true,"keyScope":"listener-id + client-id + requested preference patch"},"rateLimit":{"scope":"signed-in-listener","expectation":"Throttle repeated preference changes and keep email-delivery verification requirements intact."},"blockers":["Route preference writes through the shared agent-write envelope with durable client attribution before MCP/CLI write exposure."],"relatedIssues":["#608","#673"],"modelVisibleBoundaries":["Do not accept or expose push tokens, device ids, raw email verification tokens, or password material."]},{"id":"listener.purchase-link.preview","domain":"commerce","audiences":["listener","fan"],"status":"preview-ready","summary":"Preview buyer-facing purchase-link terms for a membership, support, shop, lesson, or paid-room target without creating Stripe Checkout Sessions or granting entitlement.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/listener-experience","method":"GET","auth":"optional-session","description":"Read listener.purchaseLinkPreview for the current target and caller."},{"href":"https://docs.fanful.net/api/agent/action-contracts","method":"GET","auth":"guest","description":"Read the cross-surface purchase-link preview contract descriptor."}],"futureToolName":"fanful_listener_purchase_link_preview","confirmation":{"required":false,"kind":"checkout","prompt":"Preview returns the exact checkout confirmation copy; creating a checkout later must resubmit that copy in the shared confirmed-write envelope."},"audit":{"required":false,"currentRecord":null,"requiredBeforeExecutable":"Preview is read-only. A future create path must persist a Fanful checkout intent with listener/scoped-grant, client, confirmation, idempotency, and audit correlation before Stripe is called.","attribution":"Preview attribution stays model-visible as buyer mode only; raw listener, grant, purchase, membership, Better Auth, and Stripe identifiers stay server-side."},"idempotency":{"requiredForWrites":false,"keyScope":"not applicable until purchase-link create"},"rateLimit":{"scope":"session-or-scoped-grant","expectation":"Throttle previews like other listener account reads; reject create retries later with checkout-intent idempotency."},"blockers":[],"relatedIssues":["#612","#916","#917","#918","#971"],"modelVisibleBoundaries":["Preview does not create Stripe Checkout Sessions, update Fanful purchase state, grant membership/lesson/room entitlement, or expose checkout URLs.","Responses may include public target label, buyer mode, price, cadence, expiration, confirmation copy, blockers, and a redacted entitlement outcome.","Live-room support uses the same preview contract with targetKind=support, targetId=donation, and the web live-room suggested amount; first-party and support-only agent checkout starts can attach liveEventId.","Do not expose Stripe Price ids, Checkout Session ids, Customer ids, Subscription ids, Payment Intent ids, raw purchase ids, membership ids, listener ids, Better Auth ids, scoped grant ids, bearer tokens, or card details.","See docs/agent/link-cli-purchase-contract.md for the canonical preview-first purchase-link contract."]},{"id":"listener.checkout.start","domain":"commerce","audiences":["listener","fan"],"status":"ready","summary":"Start a support donation, membership, or shop checkout after previewing the buyer-facing terms and resubmitting the exact confirmed write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/listener-experience","method":"POST","auth":"confirmed-listener","description":"Support, membership, and shop confirmed agent checkout-start route."},{"href":"https://docs.fanful.net/api/checkout","method":"POST","auth":"confirmed-listener","description":"Existing first-party checkout session creation route."},{"href":"https://docs.fanful.net/api/shop/status","method":"GET","auth":"guest","description":"Public shop availability/readiness route."},{"href":"https://docs.fanful.net/api/lessons","method":"GET","auth":"guest","description":"Public lesson and coaching offer catalog."}],"futureToolName":"fanful_listener_support_checkout_start / fanful_listener_membership_checkout_start / fanful_listener_shop_checkout_start","confirmation":{"required":true,"kind":"checkout","prompt":"Confirm the support donation, membership, or shop target, price, currency, recipient listener account, redirect target, and that payment effects wait for Stripe confirmation."},"audit":{"required":true,"currentRecord":"agent_checkout_intents + purchases/memberships","requiredBeforeExecutable":null,"attribution":"Attribute support, membership, and shop checkout starts to the signed-in listener or scoped listener grant plus the calling agent client, idempotency key, audit correlation id, and confirmed terms."},"idempotency":{"requiredForWrites":true,"keyScope":"listener-or-grant + target + confirmed price"},"rateLimit":{"scope":"listener-or-email","expectation":"Prevent duplicate checkout creation loops and reject reused idempotency keys before Stripe."},"blockers":["#530 must finish lesson bundle, credit, cancellation, and refund policy before lesson checkout starts become executable.","#918 remains the broader multi-target checkout-intent umbrella for lesson and paid-room targets."],"relatedIssues":["#608","#612","#673","#916","#917","#918","#986","#1222","#1517"],"modelVisibleBoundaries":["Support donations with targetKind=support/targetId=donation, membership tiers with targetKind=membership, and the signed-cd shop product with targetKind=shop are executable through the agent route today.","Lesson and paid-room checkout starts remain blocked until target-specific catalog, price, entitlement, and policy work is complete.","Do not expose Stripe checkout ids, payment intents, customer ids, card details, raw checkout intent ids, raw purchase ids, listener ids, Better Auth ids, grant ids, or private entitlement ids."]},{"id":"listener.purchase-link.status","domain":"commerce","audiences":["listener","fan"],"status":"ready","summary":"Read redacted support, membership, or shop checkout intent status after an agent-started checkout.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/listener-experience","method":"GET","auth":"confirmed-listener","description":"Read listener.purchaseLinkStatus by redacted support/membership/shop reference or idempotency key."}],"futureToolName":"fanful_listener_purchase_link_status","confirmation":{"required":false,"kind":"checkout","prompt":"Status reads are non-mutating and require the same listener/session or scoped listener grant context as checkout start."},"audit":{"required":false,"currentRecord":"agent_checkout_intents","requiredBeforeExecutable":null,"attribution":"Return only checkout intent state scoped to the signed-in listener or same scoped grant; raw checkout, Stripe, listener, purchase, membership, and grant identifiers stay server-side."},"idempotency":{"requiredForWrites":false,"keyScope":"read by prior checkout idempotency key or redacted reference"},"rateLimit":{"scope":"listener-or-grant","expectation":"Throttle repeated status polling while allowing short-lived checkout follow-up."},"blockers":["#918 remains the broader multi-target checkout-intent umbrella; lesson and paid-room checkout status should wait until those create paths exist."],"relatedIssues":["#608","#612","#673","#918","#986","#1069","#1222","#1517"],"modelVisibleBoundaries":["Only support donation, membership, and shop checkout intents are readable through this status contract today.","Status reads may return redacted reference, status, target summary, amount/currency, timestamps, live-event attribution when applicable, and whether Stripe ids are redacted.","Do not expose raw checkout intent ids, Stripe Checkout Session ids, Payment Intent ids, Customer ids, purchase ids, listener ids, Better Auth ids, grant ids, bearer tokens, checkout URLs, or card details."]},{"id":"listener.community.post","domain":"community","audiences":["listener","fan"],"status":"ready","summary":"Post one visible community chat message or reply as the authenticated listener through the confirmed community-chat agent wrapper.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/community-chat","method":"GET","auth":"optional-session","description":"Agent-safe community chat manifest."},{"href":"https://docs.fanful.net/api/agent/community-chat","method":"POST","auth":"confirmed-listener","description":"Confirmed listener community-message post/reply wrapper."},{"href":"https://docs.fanful.net/api/community/messages","method":"POST","auth":"signed-in-listener","description":"Existing community message route."},{"href":"https://docs.fanful.net/api/live/messages","method":"POST","auth":"signed-in-listener","description":"Existing live-room message route."},{"href":"https://docs.fanful.net/api/comments","method":"POST","auth":"signed-in-listener","description":"Existing timed-comment route."}],"futureToolName":"fanful_listener_community_message_post","confirmation":{"required":true,"kind":"public-content","prompt":"Must exactly match: I confirm listener.community-message-post for <targetSummary>."},"audit":{"required":true,"currentRecord":"community_chat_messages + agent_write_idempotency_keys + community-chat notification/realtime side effects","requiredBeforeExecutable":null,"attribution":"Community messages are visibly attributed to the listener and retain the calling agent client, matched listener principal, idempotency key, audit correlation id, and reason in the confirmed-write envelope."},"idempotency":{"requiredForWrites":true,"keyScope":"listener-id + channel-id + body + reply target"},"rateLimit":{"scope":"listener + target channel","expectation":"Use existing channel access, slow-mode, body length, reply-target, hidden-message, and idempotent retry controls before mutating."},"blockers":[],"relatedIssues":["#573","#608","#616","#622","#648","#673","#1546","#1710"],"modelVisibleBoundaries":["This ready contract is limited to community chat message/reply writes through /api/agent/community-chat.","Live-room messages, timed comments, reactions, creator-speech automation, and moderation actions remain separate contracts until their own wrappers are ready.","Do not expose hidden moderation history, socket tokens, private room links, notification recipient lists, raw listener ids, or bearer/session credentials."]},{"id":"creator.commerce.lesson-credit-ledger-read","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Read the redacted admin lesson-credit ledger health contract for aggregate totals, event-type breakdowns, recent event markers, and blocked write identifiers.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"artist-admin-or-approved-automation","description":"Agent-safe creator commerce manifest with authorized commerce.adminLessonCreditLedger readback."},{"href":"https://docs.fanful.net/api/admin/lesson-credit-ledger","method":"GET","auth":"artist-admin-or-approved-automation","description":"Human/admin API with the same redacted ledger readback shape."}],"futureToolName":"fanful_creator_lesson_credit_ledger_read","confirmation":{"required":false,"kind":"none","prompt":null},"audit":{"required":false,"currentRecord":null,"requiredBeforeExecutable":null,"attribution":"Read-only ledger health summary. Credit consumption, refund, renewal, skip-week, cancellation, and tier-benefit writes need separate confirmed-write contracts before becoming executable."},"idempotency":{"requiredForWrites":false,"keyScope":"not applicable"},"rateLimit":{"scope":"artist-admin-or-automation + lesson-credit-ledger-read","expectation":"Use normal creator/admin read limits; this route does not mutate state."},"blockers":[],"relatedIssues":["#530","#858","#1417","#1784","#1794","#1795"],"modelVisibleBoundaries":["Guest and listener callers must receive an explicit authorization blocker and no partial ledger data.","Do not expose raw lesson_credit_ledger_events ids, user ids, student emails, booking ids, purchase ids, policy ids, idempotency keys, reasons, metadata JSON, Stripe checkout sessions, or Stripe payment intents.","The model-visible recent event sample is limited to aggregate numbers, event type labels, timestamps, and boolean presence markers."]},{"id":"creator.commerce.preview-and-update","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Preview creator coaching/lesson price and policy impact, then execute confirmed lesson offering price writes through the shared agent write envelope. Broader product, tier, credit, cancellation, refund, and entitlement writes remain blocked.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Non-mutating lesson price preview and confirmed lesson price write actions."},{"href":"https://docs.fanful.net/api/admin/lessons","method":"POST","auth":"artist-admin-or-approved-automation","description":"Existing lesson admin write route."},{"href":"https://docs.fanful.net/api/admin/shop","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Existing shop admin write route."}],"futureToolName":"fanful_creator_service_price_policy_update","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm before/after public copy, price/currency, Stripe impact, affected surfaces, entitlement impact, cancellation terms, stale-state guard, idempotency key, and rollback plan."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + commerce-object-id + action + confirmed version"},"rateLimit":{"scope":"artist-admin-or-automation","expectation":"Throttle billing-impacting writes and keep preview calls non-mutating."},"blockers":["Only lesson_offerings.price_cents is executable in this contract. Use creator.commerce.stripe-price-select for existing lesson Stripe Price mapping changes, creator.commerce.stripe-price-create for replacement lesson Stripe Price creation, creator.commerce.shop-product-stripe-price-select/create for shop product Price mappings, or creator.commerce.shop-product-visibility-update for shop product visibility. Broader tier changes, credits, cancellation/refund terms, and entitlement changes remain blocked."],"relatedIssues":["#534","#608","#612","#671","#799","#945","#1057","#1083"],"modelVisibleBoundaries":["Do not expose Stripe price ids, checkout ids, student contact details, meeting URLs, booking instructions, download URLs, or private notes."]},{"id":"creator.commerce.lesson-policy-update","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Create or update lesson policy settings through a confirmed, audited write envelope. Refund execution, credit spending, bundle creation, and cancellation/reschedule workflows remain blocked.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed lesson policy settings write for one artist-default or offering-override row."},{"href":"https://docs.fanful.net/api/lesson-policy-readiness","method":"GET","auth":"guest","description":"Shared web/native/agent lesson policy readiness contract."}],"futureToolName":"fanful_creator_lesson_policy_update","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm policy id, scope, offering override if any, cancellation/reschedule cutoffs, refund/no-show/skip-week settings, stale-state guard, idempotency key, audit correlation id, and the fact that no refund, credit, Stripe, or booking-state mutation will happen."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted before/after policy settings, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + lesson-policy-settings-id + observed updated_at-or-policy-id-set + settings"},"rateLimit":{"scope":"artist-admin-or-automation + lesson-policy-settings-id","expectation":"Reject duplicate idempotency keys, stale policy rows, stale policy id catalogs, no-op updates, and invalid offering overrides before mutating."},"blockers":["This contract updates lesson_policy_settings only; cancellation/reschedule execution, refunds, credit ledger consumption, bundles, subscription renewals, and tier-linked benefit enforcement remain blocked in #530."],"relatedIssues":["#530","#799","#1371","#1413"],"modelVisibleBoundaries":["Do not expose student contact details, booking notes, meeting URLs, raw Stripe ids, refund ids, or private lesson notes."]},{"id":"creator.commerce.lesson-availability-update","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Create or update future lesson availability windows through a confirmed, audited write envelope. Booking, refund, credit, Stripe, meeting URL, and private note changes remain blocked.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed lesson availability write for one future open or cancelled window."},{"href":"https://docs.fanful.net/api/admin/lessons","method":"POST","auth":"artist-admin-or-approved-automation","description":"Existing first-party lesson admin write route."}],"futureToolName":"fanful_creator_lesson_availability_update","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm availability id, offering id, start/end time, timezone, open/cancelled status, capacity, stale-state guard, idempotency key, audit correlation id, and the fact that no booking, refund, credit, Stripe, meeting URL, or private-note mutation will happen."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted before/after availability summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + lesson-availability-window-id + observed updated_at-or-availability-id-set + schedule settings"},"rateLimit":{"scope":"artist-admin-or-automation + lesson-availability-window-id","expectation":"Reject duplicate idempotency keys, stale availability rows, stale availability id catalogs, no-op updates, past windows, held/booked slot mutations, and unsafe side-effect fields before mutating."},"blockers":["This executable slice updates lesson_availability_windows scheduling fields only. Booking cancellation/reschedule execution, refunds, credit ledger consumption, meeting URL writes, and private notes remain blocked under #530 or need separate contracts."],"relatedIssues":["#530","#799","#1413","#1550"],"modelVisibleBoundaries":["Do not expose student contact details, booking notes, meeting URLs, raw Stripe ids, refund ids, or private lesson notes.","This wrapper never updates lesson_bookings, lesson_credit_ledger_events, Stripe checkout sessions, meeting_url, or notes."]},{"id":"creator.commerce.shop-product-create","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Create one shop product with safe catalog metadata through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed shop product creation write."},{"href":"https://docs.fanful.net/api/admin/shop","method":"GET","auth":"artist-admin-or-approved-automation","description":"Existing first-party shop product admin read."}],"futureToolName":"fanful_creator_shop_product_create","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm product title, kind, price, visibility state, inventory fields, safe fulfillment/display metadata, observed product ids, idempotency key, audit correlation id, and affected fan surfaces before creating a product."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute creation to the artist admin or approved automation identity, including agent client, redacted created product summary, observed product ids, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + shop-product-id + observed product ids + catalog metadata"},"rateLimit":{"scope":"artist-admin-or-automation + shop-product-create","expectation":"Reject duplicate idempotency keys, stale product catalogs, duplicate product ids or generated slugs, unsupported product kinds, invalid visibility combinations, non-download download metadata, and unsafe extra product mutation fields before mutating."},"blockers":["This executable slice inserts one store_items row with safe catalog metadata only. Raw download file URLs, external fulfillment URLs, Stripe Price ids, checkout sessions, purchase rows, fulfillment execution, order changes, refunds, and credits need separate contracts."],"relatedIssues":["#612","#671","#799","#1052","#1548","#1681","#1684","#1692"],"modelVisibleBoundaries":["Do not expose raw Stripe Price ids, checkout sessions, payment intents, external fulfillment URLs, private download URLs, inventory supplier notes, or buyer identifiers.","Model-visible responses may show product id, title, description, kind, price cents, active/showInShop booleans, inventory count, fulfillment note, download display filename/release notes, sort order, and booleans for sensitive fields only.","This wrapper never sets raw download file URLs, external URLs, Stripe Price mappings, checkout sessions, purchase rows, fulfillment execution, refunds, or credits. Use the dedicated existing-product wrappers for later visibility, details, and Stripe Price mapping changes."]},{"id":"creator.commerce.shop-product-visibility-update","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Update one editable shop product's active and public-shop visibility flags through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed shop product visibility write for one editable product."},{"href":"https://docs.fanful.net/api/admin/shop","method":"GET","auth":"artist-admin-or-approved-automation","description":"Existing first-party shop product admin read."}],"futureToolName":"fanful_creator_shop_product_visibility_update","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm shop product id, product title, requested active/showInShop state, stale-state guard, idempotency key, audit correlation id, and affected fan surfaces before changing product visibility."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted before/after product visibility summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + shop-product-id + active/showInShop + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + shop-product-id","expectation":"Reject duplicate idempotency keys, stale product rows, no-op visibility changes, unsupported product kinds, and unsafe extra product mutation fields before mutating."},"blockers":["This executable slice is limited to store_items.active and store_items.show_in_shop. Safe product detail edits use creator.commerce.shop-product-details-update; price and Stripe Price mapping use creator.commerce.shop-product-stripe-price-select/create. Raw download URL, external URL, checkout, fulfillment execution, order, and refund changes need separate contracts."],"relatedIssues":["#612","#671","#1052","#1517","#1548"],"modelVisibleBoundaries":["Do not expose raw Stripe Price ids, checkout sessions, payment intents, external fulfillment URLs, private download URLs, inventory supplier notes, or buyer identifiers.","Model-visible responses may show product id, title, kind, price cents, active/showInShop booleans, inventory count, and booleans for sensitive fields only.","This wrapper never changes product details, price, Stripe mapping, fulfillment terms, external URLs, or download URLs."]},{"id":"creator.commerce.shop-product-details-update","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Update one existing shop product's safe catalog copy, inventory, fulfillment note, download display metadata, or sort order through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed shop product details write for one editable product."},{"href":"https://docs.fanful.net/api/admin/shop","method":"GET","auth":"artist-admin-or-approved-automation","description":"Existing first-party shop product admin read."}],"futureToolName":"fanful_creator_shop_product_details_update","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm shop product id, title, requested detail fields, stale-state guard, idempotency key, audit correlation id, and affected fan surfaces before changing product details."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted before/after product detail summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + shop-product-id + requested details + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + shop-product-id","expectation":"Reject duplicate idempotency keys, stale product rows, no-op details changes, unsupported product kinds, duplicate generated slugs, and unsafe extra product mutation fields before mutating."},"blockers":["This executable slice is limited to store_items title/description/slug, inventory tracking/count, fulfillment note, download display metadata, and sort order. Price and Stripe Price mapping use creator.commerce.shop-product-stripe-price-select/create. Raw download URLs, external URLs, product kind/id, checkout sessions, order fulfillment, and refunds need separate contracts."],"relatedIssues":["#612","#671","#799","#1052","#1548","#1681"],"modelVisibleBoundaries":["Do not expose raw Stripe Price ids, checkout sessions, payment intents, external fulfillment URLs, private download URLs, inventory supplier notes, or buyer identifiers.","Model-visible responses may show product id, title, description, kind, price cents, active/showInShop booleans, inventory count, fulfillment note, download display filename/release notes, and booleans for sensitive fields only.","This wrapper never changes price, Stripe mapping, raw download file URLs, external URLs, product kind/id, checkout sessions, purchase rows, fulfillment execution, or refunds. Use creator.commerce.shop-product-stripe-price-select/create for shop product Price mappings."]},{"id":"creator.commerce.shop-product-stripe-price-select","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Select or clear an already-known Stripe Price mapping for one existing shop product through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed shop product Stripe Price selection wrapper."},{"href":"https://docs.fanful.net/api/admin/stripe-catalog","method":"GET","auth":"artist-admin-or-approved-automation","description":"Authenticated Stripe catalog readiness and app-state mapping contract."}],"futureToolName":"fanful_creator_shop_product_stripe_price_select","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm shop product id, selected or cleared Stripe Price mapping, stale-state guard, amount/currency compatibility, one-time Price compatibility, idempotency key, audit correlation id, and rollback path."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted shop product Stripe Price mapping summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + shop-product-id + selected-stripe-price-id + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + shop-product-id","expectation":"Reject duplicate idempotency keys, stale product state, no-op selections, unknown Stripe Price ids, recurring Price references, and amount/currency mismatches before mutating."},"blockers":["Selected Stripe Price ids must already appear in Laurel app-state Stripe catalog references and match the shop product amount/currency."],"relatedIssues":["#612","#671","#799","#1052","#1681","#1684"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, raw Stripe Price ids, raw Stripe Product ids, checkout sessions, payment intents, customer ids, buyer identifiers, private download URLs, or fulfillment internals.","Model-visible responses may show redacted Stripe Price ids only; use the authenticated admin catalog for raw ids.","This wrapper updates only store_items.stripe_price_id; it never changes product price, copy, inventory, fulfillment, checkout sessions, orders, refunds, or credits."]},{"id":"creator.commerce.shop-product-stripe-price-create","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Create one replacement immutable one-time Stripe Price for one existing shop product, then select it through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed shop product Stripe Price creation wrapper."},{"href":"https://docs.fanful.net/api/admin/stripe-catalog","method":"GET","auth":"artist-admin-or-approved-automation","description":"Authenticated Stripe catalog readiness and app-state mapping contract."}],"futureToolName":"fanful_creator_shop_product_stripe_price_create","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm shop product id, new amount/currency, existing product context, stale-state guard, idempotency key, audit correlation id, and rollback path before creating and selecting a replacement one-time Stripe Price."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted shop product Stripe Price creation summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + shop-product-id + new-amount + currency + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + shop-product-id","expectation":"Reject duplicate idempotency keys, stale product state, no-op prices, missing credentials, missing product context, recurring Price context, and cross-currency changes before mutating app state."},"blockers":["Requires server-side Stripe credentials and an existing one-time shop product Stripe Price mapping to supply the Stripe Product context."],"relatedIssues":["#612","#671","#799","#1052","#1681","#1684"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, raw Stripe Price ids, raw Stripe Product ids, checkout sessions, payment intents, customer ids, buyer identifiers, private download URLs, or fulfillment internals.","Model-visible responses may show redacted Stripe Price and Product ids only; use the authenticated admin catalog for raw ids.","This wrapper updates only store_items.price_cents and store_items.stripe_price_id; product copy, inventory, fulfillment, raw URLs, checkout sessions, orders, refunds, and credits remain out of scope."]},{"id":"creator.commerce.stripe-price-select","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Select or clear an already-known Stripe Price mapping for one lesson/coaching offering through a confirmed, audited write envelope. Replacement Stripe Price creation uses a separate confirmed wrapper; broader product/tier metadata writes remain blocked.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed lesson Stripe Price selection wrapper for one lesson offering."},{"href":"https://docs.fanful.net/api/admin/stripe-catalog","method":"GET","auth":"artist-admin-or-approved-automation","description":"Authenticated Stripe catalog readiness and app-state mapping contract."}],"futureToolName":"fanful_creator_lesson_stripe_price_select","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm offering id, selected or cleared Stripe Price mapping, stale-state guard, amount/currency compatibility, idempotency key, audit correlation id, and rollback path."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted Stripe Price mapping summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + lesson-offering-id + selected-stripe-price-id + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + lesson-offering-id","expectation":"Reject duplicate idempotency keys, stale offering state, no-op selections, and unknown Stripe Price ids before mutating."},"blockers":["Selected Stripe Price ids must already appear in Laurel app-state Stripe catalog references."],"relatedIssues":["#534","#799","#925","#926","#1052","#1053","#1057","#1083"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, checkout sessions, payment intents, customer ids, subscriptions, student contact details, meeting URLs, or private booking notes.","Model-visible responses may show redacted Stripe Price ids only; use the authenticated admin catalog for raw ids."]},{"id":"creator.commerce.stripe-price-create","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Create one replacement immutable Stripe Price for one lesson/coaching offering, then select it through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed lesson Stripe Price creation wrapper for one lesson offering."},{"href":"https://docs.fanful.net/api/admin/stripe-catalog","method":"GET","auth":"artist-admin-or-approved-automation","description":"Authenticated Stripe catalog readiness and app-state mapping contract."}],"futureToolName":"fanful_creator_lesson_stripe_price_create","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm offering id, new amount/currency, existing product context, stale-state guard, idempotency key, audit correlation id, and rollback path before creating and selecting a replacement Stripe Price."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted Stripe Price creation summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + lesson-offering-id + new-amount + currency + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + lesson-offering-id","expectation":"Reject duplicate idempotency keys, stale offering state, no-op prices, missing credentials, missing product context, and cross-currency changes before mutating app state."},"blockers":["Requires server-side Stripe credentials and an existing lesson Stripe Price mapping to supply the Stripe Product context."],"relatedIssues":["#534","#799","#925","#926","#1052","#1053","#1057","#1083"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, raw Stripe Price ids, raw Stripe Product ids, checkout sessions, payment intents, customer ids, subscriptions, student contact details, meeting URLs, or private booking notes.","Model-visible responses may show redacted Stripe Price and Product ids only; use the authenticated admin catalog for raw ids.","This wrapper updates only lesson_offerings.price_cents and lesson_offerings.stripe_price_id; shop products, tiers, entitlements, credits, bundles, cancellation, and refund policy remain out of scope."]},{"id":"creator.commerce.membership-stripe-price-select","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Select or clear an already-known Stripe Price mapping for one membership tier through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed membership-tier Stripe Price selection wrapper."},{"href":"https://docs.fanful.net/api/admin/stripe-catalog","method":"GET","auth":"artist-admin-or-approved-automation","description":"Authenticated Stripe catalog readiness and app-state mapping contract."}],"futureToolName":"fanful_creator_membership_stripe_price_select","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm membership tier id, selected or cleared Stripe Price mapping, stale-state guard, amount/currency compatibility, idempotency key, audit correlation id, and rollback path."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted Stripe Price mapping summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + membership-tier-id + selected-stripe-price-id + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + membership-tier-id","expectation":"Reject duplicate idempotency keys, stale tier state, no-op selections, and unknown Stripe Price ids before mutating."},"blockers":["Selected Stripe Price ids must already appear in Laurel app-state Stripe catalog references."],"relatedIssues":["#534","#925","#926","#1052","#1186"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, raw Stripe Price ids, checkout sessions, payment intents, customer ids, subscriptions, or entitlement internals.","Model-visible responses may show redacted Stripe Price ids only; use the authenticated admin catalog for raw ids."]},{"id":"creator.commerce.membership-stripe-price-create","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Create one replacement immutable recurring Stripe Price for one membership tier, then select it through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed membership-tier Stripe Price creation wrapper."},{"href":"https://docs.fanful.net/api/admin/stripe-catalog","method":"GET","auth":"artist-admin-or-approved-automation","description":"Authenticated Stripe catalog readiness and app-state mapping contract."}],"futureToolName":"fanful_creator_membership_stripe_price_create","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm membership tier id, new monthly amount/currency, existing product context, stale-state guard, idempotency key, audit correlation id, and rollback path before creating and selecting a replacement recurring Stripe Price."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted Stripe Price creation summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + membership-tier-id + new-monthly-amount + currency + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + membership-tier-id","expectation":"Reject duplicate idempotency keys, stale tier state, no-op prices, missing credentials, missing product context, and cross-currency changes before mutating app state."},"blockers":["Requires server-side Stripe credentials and an existing membership Stripe Price mapping to supply the Stripe Product context."],"relatedIssues":["#534","#925","#926","#1052","#1186"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, raw Stripe Price ids, raw Stripe Product ids, checkout sessions, payment intents, customer ids, subscriptions, or entitlement internals.","Model-visible responses may show redacted Stripe Price and Product ids only; use the authenticated admin catalog for raw ids.","This wrapper updates only membership_tiers.monthly_amount_cents and membership_tiers.stripe_price_id; tier lifecycle, entitlement metadata, checkout policy, cancellation, and refunds remain out of scope."]},{"id":"creator.commerce.membership-tier-create","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Create one inactive membership tier with public profile, monthly amount, sort order, and benefits through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed inactive membership-tier creation wrapper."}],"futureToolName":"fanful_creator_membership_tier_create","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm new tier id, profile fields, monthly amount/currency, inactive initial state, ordered benefits, observed catalog tier ids, idempotency key, audit correlation id, and rollback path."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted tier profile and benefit summary, observed catalog ids, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + membership-tier-id + observed catalog tier ids + profile-benefits"},"rateLimit":{"scope":"artist-admin-or-automation + membership-tier-id","expectation":"Reject duplicate idempotency keys, duplicate tier ids, stale catalog reads, duplicate benefits, non-USD currency, and active-at-create requests before mutating."},"blockers":[],"relatedIssues":["#534","#1052","#1260","#1371","#1386"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, raw Stripe Price ids, checkout sessions, payment intents, customer ids, subscriptions, listener membership ids, or payment identifiers.","This wrapper inserts membership_tiers and membership_tier_benefits only; new tiers start inactive until Stripe Price mapping and restore are confirmed separately.","This wrapper never creates Stripe Prices, selects stripe_price_id, grants memberships, changes checkout policy, or writes protected-surface entitlement metadata."]},{"id":"creator.commerce.membership-tier-update","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Update one membership tier's public profile and benefit copy through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed membership-tier profile and benefit copy write."}],"futureToolName":"fanful_creator_membership_tier_update","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm membership tier id, profile fields, ordered benefits, stale-state guard, idempotency key, audit correlation id, and rollback path."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted tier profile and benefit summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + membership-tier-id + profile-benefits + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + membership-tier-id","expectation":"Reject duplicate idempotency keys, stale tier state, duplicate benefits, and no-op updates before mutating."},"blockers":[],"relatedIssues":["#534","#1052","#1260","#1371"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, raw Stripe Price ids, checkout sessions, payment intents, customer ids, subscriptions, listener membership ids, or payment identifiers.","This wrapper updates only membership_tiers.name, membership_tiers.description, membership_tiers.sort_order, and membership_tier_benefits.","This wrapper never creates tiers, changes monthly_amount_cents, changes stripe_price_id, or writes protected-surface entitlement metadata."]},{"id":"creator.commerce.membership-tier-archive-state","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Archive or restore one membership tier through a confirmed, audited write envelope while preserving existing memberships.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed membership-tier archive/restore active-state write."}],"futureToolName":"fanful_creator_membership_tier_archive_state","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm membership tier id, requested active state, stale-state guard, idempotency key, audit correlation id, active member impact, and rollback path."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, redacted tier active-state summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + membership-tier-id + archive-state + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + membership-tier-id","expectation":"Reject duplicate idempotency keys, stale tier state, no-op archive/restore requests, and archiving the last active public tier before mutating."},"blockers":[],"relatedIssues":["#534","#1052","#1260","#1371"],"modelVisibleBoundaries":["Do not expose raw Stripe secret keys, raw Stripe Price ids, checkout sessions, payment intents, customer ids, subscriptions, listener membership ids, or payment identifiers.","This wrapper updates only membership_tiers.active; existing membership entitlement history is preserved.","This wrapper never cancels subscriptions, refunds payments, creates tiers, changes prices, changes stripe_price_id, or writes protected-surface entitlement metadata."]},{"id":"creator.commerce.entitlement-metadata-update","domain":"commerce","audiences":["creator","operator"],"status":"ready","summary":"Update one protected community channel's membership-tier access metadata through a confirmed, audited write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"GET","auth":"guest","description":"Agent-safe creator commerce manifest."},{"href":"https://docs.fanful.net/api/agent/creator-commerce","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed protected-surface entitlement metadata write."},{"href":"https://docs.fanful.net/api/agent/community-chat","method":"GET","auth":"guest","description":"Agent-safe community channel access metadata read."}],"futureToolName":"fanful_creator_entitlement_metadata_update","confirmation":{"required":true,"kind":"creator-commerce","prompt":"Confirm community channel id, membership access mode, tier ids, stale-state guard, idempotency key, audit correlation id, and affected fan surfaces before changing protected-surface metadata."},"audit":{"required":true,"currentRecord":"creator_commerce_agent_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, before/after channel access summaries, idempotency key, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + community-channel-id + access metadata + observed updated_at"},"rateLimit":{"scope":"artist-admin-or-automation + community-channel-id","expectation":"Reject duplicate idempotency keys, stale channel state, default #general changes, no-op access metadata, and unsupported entitlement-group writes before mutating."},"blockers":["This executable slice is limited to community channel tier-access metadata; lesson credits, paid rooms, entitlement groups, membership revocation, and active checkout readiness for newly created tiers remain separate blockers."],"relatedIssues":["#534","#560","#851","#1371","#1386"],"modelVisibleBoundaries":["Do not expose listener membership ids, payment identifiers, Stripe ids, private member directories, hidden messages, or notification recipient lists.","This wrapper updates only community_chat_channels.access_mode, access_tier_ids_json, and access_entitlement_group_ids_json.","This wrapper never creates tiers, changes prices, grants lesson credits, changes paid-room access, resolves entitlement groups, revokes memberships, or edits chat messages."]},{"id":"creator.live.schedule-and-status","domain":"live","audiences":["creator","operator"],"status":"ready","summary":"Preview live-room schedule/create/update payloads, execute confirmed new event creates and existing-event schedule updates, preview status transitions, and execute confirmed status transitions through the shared agent write envelope.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/live-controls","method":"GET","auth":"guest","description":"Agent-safe live-controls manifest."},{"href":"https://docs.fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Non-mutating live schedule/create/update and status transition preview actions."},{"href":"https://docs.fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed live schedule and status write wrappers for confirm_live_event_schedule_create, confirm_live_event_schedule_change, and confirm_live_event_status_change with agent-write-envelope.v1. Schedule writes can also persist preference-gated notification-center rows and attempt APNs/FCM push delivery when fanNotification is confirmed."},{"href":"https://docs.fanful.net/api/admin/live-events","method":"POST","auth":"artist-admin-or-approved-automation","description":"Existing live-event create route."},{"href":"https://docs.fanful.net/api/admin/live-events","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Existing live-event update route."},{"href":"https://docs.fanful.net/api/admin/live-events/status","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Dedicated status transition route for go-live/end/cancel."}],"futureToolName":"fanful_creator_live_status_update","confirmation":{"required":true,"kind":"go-live","prompt":"Confirm event id, next status, audience visibility, chat settings, stream readiness, and rollback/cancel path."},"audit":{"required":true,"currentRecord":"live_event_admin_actions","requiredBeforeExecutable":null,"attribution":"Attribute writes to the artist admin or approved automation identity, including agent client, tool name, idempotency key, audit correlation id, operator reason, and fan-notification summary when requested."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + event-id/proposed schedule + proposed mutation + observed updated_at when updating"},"rateLimit":{"scope":"artist-admin-or-automation + event-id/proposed schedule","expectation":"Reject duplicate idempotency keys and stale preview guards before mutating live schedule or status."},"blockers":[],"relatedIssues":["#608","#656","#672","#704","#757","#800","#920","#960","#998","#1012","#1549","#1657"],"modelVisibleBoundaries":["Do not expose raw stream URLs, Cloudflare Stream customer codes, socket tokens, private invite links, or external fallback URLs.","Use preview_live_event_schedule_change before confirm_live_event_schedule_create or confirm_live_event_schedule_change; fanful_creator_live_schedule_create only creates live_events and optional notification-center rows, while fanful_creator_live_schedule_update only updates existing live events and optional notification-center rows.","When fanNotification is requested (#1657), confirmed envelopes must carry matching fanNotificationAudience, fanNotificationTitle, fanNotificationBody, and fanNotificationTimeZone target attributes. Confirmed writes create in-app notification-center rows first, then attempt APNs/FCM push delivery for recipients with live push enabled and active devices. Raw push tokens and device ids are never model-visible; production delivery reports provider-not-configured until server credentials are installed.","Use preview_live_event_status_change first, then confirm_live_event_status_change with the exact shared-envelope confirmation text, observed updated_at, idempotency key, audit correlation id, and reason."]},{"id":"creator.live.moderation-and-stage","domain":"live","audiences":["creator","operator"],"status":"ready","summary":"Execute confirmed embedded-room roster, co-host, and stage changes; broader live/community message moderation remains route-scoped until separate wrappers land.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/embedded-rooms","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed embedded-room roster/stage write wrapper with agent-write-envelope.v1."},{"href":"https://docs.fanful.net/api/admin/live-events/messages","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Existing live-message moderation route."},{"href":"https://docs.fanful.net/api/admin/community-chat/messages","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Existing community-chat moderation route."},{"href":"https://docs.fanful.net/api/admin/embedded-rooms/[roomId]/participants","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Existing embedded-room roster route."}],"futureToolName":"fanful_creator_embedded_room_roster_update","confirmation":{"required":true,"kind":"moderation","prompt":"Confirm room, participant, roster/stage action, reason, and whether the action affects visible access or presenter status."},"audit":{"required":true,"currentRecord":"embedded_room_admin_actions + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute confirmed roster/stage writes to the artist admin or approved automation identity, including agent client, tool name, idempotency key, audit correlation id, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"artist-id + room-id + participant-id + roster mutation + observed updated_at when updating"},"rateLimit":{"scope":"artist-admin-or-automation + room/channel","expectation":"Reject duplicate idempotency keys, stale participant state, and no-op roster/stage toggles before mutating."},"blockers":[],"relatedIssues":["#505","#524","#608","#656","#672","#1028"],"modelVisibleBoundaries":["fanful_creator_embedded_room_roster_update only changes one embedded-room participant role/status/display name at a time; use separate future wrappers for live/community message moderation.","Do not expose private invite links, raw RealtimeKit tokens, media participant ids, hidden moderation notes, or listener user ids."]},{"id":"member.ideas.submit-and-vote","domain":"ideas","audiences":["listener","fan"],"status":"ready","summary":"Submit and vote on visible member ideas with signed-in/scoped-listener attribution and public-content confirmation.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/idea-board","method":"GET","auth":"optional-session","description":"Agent-safe idea-board manifest."},{"href":"https://docs.fanful.net/api/agent/idea-board","method":"POST","auth":"confirmed-listener","description":"Confirmed agent submit/vote wrapper."},{"href":"https://docs.fanful.net/api/ideas","method":"GET","auth":"guest","description":"Existing public idea list route."},{"href":"https://docs.fanful.net/api/ideas","method":"POST","auth":"signed-in-listener","description":"Existing idea submission route."},{"href":"https://docs.fanful.net/api/ideas/votes","method":"POST","auth":"signed-in-listener","description":"Existing idea voting route."}],"futureToolName":"fanful_member_idea_board_manage","confirmation":{"required":true,"kind":"idea-board","prompt":"Confirm public idea text or vote target before writing."},"audit":{"required":true,"currentRecord":"idea_posts/idea_votes + analytics_events + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute listener writes to the signed-in listener or scoped listener grant plus the calling agent client, idempotency key, audit correlation id, and exact confirmation evidence."},"idempotency":{"requiredForWrites":true,"keyScope":"actor-id + idea-id-or-content hash + action"},"rateLimit":{"scope":"signed-in actor","expectation":"Prevent repeated votes/submissions and preserve existing abuse controls."},"blockers":[],"relatedIssues":["#599","#602","#608","#1702"],"modelVisibleBoundaries":["Do not expose private admin notes or raw voter/listener ids.","This contract covers member submit/vote only; creator review, board settings, featuring, hiding, and status changes remain separate contract-only operations."]},{"id":"creator.ideas.moderate","domain":"ideas","audiences":["creator","operator"],"status":"ready","summary":"Resolve member idea-board reports and duplicate suggestions with confirmed artist-admin or approved automation attribution.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/idea-board","method":"GET","auth":"optional-session","description":"Agent-safe idea-board manifest."},{"href":"https://docs.fanful.net/api/agent/idea-board","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed agent moderation wrapper for duplicate, archive, restore, and private-note actions."},{"href":"https://docs.fanful.net/api/admin/ideas/moderation","method":"POST","auth":"artist-admin-or-approved-automation","description":"Existing admin moderation route."},{"href":"https://docs.fanful.net/api/ideas/reports","method":"POST","auth":"signed-in-listener","description":"Existing listener report route."}],"futureToolName":"fanful_creator_idea_moderation_manage","confirmation":{"required":true,"kind":"moderation","prompt":"Confirm idea title, moderation action, public consequence, stale-state updated_at value when required, idempotency key, audit correlation id, and operator reason."},"audit":{"required":true,"currentRecord":"idea_moderation_events + idea_moderation_reports/idea_duplicate_links/idea_private_admin_notes + agent_write_idempotency_keys","requiredBeforeExecutable":null,"attribution":"Attribute moderation writes to the artist admin or approved automation identity, including agent client, exact target summary, idempotency key, audit correlation id, and operator reason."},"idempotency":{"requiredForWrites":true,"keyScope":"admin-or-automation + idea-id + moderation action + observed updated_at when required"},"rateLimit":{"scope":"artist-admin-or-automation + idea-board moderation action","expectation":"Reject duplicate idempotency keys, unauthorized callers, stale destructive moderation state, missing confirmation, and ambiguous duplicate targets before mutating."},"blockers":[],"relatedIssues":["#527","#1894","#1897"],"modelVisibleBoundaries":["Guest and listener callers never receive open report queues, private admin-note bodies, or reviewer identifiers.","Accepted duplicate/archive/restore actions can change public idea state and must repeat the exact public consequence before execution.","Private note writes are admin-only context; do not quote private note details into public agent responses."]},{"id":"platform.admin.settings","domain":"platform","audiences":["creator","operator"],"status":"deferred","summary":"Manage platform-level settings such as domains, artist workspace configuration, and future multi-artist admin policy.","existingEndpoints":[{"href":"https://docs.fanful.net/api/agent/domains","method":"GET","auth":"guest","description":"Agent-readable domain manifest."},{"href":"https://docs.fanful.net/api/admin/domains","method":"POST","auth":"platform-owner","description":"Existing domain admin action route."},{"href":"https://docs.fanful.net/api/admin/domain-purchases","method":"POST","auth":"platform-owner","description":"Existing domain purchase route."}],"futureToolName":"fanful_platform_settings_manage","confirmation":{"required":true,"kind":"platform-setting","prompt":"Confirm domain/workspace setting, billing/registrar impact, and rollback path before writing."},"audit":{"required":true,"currentRecord":"domain admin records","requiredBeforeExecutable":"Platform-owner action log with external provider response summaries.","attribution":"Attribute platform writes to Mark/platform-owner or an explicitly approved automation identity."},"idempotency":{"requiredForWrites":true,"keyScope":"platform-owner + provider object + requested state"},"rateLimit":{"scope":"platform-owner","expectation":"Throttle provider-mutating calls and require explicit billing/registrar confirmation."},"blockers":["Keep registrar/domain purchase agent writes parked behind #729 and #733."],"relatedIssues":["#608","#729","#733"],"modelVisibleBoundaries":["Do not expose registrar tokens, provider order ids, payment details, or private DNS/provider metadata."]}],"nextBuildOrder":[{"issue":"#810","task":"Use the scoped delegated-grant model as the canonical private-agent auth contract."},{"issue":"#811","task":"Shipped: store and revoke scoped agent grants before private MCP/ChatGPT reads depend on them."},{"issue":"#812","task":"Shipped: resolve scoped principals in /mcp and /api/agent/*."},{"issue":"#818","task":"Shipped: approve scoped grants and exchange one-time codes for bearer tokens."},{"issue":"#819","task":"Shipped: let users inspect and revoke scoped agent grants from account settings."},{"issue":"#608","task":"Keep this manifest as the canonical cross-surface contract list and wire MCP/CLI clients to it."},{"issue":"#786","task":"Use the shared validation endpoint before any MCP, CLI, or ChatGPT mutating tool executes."},{"issue":"#757","task":"Shipped: atomic live-event audit writes keep status changes and audit rows together."},{"issue":"#800","task":"Shipped: use the non-mutating live status preview before confirmed writes."},{"issue":"#920","task":"Shipped: execute confirmed live status writes through the shared write envelope with stale-state, idempotency, and audit correlation."},{"issue":"#998","task":"Shipped: execute confirmed existing-event live schedule writes through the shared write envelope with stale-state, idempotency, and audit correlation."},{"issue":"#1012","task":"Shipped: execute confirmed new live-event creation through the shared write envelope with idempotency, blocker checks, and audit correlation."},{"issue":"#612","task":"Define checkout/link-cli purchase support using the confirmed-listener envelope."},{"issue":"#986","task":"Expose support-only listener checkout starts with persisted intents, idempotency, audit attribution, and redacted responses."},{"issue":"#611","task":"Build the CLI on these same MCP resources and tools instead of adding a separate contract."}]}