{"result":{"depiction_url":null,"edges":{"in_module":{"objects":[{"created":"2026-10-22T10:28:13Z","object_id":{"id":3105,"is_a":["text","documentation","reference","module"],"name":"doc_external_9_mod_paysub","title":"mod_paysub","uri":"https:\/\/zotonic.com\/id\/3105"},"seq":1}],"predicate":{"id":333,"is_a":["meta","predicate"],"name":"in_module","title":{"_type":"trans","tr":{"en":"In module"}},"uri":"https:\/\/zotonic.com\/id\/in_module"}},"subject":{"objects":[{"created":"2026-10-22T10:28:13Z","object_id":{"id":2555,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_reference","title":"Reference","uri":"https:\/\/zotonic.com\/id\/2555"},"seq":1},{"created":"2026-10-22T10:28:13Z","object_id":{"id":2563,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_frontend_developer","title":"Frontend developer","uri":"https:\/\/zotonic.com\/id\/2563"},"seq":2},{"created":"2026-10-22T10:28:13Z","object_id":{"id":2564,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_backend_developer","title":"Backend developer","uri":"https:\/\/zotonic.com\/id\/2564"},"seq":3},{"created":"2026-10-22T10:28:13Z","object_id":{"id":2589,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_identity_and_accounts","title":"Identity and accounts","uri":"https:\/\/zotonic.com\/id\/2589"},"seq":4},{"created":"2026-10-22T10:28:13Z","object_id":{"id":2592,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_authorization_and_access_control","title":"Authorization and access control","uri":"https:\/\/zotonic.com\/id\/2592"},"seq":5},{"created":"2026-10-22T10:28:13Z","object_id":{"id":2599,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_api_and_integration","title":"API and integration","uri":"https:\/\/zotonic.com\/id\/2599"},"seq":6},{"created":"2026-10-22T10:28:13Z","object_id":{"id":2625,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_model","title":"Model","uri":"https:\/\/zotonic.com\/id\/2625"},"seq":7}],"predicate":{"id":308,"is_a":["meta","predicate"],"name":"subject","title":{"_type":"trans","tr":{"en":"Keyword"}},"uri":"http:\/\/purl.org\/dc\/elements\/1.1\/subject"}}},"id":3107,"is_a":["text","documentation","reference","model"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/3107"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_external_9_m_paysub","page_url":{"en":"https:\/\/zotonic.com\/docs\/3107\/m_paysub","x-default":"https:\/\/zotonic.com\/docs\/3107\/m_paysub"},"preview_url":null,"resource":{"version":17,"pivot_location_lat":null,"title":"m_paysub","is_authoritative":true,"body":"<p>Access local payment and subscription records, membership state and provider\ncustomer portals. Database records generally use binary map keys. Template\npaths return their values through <code>m_get\/3<\/code> as <code>{ok, {Value, Rest}}<\/code>; failed\nlookups can return <code>{error, enoent}<\/code> or <code>{error, eacces}<\/code>.<\/p>\n<h2>Common template paths<\/h2>\n<table class=\"table\"><thead><tr><th>Path under <code>m.paysub<\/code><\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td><code>is_allowed_paysub<\/code><\/td><td>Administrator or <code>use mod_paysub<\/code> permission.<\/td><\/tr><tr><td><code>is_subscriber<\/code> \/ <code>is_subscriber[id]<\/code><\/td><td>Membership of the current or specified resource, including main-contact relationships.<\/td><\/tr><tr><td><code>is_unpaid_access<\/code><\/td><td>Current unpaid-access configuration.<\/td><\/tr><tr><td><code>rsc[id].subscriptions.list<\/code> \/ <code>.count<\/code><\/td><td>Subscription records or count.<\/td><\/tr><tr><td><code>rsc[id].invoices.list<\/code> \/ <code>.count<\/code><\/td><td>Invoice records or count.<\/td><\/tr><tr><td><code>rsc[id].payments.list<\/code> \/ <code>.count<\/code><\/td><td>Payment records or count.<\/td><\/tr><tr><td><code>subscription[id]<\/code>, <code>invoice[id]<\/code>, <code>payment[id]<\/code><\/td><td>One record by local numeric ID.<\/td><\/tr><tr><td><code>product[id]<\/code><\/td><td>One product by local numeric ID.<\/td><\/tr><tr><td><code>products[psp]<\/code>, <code>prices[psp]<\/code><\/td><td>Provider products or prices.<\/td><\/tr><tr><td><code>price_info[psp][price_id]<\/code><\/td><td>Selected display fields for a provider price.<\/td><\/tr><tr><td><code>checkout.status[checkout_nr]<\/code><\/td><td>Checkout status map.<\/td><\/tr><tr><td><code>subscriptions.states<\/code><\/td><td>Supported status names.<\/td><\/tr><tr><td><code>subscriptions.user_groups<\/code>, <code>.psps<\/code>, <code>.products<\/code>, <code>.prices<\/code><\/td><td>Subscription filter choices.<\/td><\/tr><tr><td><code>overview_by.user_group<\/code><\/td><td>Administrative membership overview.<\/td><\/tr><\/tbody><\/table>\n<p>For example:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-django\">{% for sub in m.paysub.rsc[id].subscriptions.list %}\n    {{ sub.status|escape }}\n{% endfor %}\n<\/code><\/pre>\n<p>The resource list\/count paths allow a Paysub administrator, the resource&#39;s\nown user, or its current main contact. Single invoice, subscription and\npayment paths restrict non-administrators to their own linked records.\nProducts and the user-group overview require Paysub management permission;\nprovider product\/price lists also accept <code>use mod_admin<\/code> permission.\n<code>price_info<\/code> and subscription filter choices have no equivalent management\ngate. <code>is_subscriber<\/code> checks resource visibility and returns false for\nunknown or invisible resources.<\/p>\n<h2>Checkout and customer portal<\/h2>\n<p><code>checkout.status[checkout_nr]<\/code> looks up a checkout by its checkout number;\nit does not require the current user to own the checkout. Returned fields\ninclude status, payment status, resource and requestor IDs and stored checkout\nproperties. Treat checkout numbers as private flow identifiers.<\/p>\n<p><code>is_customer_portal.stripe[id]<\/code> tests customer-portal availability and access.\n<code>customer_portal_session_url.stripe[id]<\/code> creates a provider session and returns\nits URL; omitting the ID uses the current user. This lookup performs an\nexternal request. <code>customer_url.stripe[id]<\/code> returns an administrative provider\nURL and requires both resource visibility and Paysub management permission.<\/p>\n<h2>Erlang interface<\/h2>\n<pre class=\"notranslate\"><code class=\"notranslate language-erlang\">m_paysub:is_subscriber(UserId, Context).\nm_paysub:user_subscriptions(UserId, Context).\n<\/code><\/pre>\n<p>The first call returns a boolean. The second returns <code>{ok, Subscriptions}<\/code>\nor an error and is a direct database helper: callers must authorize it.\nDo not assume that exported synchronization, lookup or mutation helpers\nrepeat the template path ACL checks.<\/p>\n<p><code>active_states\/0<\/code> includes <code>incomplete<\/code>, <code>trialing<\/code>, <code>active<\/code> and <code>past_due<\/code>.\n<code>access_states\/1<\/code> additionally includes <code>incomplete_expired<\/code> and <code>unpaid<\/code>\nwhen configured. Membership checks and group derivation use these states;\nthey do not apply the end-date filtering of some administrative searches.<\/p>","slug":"m_paysub","doc_module_config":[],"is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"doc_source_hash":"79d1d1c6ed6d302cdd4cf81ad9f37fe25e1d06158ffb86d2cc968b3ac365f2e6","is_featured":false,"content_group_id":{"id":2551,"is_a":["meta","content_group"],"name":"content_group_imported_docs","title":"Imported documentation","uri":"https:\/\/zotonic.com\/id\/content_group_imported_docs"},"external_module_id":{"id":9,"is_a":[],"name":null,"title":null,"uri":"https:\/\/zotonic.com\/id\/9"},"git_url":"https:\/\/github.com\/zotonic\/zotonic_mod_paysub.git","category_id":{"id":322,"is_a":["meta","category"],"name":"model","title":"Models","uri":"https:\/\/test.zotonic.com\/id\/322"},"doc_source_path":".\/src\/models\/m_paysub.erl","publication_start":"2026-10-22T10:28:13Z","github_url":"https:\/\/github.com\/zotonic\/zotonic_mod_paysub.git","pivot_location_lng":null,"doc_source_kind":"external","name":"doc_external_9_m_paysub","is_unfindable":false,"is_published":true,"pivot_geocode":null,"external_module_title":"Paid Subscriptions","created":"2026-10-22T10:28:13Z","uri":null,"doc_status":"current","is_dependent":false,"is_external_module":true,"publication_end":"9999-06-01T00:00:00Z","modifier_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"privacy":0,"doc_source_commit":"3a4ee4d7434205778e4318c0c2e1576884e5678b","creator_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"modified":"2026-10-22T10:28:14Z","title_slug":"m_paysub"},"uri":"https:\/\/zotonic.com\/id\/3107","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/3107"}},"status":"ok"}