[{"data":1,"prerenderedAt":3244},["ShallowReactive",2],{"navigation_docs":3,"-modules-commerce-payments":587,"-modules-commerce-payments-surround":3239},[4,50,155,441,504],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":49},"Get Started","i-lucide-rocket","\u002Fget-started","1.get-started",[10,15,20,25,30,35,40,45],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fget-started\u002Fintroduction","1.get-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fget-started\u002Finstallation","1.get-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Project structure","\u002Fget-started\u002Fproject-structure","1.get-started\u002F3.project-structure","i-lucide-folder-tree",{"title":26,"path":27,"stem":28,"icon":29},"Configuration","\u002Fget-started\u002Fconfiguration","1.get-started\u002F4.configuration","i-lucide-settings",{"title":31,"path":32,"stem":33,"icon":34},"Authentication","\u002Fget-started\u002Fauthentication","1.get-started\u002F5.authentication","i-lucide-lock",{"title":36,"path":37,"stem":38,"icon":39},"Adding modules","\u002Fget-started\u002Fadding-modules","1.get-started\u002F6.adding-modules","i-lucide-puzzle",{"title":41,"path":42,"stem":43,"icon":44},"Database","\u002Fget-started\u002Fdatabase","1.get-started\u002F7.database","i-lucide-database",{"title":46,"path":47,"stem":48,"icon":6},"Deployment","\u002Fget-started\u002Fdeployment","1.get-started\u002F8.deployment",false,{"title":51,"icon":52,"path":53,"stem":54,"children":55,"page":49},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[56,90,115,125],{"title":57,"icon":49,"path":58,"stem":59,"children":60,"page":49},"Concepts","\u002Fguide\u002Fconcepts","2.guide\u002F1.concepts",[61,66,71,76,80,85],{"title":62,"path":63,"stem":64,"icon":65},"Architecture","\u002Fguide\u002Fconcepts\u002Farchitecture","2.guide\u002F1.concepts\u002F1.architecture","i-lucide-blocks",{"title":67,"path":68,"stem":69,"icon":70},"Access control","\u002Fguide\u002Fconcepts\u002Fauth-and-scopes","2.guide\u002F1.concepts\u002F2.auth-and-scopes","i-lucide-shield-check",{"title":72,"path":73,"stem":74,"icon":75},"Extension points","\u002Fguide\u002Fconcepts\u002Fextension-points","2.guide\u002F1.concepts\u002F3.extension-points","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":44},"Database extensions","\u002Fguide\u002Fconcepts\u002Fdatabase-extensions","2.guide\u002F1.concepts\u002F4.database-extensions",{"title":81,"path":82,"stem":83,"icon":84},"Identity","\u002Fguide\u002Fconcepts\u002Fidentity","2.guide\u002F1.concepts\u002F5.identity","i-lucide-fingerprint",{"title":86,"path":87,"stem":88,"icon":89},"Glossary","\u002Fguide\u002Fconcepts\u002Fglossary","2.guide\u002F1.concepts\u002F6.glossary","i-lucide-book-a",{"title":91,"icon":49,"path":92,"stem":93,"children":94,"page":49},"UX patterns","\u002Fguide\u002Fux-patterns","2.guide\u002F2.ux-patterns",[95,100,105,110],{"title":96,"path":97,"stem":98,"icon":99},"Layouts and navigation","\u002Fguide\u002Fux-patterns\u002Flayouts-and-navigation","2.guide\u002F2.ux-patterns\u002F1.layouts-and-navigation","i-lucide-layout-template",{"title":101,"path":102,"stem":103,"icon":104},"Pages","\u002Fguide\u002Fux-patterns\u002Fpages","2.guide\u002F2.ux-patterns\u002F2.pages","i-lucide-table",{"title":106,"path":107,"stem":108,"icon":109},"Forms and actions","\u002Fguide\u002Fux-patterns\u002Fforms-and-actions","2.guide\u002F2.ux-patterns\u002F3.forms-and-actions","i-lucide-square-pen",{"title":111,"path":112,"stem":113,"icon":114},"Text and formatting","\u002Fguide\u002Fux-patterns\u002Ftext-and-formatting","2.guide\u002F2.ux-patterns\u002F4.text-and-formatting","i-lucide-type",{"title":116,"icon":49,"path":117,"stem":118,"children":119,"page":49},"Best practices","\u002Fguide\u002Fbest-practices","2.guide\u002F3.best-practices",[120],{"title":121,"path":122,"stem":123,"icon":124},"HTTP routes","\u002Fguide\u002Fbest-practices\u002Fhttp-routes","2.guide\u002F3.best-practices\u002F1.http-routes","i-lucide-route",{"title":126,"icon":49,"path":127,"stem":128,"children":129,"page":49},"Going further","\u002Fguide\u002Fgoing-further","2.guide\u002F4.going-further",[130,135,140,145,150],{"title":131,"path":132,"stem":133,"icon":134},"Use your own OAuth server","\u002Fguide\u002Fgoing-further\u002Fown-oauth-server","2.guide\u002F4.going-further\u002F1.own-oauth-server","i-lucide-key-round",{"title":136,"path":137,"stem":138,"icon":139},"Create an OAuth application","\u002Fguide\u002Fgoing-further\u002Foauth-application","2.guide\u002F4.going-further\u002F2.oauth-application","i-lucide-app-window",{"title":141,"path":142,"stem":143,"icon":144},"Signing keys","\u002Fguide\u002Fgoing-further\u002Fsigning-keys","2.guide\u002F4.going-further\u002F3.signing-keys","i-lucide-key-square",{"title":146,"path":147,"stem":148,"icon":149},"Stripe setup","\u002Fguide\u002Fgoing-further\u002Fstripe-setup","2.guide\u002F4.going-further\u002F4.stripe-setup","i-lucide-credit-card",{"title":151,"path":152,"stem":153,"icon":154},"Migrate to the permission model","\u002Fguide\u002Fgoing-further\u002Fmigrate-access-control","2.guide\u002F4.going-further\u002F5.migrate-access-control","i-lucide-arrow-right-left",{"title":156,"icon":157,"path":158,"stem":159,"children":160},"Modules","i-lucide-boxes","\u002Fmodules","3.modules",[161,163,244,273,320,375],{"title":156,"path":158,"stem":162},"3.modules\u002Findex",{"title":81,"icon":49,"path":164,"stem":165,"children":166,"page":49},"\u002Fmodules\u002Fidentity","3.modules\u002F1.identity",[167,190,194,198,220,224,240],{"title":168,"path":169,"stem":170,"children":171},"Auth","\u002Fmodules\u002Fidentity\u002Fauth","3.modules\u002F1.identity\u002F1.auth\u002Findex",[172,174,178,182,186],{"title":173,"path":169,"stem":170},"Overview",{"title":175,"path":176,"stem":177},"Server API","\u002Fmodules\u002Fidentity\u002Fauth\u002Fserver","3.modules\u002F1.identity\u002F1.auth\u002F2.server",{"title":179,"path":180,"stem":181},"Reference","\u002Fmodules\u002Fidentity\u002Fauth\u002Freference","3.modules\u002F1.identity\u002F1.auth\u002F3.reference",{"title":183,"path":184,"stem":185},"Client mode","\u002Fmodules\u002Fidentity\u002Fauth\u002Fclient-mode","3.modules\u002F1.identity\u002F1.auth\u002F4.client-mode",{"title":187,"path":188,"stem":189},"OAuth providers","\u002Fmodules\u002Fidentity\u002Fauth\u002Foauth-providers","3.modules\u002F1.identity\u002F1.auth\u002F5.oauth-providers",{"title":191,"path":192,"stem":193},"Users","\u002Fmodules\u002Fidentity\u002Fusers","3.modules\u002F1.identity\u002F2.users",{"title":195,"path":196,"stem":197},"Account","\u002Fmodules\u002Fidentity\u002Faccount","3.modules\u002F1.identity\u002F3.account",{"title":199,"path":200,"stem":201,"children":202},"Authorization","\u002Fmodules\u002Fidentity\u002Fauthorization","3.modules\u002F1.identity\u002F4.authorization\u002Findex",[203,204,208,212,216],{"title":173,"path":200,"stem":201},{"title":205,"path":206,"stem":207},"Roles and requirements","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Froles-and-requirements","3.modules\u002F1.identity\u002F4.authorization\u002F2.roles-and-requirements",{"title":209,"path":210,"stem":211},"Policies","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fpolicies","3.modules\u002F1.identity\u002F4.authorization\u002F3.policies",{"title":213,"path":214,"stem":215},"Client","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fclient","3.modules\u002F1.identity\u002F4.authorization\u002F4.client",{"title":217,"path":218,"stem":219},"Admin","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fadmin","3.modules\u002F1.identity\u002F4.authorization\u002F5.admin",{"title":221,"path":222,"stem":223},"Preferences","\u002Fmodules\u002Fidentity\u002Fpreferences","3.modules\u002F1.identity\u002F5.preferences",{"title":225,"path":226,"stem":227,"children":228},"OAuth Server","\u002Fmodules\u002Fidentity\u002Foauth-server","3.modules\u002F1.identity\u002F6.oauth-server\u002Findex",[229,230,233,237],{"title":173,"path":226,"stem":227},{"title":175,"path":231,"stem":232},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fserver","3.modules\u002F1.identity\u002F6.oauth-server\u002F2.server",{"title":234,"path":235,"stem":236},"Hooks","\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fhooks","3.modules\u002F1.identity\u002F6.oauth-server\u002F3.hooks",{"title":179,"path":238,"stem":239},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Froutes-and-clients","3.modules\u002F1.identity\u002F6.oauth-server\u002F4.routes-and-clients",{"title":241,"path":242,"stem":243},"OAuth Resource","\u002Fmodules\u002Fidentity\u002Foauth-resource","3.modules\u002F1.identity\u002F8.oauth-resource",{"title":245,"icon":49,"path":246,"stem":247,"children":248,"page":49},"Commerce","\u002Fmodules\u002Fcommerce","3.modules\u002F2.commerce",[249,253,257],{"title":250,"path":251,"stem":252},"Stripe","\u002Fmodules\u002Fcommerce\u002Fstripe","3.modules\u002F2.commerce\u002F1.stripe",{"title":254,"path":255,"stem":256},"Payments","\u002Fmodules\u002Fcommerce\u002Fpayments","3.modules\u002F2.commerce\u002F2.payments",{"title":258,"path":259,"stem":260,"children":261},"Subscriptions","\u002Fmodules\u002Fcommerce\u002Fsubscriptions","3.modules\u002F2.commerce\u002F3.subscriptions\u002Findex",[262,263,266,270],{"title":173,"path":259,"stem":260},{"title":175,"path":264,"stem":265},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fserver","3.modules\u002F2.commerce\u002F3.subscriptions\u002F2.server",{"title":267,"path":268,"stem":269},"App","\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fapp","3.modules\u002F2.commerce\u002F3.subscriptions\u002F3.app",{"title":179,"path":271,"stem":272},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Freference","3.modules\u002F2.commerce\u002F3.subscriptions\u002F4.reference",{"title":274,"icon":49,"path":275,"stem":276,"children":277,"page":49},"Features","\u002Fmodules\u002Ffeatures","3.modules\u002F3.features",[278,293,312,316],{"title":279,"path":280,"stem":281,"children":282},"Events","\u002Fmodules\u002Ffeatures\u002Fevents","3.modules\u002F3.features\u002F1.events\u002Findex",[283,284,287,290],{"title":173,"path":280,"stem":281},{"title":175,"path":285,"stem":286},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fserver","3.modules\u002F3.features\u002F1.events\u002F2.server",{"title":267,"path":288,"stem":289},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fapp","3.modules\u002F3.features\u002F1.events\u002F3.app",{"title":179,"path":291,"stem":292},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Freference","3.modules\u002F3.features\u002F1.events\u002F4.reference",{"title":294,"path":295,"stem":296,"children":297},"Forms","\u002Fmodules\u002Ffeatures\u002Fforms","3.modules\u002F3.features\u002F2.forms\u002Findex",[298,299,303,306,309],{"title":173,"path":295,"stem":296},{"title":300,"path":301,"stem":302},"Definition","\u002Fmodules\u002Ffeatures\u002Fforms\u002Fdefinition","3.modules\u002F3.features\u002F2.forms\u002F2.definition",{"title":175,"path":304,"stem":305},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fserver","3.modules\u002F3.features\u002F2.forms\u002F3.server",{"title":267,"path":307,"stem":308},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fapp","3.modules\u002F3.features\u002F2.forms\u002F4.app",{"title":179,"path":310,"stem":311},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Freference","3.modules\u002F3.features\u002F2.forms\u002F5.reference",{"title":313,"path":314,"stem":315},"Cookie Consent","\u002Fmodules\u002Ffeatures\u002Fcookie-consent","3.modules\u002F3.features\u002F3.cookie-consent",{"title":317,"path":318,"stem":319},"MCP","\u002Fmodules\u002Ffeatures\u002Fmcp","3.modules\u002F3.features\u002F4.mcp",{"title":321,"icon":49,"path":322,"stem":323,"children":324,"page":49},"Interface","\u002Fmodules\u002Finterface","3.modules\u002F4.interface",[325,350,353,357,361],{"title":326,"path":327,"stem":328,"children":329},"UI","\u002Fmodules\u002Finterface\u002Fui","3.modules\u002F4.interface\u002F1.ui\u002Findex",[330,331,335,339,343,347],{"title":173,"path":327,"stem":328},{"title":332,"path":333,"stem":334},"Page components","\u002Fmodules\u002Finterface\u002Fui\u002Fpage-components","3.modules\u002F4.interface\u002F1.ui\u002F2.page-components",{"title":336,"path":337,"stem":338},"App shell","\u002Fmodules\u002Finterface\u002Fui\u002Fapp-shell","3.modules\u002F4.interface\u002F1.ui\u002F3.app-shell",{"title":340,"path":341,"stem":342},"Form inputs","\u002Fmodules\u002Finterface\u002Fui\u002Fform-inputs","3.modules\u002F4.interface\u002F1.ui\u002F4.form-inputs",{"title":344,"path":345,"stem":346},"Composables and helpers","\u002Fmodules\u002Finterface\u002Fui\u002Fcomposables","3.modules\u002F4.interface\u002F1.ui\u002F5.composables",{"title":179,"path":348,"stem":349},"\u002Fmodules\u002Finterface\u002Fui\u002Freference","3.modules\u002F4.interface\u002F1.ui\u002F6.reference",{"title":217,"path":351,"stem":352},"\u002Fmodules\u002Finterface\u002Fadmin","3.modules\u002F4.interface\u002F2.admin",{"title":354,"path":355,"stem":356},"Menu","\u002Fmodules\u002Finterface\u002Fmenu","3.modules\u002F4.interface\u002F3.menu",{"title":358,"path":359,"stem":360},"Widget","\u002Fmodules\u002Finterface\u002Fwidget","3.modules\u002F4.interface\u002F4.widget",{"title":362,"path":363,"stem":364,"children":365},"Mobile","\u002Fmodules\u002Finterface\u002Fmobile","3.modules\u002F4.interface\u002F5.mobile\u002Findex",[366,367,371],{"title":173,"path":363,"stem":364},{"title":368,"path":369,"stem":370},"CLI and devices","\u002Fmodules\u002Finterface\u002Fmobile\u002Fcli-and-devices","3.modules\u002F4.interface\u002F5.mobile\u002F2.cli-and-devices",{"title":372,"path":373,"stem":374},"Splash screen","\u002Fmodules\u002Finterface\u002Fmobile\u002Fsplash-screen","3.modules\u002F4.interface\u002F5.mobile\u002F3.splash-screen",{"title":376,"icon":49,"path":377,"stem":378,"children":379,"page":49},"Platform","\u002Fmodules\u002Fplatform","3.modules\u002F5.platform",[380,402,406,423],{"title":381,"path":382,"stem":383,"children":384},"Module Kit","\u002Fmodules\u002Fplatform\u002Fmodule-kit","3.modules\u002F5.platform\u002F1.module-kit\u002Findex",[385,386,390,394,398],{"title":173,"path":382,"stem":383},{"title":387,"path":388,"stem":389},"Server toolkit","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fserver-toolkit","3.modules\u002F5.platform\u002F1.module-kit\u002F2.server-toolkit",{"title":391,"path":392,"stem":393},"Registries and menus","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fregistries-and-menus","3.modules\u002F5.platform\u002F1.module-kit\u002F3.registries-and-menus",{"title":395,"path":396,"stem":397},"Translations","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fi18n","3.modules\u002F5.platform\u002F1.module-kit\u002F4.i18n",{"title":399,"path":400,"stem":401},"Database helpers","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fdatabase","3.modules\u002F5.platform\u002F1.module-kit\u002F5.database",{"title":403,"path":404,"stem":405},"Notify","\u002Fmodules\u002Fplatform\u002Fnotify","3.modules\u002F5.platform\u002F2.notify",{"title":407,"path":408,"stem":409,"children":410},"Email Templates","\u002Fmodules\u002Fplatform\u002Femail-templates","3.modules\u002F5.platform\u002F3.email-templates\u002Findex",[411,412,416,419],{"title":173,"path":408,"stem":409},{"title":413,"path":414,"stem":415},"Email components","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fcomponents","3.modules\u002F5.platform\u002F3.email-templates\u002F2.components",{"title":175,"path":417,"stem":418},"\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fserver","3.modules\u002F5.platform\u002F3.email-templates\u002F3.server",{"title":420,"path":421,"stem":422},"Module emails","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fmodule-emails","3.modules\u002F5.platform\u002F3.email-templates\u002F4.module-emails",{"title":424,"path":425,"stem":426,"children":427},"Base Layer","\u002Fmodules\u002Fplatform\u002Fbase-layer","3.modules\u002F5.platform\u002F4.base-layer\u002Findex",[428,429,433,437],{"title":173,"path":425,"stem":426},{"title":430,"path":431,"stem":432},"Content collections","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcontent-collections","3.modules\u002F5.platform\u002F4.base-layer\u002F2.content-collections",{"title":434,"path":435,"stem":436},"Layouts and routing","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Flayouts-and-routing","3.modules\u002F5.platform\u002F4.base-layer\u002F3.layouts-and-routing",{"title":438,"path":439,"stem":440},"Composables and utils","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcomposables-and-utils","3.modules\u002F5.platform\u002F4.base-layer\u002F4.composables-and-utils",{"title":442,"icon":443,"path":444,"stem":445,"children":446,"page":49},"Examples","i-lucide-code-xml","\u002Fexamples","4.examples",[447,466,476],{"title":448,"icon":49,"path":449,"stem":450,"children":451,"page":49},"Starters","\u002Fexamples\u002Fstarters","4.examples\u002F1.starters",[452,456,461],{"title":453,"path":454,"stem":455,"icon":6},"Workspace starter","\u002Fexamples\u002Fstarters\u002Fworkspace","4.examples\u002F1.starters\u002F1.workspace",{"title":457,"path":458,"stem":459,"icon":460},"Mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile","4.examples\u002F1.starters\u002F2.mobile","i-lucide-smartphone",{"title":462,"path":463,"stem":464,"icon":465},"Standalone mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile-standalone","4.examples\u002F1.starters\u002F3.mobile-standalone","i-lucide-tablet-smartphone",{"title":467,"icon":49,"path":468,"stem":469,"children":470,"page":49},"Apps","\u002Fexamples\u002Fapps","4.examples\u002F2.apps",[471],{"title":472,"path":473,"stem":474,"icon":475},"Frigear website app","\u002Fexamples\u002Fapps\u002Ffrigear-nu-website","4.examples\u002F2.apps\u002F1.frigear-nu-website","i-lucide-layout-dashboard",{"title":477,"icon":49,"path":478,"stem":479,"children":480,"page":49},"Tasks","\u002Fexamples\u002Ftasks","4.examples\u002F3.tasks",[481,485,489,494,499],{"title":482,"path":483,"stem":484,"icon":70},"Protect a route","\u002Fexamples\u002Ftasks\u002Fprotect-a-route","4.examples\u002F3.tasks\u002F1.protect-a-route",{"title":486,"path":487,"stem":488,"icon":475},"Add an admin page","\u002Fexamples\u002Ftasks\u002Fadd-an-admin-page","4.examples\u002F3.tasks\u002F2.add-an-admin-page",{"title":490,"path":491,"stem":492,"icon":493},"Sell event tickets","\u002Fexamples\u002Ftasks\u002Fsell-event-tickets","4.examples\u002F3.tasks\u002F3.sell-event-tickets","i-lucide-ticket",{"title":495,"path":496,"stem":497,"icon":498},"Build a form","\u002Fexamples\u002Ftasks\u002Fbuild-a-form","4.examples\u002F3.tasks\u002F4.build-a-form","i-lucide-clipboard-list",{"title":500,"path":501,"stem":502,"icon":503},"Send an email","\u002Fexamples\u002Ftasks\u002Fsend-an-email","4.examples\u002F3.tasks\u002F5.send-an-email","i-lucide-mail",{"title":505,"icon":506,"path":507,"stem":508,"children":509,"page":49},"Contribute","i-lucide-git-pull-request","\u002Fcontribute","5.contribute",[510,513,518,544,549,552,556,571],{"title":173,"path":511,"stem":512,"icon":506},"\u002Fcontribute\u002Foverview","5.contribute\u002F1.overview",{"title":514,"path":515,"stem":516,"icon":517},"Local development","\u002Fcontribute\u002Flocal-development","5.contribute\u002F2.local-development","i-lucide-terminal",{"title":519,"icon":49,"path":520,"stem":521,"children":522,"page":49},"Writing a module","\u002Fcontribute\u002Fwriting-a-module","5.contribute\u002F3.writing-a-module",[523,527,532,536,541],{"title":524,"path":525,"stem":526,"icon":39},"Scaffold a module","\u002Fcontribute\u002Fwriting-a-module\u002Fscaffold","5.contribute\u002F3.writing-a-module\u002F1.scaffold",{"title":528,"path":529,"stem":530,"icon":531},"Setup checklist","\u002Fcontribute\u002Fwriting-a-module\u002Fsetup-checklist","5.contribute\u002F3.writing-a-module\u002F2.setup-checklist","i-lucide-list-checks",{"title":533,"path":534,"stem":535,"icon":44},"Database tables","\u002Fcontribute\u002Fwriting-a-module\u002Fdatabase-tables","5.contribute\u002F3.writing-a-module\u002F3.database-tables",{"title":537,"path":538,"stem":539,"icon":540},"Testing","\u002Fcontribute\u002Fwriting-a-module\u002Ftesting","5.contribute\u002F3.writing-a-module\u002F4.testing","i-lucide-flask-conical",{"title":67,"path":542,"stem":543,"icon":70},"\u002Fcontribute\u002Fwriting-a-module\u002Faccess-control","5.contribute\u002F3.writing-a-module\u002F5.access-control",{"title":545,"path":546,"stem":547,"icon":548},"Publishing","\u002Fcontribute\u002Fpublishing","5.contribute\u002F4.publishing","i-lucide-package-check",{"title":448,"path":550,"stem":551,"icon":6},"\u002Fcontribute\u002Fstarters","5.contribute\u002F5.starters",{"title":553,"path":554,"stem":555,"icon":52},"Documentation","\u002Fcontribute\u002Fdocumentation","5.contribute\u002F6.documentation",{"title":557,"icon":49,"path":558,"stem":559,"children":560,"page":49},"Tooling","\u002Fcontribute\u002Ftooling","5.contribute\u002F7.tooling",[561,566],{"title":562,"path":563,"stem":564,"icon":565},"CLI","\u002Fcontribute\u002Ftooling\u002Fcli","5.contribute\u002F7.tooling\u002F1.cli","i-lucide-square-terminal",{"title":567,"path":568,"stem":569,"icon":570},"ESLint config","\u002Fcontribute\u002Ftooling\u002Feslint-config","5.contribute\u002F7.tooling\u002F2.eslint-config","i-lucide-spell-check",{"title":572,"icon":49,"path":573,"stem":574,"children":575},"Decisions","\u002Fcontribute\u002Fdecisions","5.contribute\u002F8.decisions\u002Findex",[576,578,583],{"title":572,"path":573,"stem":574,"icon":577},"i-lucide-scale",{"title":579,"path":580,"stem":581,"icon":582},"Session lifetimes per OAuth client","\u002Fcontribute\u002Fdecisions\u002Foauth-token-lifetimes","5.contribute\u002F8.decisions\u002F1.oauth-token-lifetimes","i-lucide-timer",{"title":584,"path":585,"stem":586,"icon":70},"One permission model","\u002Fcontribute\u002Fdecisions\u002Fpermission-model","5.contribute\u002F8.decisions\u002F2.permission-model",{"id":588,"title":254,"body":589,"description":3233,"extension":3234,"links":3235,"meta":3236,"navigation":1724,"path":255,"seo":3237,"stem":256,"__hash__":3238},"docs\u002F3.modules\u002F2.commerce\u002F2.payments.md",{"type":590,"value":591,"toc":3210},"minimark",[592,600,608,613,665,669,706,710,1440,1463,1467,1473,1545,1552,1556,1562,1643,1653,2134,2161,2189,2211,2215,2234,2262,2268,2272,2304,2307,2316,2349,2355,2357,2364,2464,2572,2581,2585,2588,2704,2741,2745,2759,2822,2867,2880,2883,2890,2896,3100,3103,3109,3136,3190,3194,3206],[593,594,595,596,599],"p",{},"Payments lets your app charge a signed-in user once, for a ticket, an order or a fee. Your code creates a payment with\nits line items and sends the user to Stripe Checkout. A hook tells your code when the money has arrived. Payments does\nnot know what is sold, so Events and your own routes can share it. For recurring charges, use\n",[597,598,258],"a",{"href":259},".",[593,601,602,603,607],{},"The package is ",[604,605,606],"code",{},"@frigear-nu\u002Fpayments",". Only a verified Stripe event marks a payment as paid, never the redirect back to\nyour app. Prices are inline, so you create no products or prices in Stripe.",[609,610,612],"h2",{"id":611},"what-you-get","What you get",[614,615,616,636,653],"ul",{},[617,618,619,623,624,627,628,631,632,635],"li",{},[620,621,622],"strong",{},"Server routes"," (on by default): the signed-in user's payments, and resuming an unpaid one. A\n",[597,625,626],{"href":87},"staff"," route for revenue, guarded by the ",[604,629,630],{},"payments:manage"," permission (the ",[604,633,634],{},"admin"," role\nholds it).",[617,637,638,640,641,644,645,648,649,652],{},[620,639,344],{}," (on by default): ",[604,642,643],{},"createPayment",", ",[604,646,647],{},"refundPayment"," and readers on the server, and\n",[604,650,651],{},"usePayments()"," in the app.",[617,654,655,658,659,661,662,664],{},[620,656,657],{},"Admin area"," (with ",[597,660,217],{"href":351}," and ",[597,663,358],{"href":359},"): a Payments tab and a\nLast payment card on the admin user page, and revenue and recent transactions on the dashboard.",[666,667],"module-runtime",{":client":668,":server":668},"true",[670,671,672,692,700],"note",{},[593,673,674,677,678,644,681,644,683,685,686,644,688,661,690,599],{},[620,675,676],{},"Installed for you:"," ",[604,679,680],{},"@frigear-nu\u002Fmodule-kit",[597,682,168],{"href":169},[597,684,191],{"href":192},",\n",[597,687,250],{"href":251},[597,689,317],{"href":318},[597,691,326],{"href":327},[593,693,694,677,697,599],{},[620,695,696],{},"You add:",[604,698,699],{},"@nuxthub\u002Fcore",[593,701,702,705],{},[620,703,704],{},"Optional:"," Admin and Widget, for the admin tab, card and dashboard widgets. They need both.",[609,707,709],{"id":708},"quick-setup","Quick setup",[711,712,713,718,746,750,867,875,879,885,897,901,913,917,928,1021,1027,1030,1034,1048,1319,1322],"steps",{},[714,715,717],"h3",{"id":716},"install-payments","Install Payments",[719,720,725],"pre",{"className":721,"code":722,"language":723,"meta":724,"style":724},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @frigear-nu\u002Fpayments @nuxthub\u002Fcore\n","bash","",[604,726,727],{"__ignoreMap":724},[728,729,732,736,740,743],"span",{"class":730,"line":731},"line",1,[728,733,735],{"class":734},"sBMFI","pnpm",[728,737,739],{"class":738},"sfazB"," add",[728,741,742],{"class":738}," @frigear-nu\u002Fpayments",[728,744,745],{"class":738}," @nuxthub\u002Fcore\n",[714,747,749],{"id":748},"add-it-to-nuxtconfigts","Add it to nuxt.config.ts",[719,751,756],{"className":752,"code":753,"filename":754,"language":755,"meta":724,"style":724},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@nuxthub\u002Fcore', '@frigear-nu\u002Fpayments'], \u002F\u002F installs Users and Stripe for you\n  payments: {\n    settings: { checkoutExpiresInMinutes: 30 },\n  },\n})\n","nuxt.config.ts","ts",[604,757,758,779,818,829,852,858],{"__ignoreMap":724},[728,759,760,764,767,771,775],{"class":730,"line":731},[728,761,763],{"class":762},"s7zQu","export",[728,765,766],{"class":762}," default",[728,768,770],{"class":769},"s2Zo4"," defineNuxtConfig",[728,772,774],{"class":773},"sTEyZ","(",[728,776,778],{"class":777},"sMK4o","{\n",[728,780,782,786,789,792,795,797,799,802,805,807,809,812,814],{"class":730,"line":781},2,[728,783,785],{"class":784},"swJcz","  modules",[728,787,788],{"class":777},":",[728,790,791],{"class":773}," [",[728,793,794],{"class":777},"'",[728,796,699],{"class":738},[728,798,794],{"class":777},[728,800,801],{"class":777},",",[728,803,804],{"class":777}," '",[728,806,606],{"class":738},[728,808,794],{"class":777},[728,810,811],{"class":773},"]",[728,813,801],{"class":777},[728,815,817],{"class":816},"sHwdD"," \u002F\u002F installs Users and Stripe for you\n",[728,819,821,824,826],{"class":730,"line":820},3,[728,822,823],{"class":784},"  payments",[728,825,788],{"class":777},[728,827,828],{"class":777}," {\n",[728,830,832,835,837,840,843,845,849],{"class":730,"line":831},4,[728,833,834],{"class":784},"    settings",[728,836,788],{"class":777},[728,838,839],{"class":777}," {",[728,841,842],{"class":784}," checkoutExpiresInMinutes",[728,844,788],{"class":777},[728,846,848],{"class":847},"sbssI"," 30",[728,850,851],{"class":777}," },\n",[728,853,855],{"class":730,"line":854},5,[728,856,857],{"class":777},"  },\n",[728,859,861,864],{"class":730,"line":860},6,[728,862,863],{"class":777},"}",[728,865,866],{"class":773},")\n",[868,869,870,871,874],"caution",{},"Use test keys (",[604,872,873],{},"sk_test_...",") until the whole flow works: live keys charge real cards.",[714,876,878],{"id":877},"connect-your-stripe-account","Connect your Stripe account",[593,880,881,882,884],{},"Set the keys and the webhook endpoint as ",[597,883,146],{"href":147}," describes, with the events\nit lists for Payments.",[886,887,888,889,892,893,896],"warning",{},"Without a ",[597,890,891],{"href":87},"migration"," the ",[604,894,895],{},"payments"," table does not exist, and every checkout fails.",[714,898,900],{"id":899},"generate-the-migration","Generate the migration",[719,902,904],{"className":721,"code":903,"language":723,"meta":724,"style":724},"pnpm db:generate\n",[604,905,906],{"__ignoreMap":724},[728,907,908,910],{"class":730,"line":731},[728,909,735],{"class":734},[728,911,912],{"class":738}," db:generate\n",[714,914,916],{"id":915},"decide-who-sees-revenue","Decide who sees revenue",[593,918,919,920,922,923,925,926,788],{},"Revenue and recent transactions on the admin dashboard need the ",[604,921,630],{}," permission. The ",[604,924,634],{}," role holds\nit by default. To give it to another role, grant it in ",[597,927,199],{"href":200},[719,929,931],{"className":752,"code":930,"filename":754,"language":755,"meta":724,"style":724},"export default defineNuxtConfig({\n  authorization: {\n    roles: {\n      bookkeeper: { label: 'Bookkeeper', grant: ['payments:manage'] },\n    },\n  },\n})\n",[604,932,933,945,954,963,1005,1010,1014],{"__ignoreMap":724},[728,934,935,937,939,941,943],{"class":730,"line":731},[728,936,763],{"class":762},[728,938,766],{"class":762},[728,940,770],{"class":769},[728,942,774],{"class":773},[728,944,778],{"class":777},[728,946,947,950,952],{"class":730,"line":781},[728,948,949],{"class":784},"  authorization",[728,951,788],{"class":777},[728,953,828],{"class":777},[728,955,956,959,961],{"class":730,"line":820},[728,957,958],{"class":784},"    roles",[728,960,788],{"class":777},[728,962,828],{"class":777},[728,964,965,968,970,972,975,977,979,982,984,986,989,991,993,995,997,999,1002],{"class":730,"line":831},[728,966,967],{"class":784},"      bookkeeper",[728,969,788],{"class":777},[728,971,839],{"class":777},[728,973,974],{"class":784}," label",[728,976,788],{"class":777},[728,978,804],{"class":777},[728,980,981],{"class":738},"Bookkeeper",[728,983,794],{"class":777},[728,985,801],{"class":777},[728,987,988],{"class":784}," grant",[728,990,788],{"class":777},[728,992,791],{"class":773},[728,994,794],{"class":777},[728,996,630],{"class":738},[728,998,794],{"class":777},[728,1000,1001],{"class":773},"] ",[728,1003,1004],{"class":777},"},\n",[728,1006,1007],{"class":730,"line":854},[728,1008,1009],{"class":777},"    },\n",[728,1011,1012],{"class":730,"line":860},[728,1013,857],{"class":777},[728,1015,1017,1019],{"class":730,"line":1016},7,[728,1018,863],{"class":777},[728,1020,866],{"class":773},[886,1022,1023,1024,1026],{},"Without a role that holds ",[604,1025,630],{},", nobody sees revenue and recent transactions on the admin dashboard.",[868,1028,1029],{},"This step charges money. Test it with test keys first.",[714,1031,1033],{"id":1032},"take-a-payment","Take a payment",[593,1035,1036,1037,1040,1041,1044,1045,1047],{},"Create the payment in a route and send the user to the returned ",[604,1038,1039],{},"url",". Charging money needs a signed-in session, so the\nroute passes ",[604,1042,1043],{},"sessionOnly: true",". See ",[597,1046,67],{"href":68}," for how a session differs from\na token:",[719,1049,1052],{"className":752,"code":1050,"filename":1051,"language":755,"meta":724,"style":724},"export default defineEventHandler(async (event) => {\n  const user = await requireUser(event, { sessionOnly: true })\n  const { url } = await createPayment({\n    userId: user.id,\n    items: [{ name: 'Workshop seat', amount: 25000, currency: 'dkk' }], \u002F\u002F 250.00 DKK\n    reference: { type: 'workshop_seat', id: 'spring' },\n    successUrl: '\u002Fshop\u002Fthanks',\n    cancelUrl: '\u002Fshop',\n  }, event)\n  return { url }\n})\n","server\u002Fapi\u002Fshop\u002Fcheckout.post.ts",[604,1053,1054,1084,1123,1145,1161,1218,1255,1271,1288,1299,1312],{"__ignoreMap":724},[728,1055,1056,1058,1060,1063,1065,1069,1072,1076,1079,1082],{"class":730,"line":731},[728,1057,763],{"class":762},[728,1059,766],{"class":762},[728,1061,1062],{"class":769}," defineEventHandler",[728,1064,774],{"class":773},[728,1066,1068],{"class":1067},"spNyl","async",[728,1070,1071],{"class":777}," (",[728,1073,1075],{"class":1074},"sHdIc","event",[728,1077,1078],{"class":777},")",[728,1080,1081],{"class":1067}," =>",[728,1083,828],{"class":777},[728,1085,1086,1089,1092,1095,1098,1101,1103,1105,1107,1109,1112,1114,1118,1121],{"class":730,"line":781},[728,1087,1088],{"class":1067},"  const",[728,1090,1091],{"class":773}," user",[728,1093,1094],{"class":777}," =",[728,1096,1097],{"class":762}," await",[728,1099,1100],{"class":769}," requireUser",[728,1102,774],{"class":784},[728,1104,1075],{"class":773},[728,1106,801],{"class":777},[728,1108,839],{"class":777},[728,1110,1111],{"class":784}," sessionOnly",[728,1113,788],{"class":777},[728,1115,1117],{"class":1116},"sfNiH"," true",[728,1119,1120],{"class":777}," }",[728,1122,866],{"class":784},[728,1124,1125,1127,1129,1132,1134,1136,1138,1141,1143],{"class":730,"line":820},[728,1126,1088],{"class":1067},[728,1128,839],{"class":777},[728,1130,1131],{"class":773}," url",[728,1133,1120],{"class":777},[728,1135,1094],{"class":777},[728,1137,1097],{"class":762},[728,1139,1140],{"class":769}," createPayment",[728,1142,774],{"class":784},[728,1144,778],{"class":777},[728,1146,1147,1150,1152,1154,1156,1159],{"class":730,"line":831},[728,1148,1149],{"class":784},"    userId",[728,1151,788],{"class":777},[728,1153,1091],{"class":773},[728,1155,599],{"class":777},[728,1157,1158],{"class":773},"id",[728,1160,685],{"class":777},[728,1162,1163,1166,1168,1170,1173,1176,1178,1180,1183,1185,1187,1190,1192,1195,1197,1200,1202,1204,1207,1209,1211,1213,1215],{"class":730,"line":854},[728,1164,1165],{"class":784},"    items",[728,1167,788],{"class":777},[728,1169,791],{"class":784},[728,1171,1172],{"class":777},"{",[728,1174,1175],{"class":784}," name",[728,1177,788],{"class":777},[728,1179,804],{"class":777},[728,1181,1182],{"class":738},"Workshop seat",[728,1184,794],{"class":777},[728,1186,801],{"class":777},[728,1188,1189],{"class":784}," amount",[728,1191,788],{"class":777},[728,1193,1194],{"class":847}," 25000",[728,1196,801],{"class":777},[728,1198,1199],{"class":784}," currency",[728,1201,788],{"class":777},[728,1203,804],{"class":777},[728,1205,1206],{"class":738},"dkk",[728,1208,794],{"class":777},[728,1210,1120],{"class":777},[728,1212,811],{"class":784},[728,1214,801],{"class":777},[728,1216,1217],{"class":816}," \u002F\u002F 250.00 DKK\n",[728,1219,1220,1223,1225,1227,1230,1232,1234,1237,1239,1241,1244,1246,1248,1251,1253],{"class":730,"line":860},[728,1221,1222],{"class":784},"    reference",[728,1224,788],{"class":777},[728,1226,839],{"class":777},[728,1228,1229],{"class":784}," type",[728,1231,788],{"class":777},[728,1233,804],{"class":777},[728,1235,1236],{"class":738},"workshop_seat",[728,1238,794],{"class":777},[728,1240,801],{"class":777},[728,1242,1243],{"class":784}," id",[728,1245,788],{"class":777},[728,1247,804],{"class":777},[728,1249,1250],{"class":738},"spring",[728,1252,794],{"class":777},[728,1254,851],{"class":777},[728,1256,1257,1260,1262,1264,1267,1269],{"class":730,"line":1016},[728,1258,1259],{"class":784},"    successUrl",[728,1261,788],{"class":777},[728,1263,804],{"class":777},[728,1265,1266],{"class":738},"\u002Fshop\u002Fthanks",[728,1268,794],{"class":777},[728,1270,685],{"class":777},[728,1272,1274,1277,1279,1281,1284,1286],{"class":730,"line":1273},8,[728,1275,1276],{"class":784},"    cancelUrl",[728,1278,788],{"class":777},[728,1280,804],{"class":777},[728,1282,1283],{"class":738},"\u002Fshop",[728,1285,794],{"class":777},[728,1287,685],{"class":777},[728,1289,1291,1294,1297],{"class":730,"line":1290},9,[728,1292,1293],{"class":777},"  },",[728,1295,1296],{"class":773}," event",[728,1298,866],{"class":784},[728,1300,1302,1305,1307,1309],{"class":730,"line":1301},10,[728,1303,1304],{"class":762},"  return",[728,1306,839],{"class":777},[728,1308,1131],{"class":773},[728,1310,1311],{"class":777}," }\n",[728,1313,1315,1317],{"class":730,"line":1314},11,[728,1316,863],{"class":777},[728,1318,866],{"class":773},[593,1320,1321],{},"Then act when Stripe confirms it, filtered on your reference type:",[719,1323,1326],{"className":752,"code":1324,"filename":1325,"language":755,"meta":724,"style":724},"export default defineNitroPlugin((nitro) => {\n  nitro.hooks.hook('payments:paid', async ({ payment }) => {\n    if (payment.referenceType !== 'workshop_seat') return\n    \u002F\u002F confirm the seat for payment.userId\n  })\n})\n","server\u002Fplugins\u002Fshop.ts",[604,1327,1328,1350,1392,1422,1427,1434],{"__ignoreMap":724},[728,1329,1330,1332,1334,1337,1339,1341,1344,1346,1348],{"class":730,"line":731},[728,1331,763],{"class":762},[728,1333,766],{"class":762},[728,1335,1336],{"class":769}," defineNitroPlugin",[728,1338,774],{"class":773},[728,1340,774],{"class":777},[728,1342,1343],{"class":1074},"nitro",[728,1345,1078],{"class":777},[728,1347,1081],{"class":1067},[728,1349,828],{"class":777},[728,1351,1352,1355,1357,1360,1362,1365,1367,1369,1372,1374,1376,1379,1382,1385,1388,1390],{"class":730,"line":781},[728,1353,1354],{"class":773},"  nitro",[728,1356,599],{"class":777},[728,1358,1359],{"class":773},"hooks",[728,1361,599],{"class":777},[728,1363,1364],{"class":769},"hook",[728,1366,774],{"class":784},[728,1368,794],{"class":777},[728,1370,1371],{"class":738},"payments:paid",[728,1373,794],{"class":777},[728,1375,801],{"class":777},[728,1377,1378],{"class":1067}," async",[728,1380,1381],{"class":777}," ({",[728,1383,1384],{"class":1074}," payment",[728,1386,1387],{"class":777}," })",[728,1389,1081],{"class":1067},[728,1391,828],{"class":777},[728,1393,1394,1397,1399,1402,1404,1407,1410,1412,1414,1416,1419],{"class":730,"line":820},[728,1395,1396],{"class":762},"    if",[728,1398,1071],{"class":784},[728,1400,1401],{"class":773},"payment",[728,1403,599],{"class":777},[728,1405,1406],{"class":773},"referenceType",[728,1408,1409],{"class":777}," !==",[728,1411,804],{"class":777},[728,1413,1236],{"class":738},[728,1415,794],{"class":777},[728,1417,1418],{"class":784},") ",[728,1420,1421],{"class":762},"return\n",[728,1423,1424],{"class":730,"line":831},[728,1425,1426],{"class":816},"    \u002F\u002F confirm the seat for payment.userId\n",[728,1428,1429,1432],{"class":730,"line":854},[728,1430,1431],{"class":777},"  }",[728,1433,866],{"class":784},[728,1435,1436,1438],{"class":730,"line":860},[728,1437,863],{"class":777},[728,1439,866],{"class":773},[1441,1442,1445,1448,1449,644,1452,1455,1456,1459,1460,1462],"callout",{"color":1443,"icon":1444},"success","i-lucide-check",[620,1446,1447],{},"What you should see:"," after paying with Stripe's test card ",[604,1450,1451],{},"4242 4242 4242 4242",[604,1453,1454],{},"GET \u002Fapi\u002Fpayments\u002Fme"," lists the\npayment as ",[604,1457,1458],{},"paid",", and your ",[604,1461,1371],{}," listener has run.",[609,1464,1466],{"id":1465},"options","Options",[593,1468,1469,1470,1472],{},"Options go under the ",[604,1471,895],{}," key.",[1474,1475,1476,1495],"table",{},[1477,1478,1479],"thead",{},[1480,1481,1482,1486,1489,1492],"tr",{},[1483,1484,1485],"th",{},"Option",[1483,1487,1488],{},"Type",[1483,1490,1491],{},"Default",[1483,1493,1494],{},"Purpose",[1496,1497,1498,1519],"tbody",{},[1480,1499,1500,1506,1511,1516],{},[1501,1502,1503],"td",{},[604,1504,1505],{},"settings.checkoutExpiresInMinutes",[1501,1507,1508],{},[604,1509,1510],{},"number",[1501,1512,1513],{},[604,1514,1515],{},"30",[1501,1517,1518],{},"Minutes a Checkout session stays open.",[1480,1520,1521,1526,1531,1536],{},[1501,1522,1523],{},[604,1524,1525],{},"settings.mcp",[1501,1527,1528],{},[604,1529,1530],{},"boolean",[1501,1532,1533],{},[604,1534,1535],{},"false",[1501,1537,1538,1539,677,1542,1544],{},"Adds the ",[604,1540,1541],{},"my-payments",[597,1543,317],{"href":318}," tool.",[593,1546,1547,1551],{},[620,1548,1549],{},[604,1550,1505],{}," is clamped to Stripe's range of 30 to 1440.",[609,1553,1555],{"id":1554},"server","Server",[593,1557,1558,1559,599],{},"These helpers are auto-imported in ",[597,1560,1561],{"href":87},"Nitro",[1474,1563,1564,1574],{},[1477,1565,1566],{},[1480,1567,1568,1571],{},[1483,1569,1570],{},"Helper",[1483,1572,1573],{},"What it does",[1496,1575,1576,1593,1607,1617,1633],{},[1480,1577,1578,1583],{},[1501,1579,1580],{},[604,1581,1582],{},"createPayment(input, event?)",[1501,1584,1585,1586,1589,1590,599],{},"Creates a Checkout session and a ",[604,1587,1588],{},"pending"," payment. Returns ",[604,1591,1592],{},"CreatePaymentResult",[1480,1594,1595,1600],{},[1501,1596,1597],{},[604,1598,1599],{},"resumePayment(paymentId, userId, event?)",[1501,1601,1602,1603,1606],{},"Returns ",[604,1604,1605],{},"{ url }"," of the open session, or of a new one once it expired.",[1480,1608,1609,1614],{},[1501,1610,1611],{},[604,1612,1613],{},"refundPayment(paymentId, { amount? })",[1501,1615,1616],{},"Asks Stripe for a full or partial refund.",[1480,1618,1619,1627],{},[1501,1620,1621,644,1624],{},[604,1622,1623],{},"getPayment(id)",[604,1625,1626],{},"getPaymentByReference(type, id)",[1501,1628,1629,1630,599],{},"One payment, the latest for a reference, or ",[604,1631,1632],{},"null",[1480,1634,1635,1640],{},[1501,1636,1637],{},[604,1638,1639],{},"listUserPayments(userId, { limit? })",[1501,1641,1642],{},"A user's payments, newest first.",[593,1644,1645,1648,1649,1652],{},[604,1646,1647],{},"@frigear-nu\u002Fpayments\u002Futils"," exports the types below and ",[604,1650,1651],{},"sumItems(items)",", which totals items in minor units.",[719,1654,1656],{"className":752,"code":1655,"language":755,"meta":724,"style":724},"type PaymentStatus = 'pending' | 'paid' | 'failed' | 'expired' | 'refunded' | 'partially_refunded'\n\ntype PaymentItem = {\n  name: string\n  description?: string\n  amount: number      \u002F\u002F unit amount in minor units (cents \u002F øre)\n  currency: string    \u002F\u002F ISO 4217\n  quantity?: number   \u002F\u002F default 1\n}\n\ntype CreatePaymentInput = {\n  userId: number\n  items: PaymentItem[]                           \u002F\u002F one currency, total above zero\n  reference?: { type: string, id: string }       \u002F\u002F e.g. { type: 'event_ticket', id }\n  successUrl: string                             \u002F\u002F absolute URL or path on the current origin\n  cancelUrl: string\n  description?: string\n  expiresInMinutes?: number                      \u002F\u002F overrides settings.checkoutExpiresInMinutes\n  metadata?: Record\u003Cstring, string>\n}\n\ntype CreatePaymentResult = { payment: PaymentDto, url: string }\n\ntype PaymentDto = {\n  id: string                      \u002F\u002F pay_...\n  userId: number\n  status: PaymentStatus\n  amount: number\n  currency: string\n  description: string | null\n  referenceType: string | null\n  referenceId: string | null\n  refundedAmount: number\n  paidAt: string | null           \u002F\u002F ISO\n  createdAt: string               \u002F\u002F ISO\n}\n",[604,1657,1658,1720,1726,1737,1747,1757,1770,1783,1795,1800,1804,1815,1826,1842,1871,1884,1894,1903,1916,1940,1945,1950,1979,1984,1995,2008,2017,2028,2037,2046,2060,2074,2088,2098,2116,2129],{"__ignoreMap":724},[728,1659,1660,1663,1666,1668,1670,1672,1674,1677,1679,1681,1683,1685,1687,1690,1692,1694,1696,1699,1701,1703,1705,1708,1710,1712,1714,1717],{"class":730,"line":731},[728,1661,1662],{"class":1067},"type",[728,1664,1665],{"class":734}," PaymentStatus",[728,1667,1094],{"class":777},[728,1669,804],{"class":777},[728,1671,1588],{"class":738},[728,1673,794],{"class":777},[728,1675,1676],{"class":777}," |",[728,1678,804],{"class":777},[728,1680,1458],{"class":738},[728,1682,794],{"class":777},[728,1684,1676],{"class":777},[728,1686,804],{"class":777},[728,1688,1689],{"class":738},"failed",[728,1691,794],{"class":777},[728,1693,1676],{"class":777},[728,1695,804],{"class":777},[728,1697,1698],{"class":738},"expired",[728,1700,794],{"class":777},[728,1702,1676],{"class":777},[728,1704,804],{"class":777},[728,1706,1707],{"class":738},"refunded",[728,1709,794],{"class":777},[728,1711,1676],{"class":777},[728,1713,804],{"class":777},[728,1715,1716],{"class":738},"partially_refunded",[728,1718,1719],{"class":777},"'\n",[728,1721,1722],{"class":730,"line":781},[728,1723,1725],{"emptyLinePlaceholder":1724},true,"\n",[728,1727,1728,1730,1733,1735],{"class":730,"line":820},[728,1729,1662],{"class":1067},[728,1731,1732],{"class":734}," PaymentItem",[728,1734,1094],{"class":777},[728,1736,828],{"class":777},[728,1738,1739,1742,1744],{"class":730,"line":831},[728,1740,1741],{"class":784},"  name",[728,1743,788],{"class":777},[728,1745,1746],{"class":734}," string\n",[728,1748,1749,1752,1755],{"class":730,"line":854},[728,1750,1751],{"class":784},"  description",[728,1753,1754],{"class":777},"?:",[728,1756,1746],{"class":734},[728,1758,1759,1762,1764,1767],{"class":730,"line":860},[728,1760,1761],{"class":784},"  amount",[728,1763,788],{"class":777},[728,1765,1766],{"class":734}," number",[728,1768,1769],{"class":816},"      \u002F\u002F unit amount in minor units (cents \u002F øre)\n",[728,1771,1772,1775,1777,1780],{"class":730,"line":1016},[728,1773,1774],{"class":784},"  currency",[728,1776,788],{"class":777},[728,1778,1779],{"class":734}," string",[728,1781,1782],{"class":816},"    \u002F\u002F ISO 4217\n",[728,1784,1785,1788,1790,1792],{"class":730,"line":1273},[728,1786,1787],{"class":784},"  quantity",[728,1789,1754],{"class":777},[728,1791,1766],{"class":734},[728,1793,1794],{"class":816},"   \u002F\u002F default 1\n",[728,1796,1797],{"class":730,"line":1290},[728,1798,1799],{"class":777},"}\n",[728,1801,1802],{"class":730,"line":1301},[728,1803,1725],{"emptyLinePlaceholder":1724},[728,1805,1806,1808,1811,1813],{"class":730,"line":1314},[728,1807,1662],{"class":1067},[728,1809,1810],{"class":734}," CreatePaymentInput",[728,1812,1094],{"class":777},[728,1814,828],{"class":777},[728,1816,1818,1821,1823],{"class":730,"line":1817},12,[728,1819,1820],{"class":784},"  userId",[728,1822,788],{"class":777},[728,1824,1825],{"class":734}," number\n",[728,1827,1829,1832,1834,1836,1839],{"class":730,"line":1828},13,[728,1830,1831],{"class":784},"  items",[728,1833,788],{"class":777},[728,1835,1732],{"class":734},[728,1837,1838],{"class":773},"[]                           ",[728,1840,1841],{"class":816},"\u002F\u002F one currency, total above zero\n",[728,1843,1845,1848,1850,1852,1854,1856,1858,1860,1862,1864,1866,1868],{"class":730,"line":1844},14,[728,1846,1847],{"class":784},"  reference",[728,1849,1754],{"class":777},[728,1851,839],{"class":777},[728,1853,1229],{"class":784},[728,1855,788],{"class":777},[728,1857,1779],{"class":734},[728,1859,801],{"class":777},[728,1861,1243],{"class":784},[728,1863,788],{"class":777},[728,1865,1779],{"class":734},[728,1867,1120],{"class":777},[728,1869,1870],{"class":816},"       \u002F\u002F e.g. { type: 'event_ticket', id }\n",[728,1872,1874,1877,1879,1881],{"class":730,"line":1873},15,[728,1875,1876],{"class":784},"  successUrl",[728,1878,788],{"class":777},[728,1880,1779],{"class":734},[728,1882,1883],{"class":816},"                             \u002F\u002F absolute URL or path on the current origin\n",[728,1885,1887,1890,1892],{"class":730,"line":1886},16,[728,1888,1889],{"class":784},"  cancelUrl",[728,1891,788],{"class":777},[728,1893,1746],{"class":734},[728,1895,1897,1899,1901],{"class":730,"line":1896},17,[728,1898,1751],{"class":784},[728,1900,1754],{"class":777},[728,1902,1746],{"class":734},[728,1904,1906,1909,1911,1913],{"class":730,"line":1905},18,[728,1907,1908],{"class":784},"  expiresInMinutes",[728,1910,1754],{"class":777},[728,1912,1766],{"class":734},[728,1914,1915],{"class":816},"                      \u002F\u002F overrides settings.checkoutExpiresInMinutes\n",[728,1917,1919,1922,1924,1927,1930,1933,1935,1937],{"class":730,"line":1918},19,[728,1920,1921],{"class":784},"  metadata",[728,1923,1754],{"class":777},[728,1925,1926],{"class":734}," Record",[728,1928,1929],{"class":777},"\u003C",[728,1931,1932],{"class":734},"string",[728,1934,801],{"class":777},[728,1936,1779],{"class":734},[728,1938,1939],{"class":777},">\n",[728,1941,1943],{"class":730,"line":1942},20,[728,1944,1799],{"class":777},[728,1946,1948],{"class":730,"line":1947},21,[728,1949,1725],{"emptyLinePlaceholder":1724},[728,1951,1953,1955,1958,1960,1962,1964,1966,1969,1971,1973,1975,1977],{"class":730,"line":1952},22,[728,1954,1662],{"class":1067},[728,1956,1957],{"class":734}," CreatePaymentResult",[728,1959,1094],{"class":777},[728,1961,839],{"class":777},[728,1963,1384],{"class":784},[728,1965,788],{"class":777},[728,1967,1968],{"class":734}," PaymentDto",[728,1970,801],{"class":777},[728,1972,1131],{"class":784},[728,1974,788],{"class":777},[728,1976,1779],{"class":734},[728,1978,1311],{"class":777},[728,1980,1982],{"class":730,"line":1981},23,[728,1983,1725],{"emptyLinePlaceholder":1724},[728,1985,1987,1989,1991,1993],{"class":730,"line":1986},24,[728,1988,1662],{"class":1067},[728,1990,1968],{"class":734},[728,1992,1094],{"class":777},[728,1994,828],{"class":777},[728,1996,1998,2001,2003,2005],{"class":730,"line":1997},25,[728,1999,2000],{"class":784},"  id",[728,2002,788],{"class":777},[728,2004,1779],{"class":734},[728,2006,2007],{"class":816},"                      \u002F\u002F pay_...\n",[728,2009,2011,2013,2015],{"class":730,"line":2010},26,[728,2012,1820],{"class":784},[728,2014,788],{"class":777},[728,2016,1825],{"class":734},[728,2018,2020,2023,2025],{"class":730,"line":2019},27,[728,2021,2022],{"class":784},"  status",[728,2024,788],{"class":777},[728,2026,2027],{"class":734}," PaymentStatus\n",[728,2029,2031,2033,2035],{"class":730,"line":2030},28,[728,2032,1761],{"class":784},[728,2034,788],{"class":777},[728,2036,1825],{"class":734},[728,2038,2040,2042,2044],{"class":730,"line":2039},29,[728,2041,1774],{"class":784},[728,2043,788],{"class":777},[728,2045,1746],{"class":734},[728,2047,2049,2051,2053,2055,2057],{"class":730,"line":2048},30,[728,2050,1751],{"class":784},[728,2052,788],{"class":777},[728,2054,1779],{"class":734},[728,2056,1676],{"class":777},[728,2058,2059],{"class":734}," null\n",[728,2061,2063,2066,2068,2070,2072],{"class":730,"line":2062},31,[728,2064,2065],{"class":784},"  referenceType",[728,2067,788],{"class":777},[728,2069,1779],{"class":734},[728,2071,1676],{"class":777},[728,2073,2059],{"class":734},[728,2075,2077,2080,2082,2084,2086],{"class":730,"line":2076},32,[728,2078,2079],{"class":784},"  referenceId",[728,2081,788],{"class":777},[728,2083,1779],{"class":734},[728,2085,1676],{"class":777},[728,2087,2059],{"class":734},[728,2089,2091,2094,2096],{"class":730,"line":2090},33,[728,2092,2093],{"class":784},"  refundedAmount",[728,2095,788],{"class":777},[728,2097,1825],{"class":734},[728,2099,2101,2104,2106,2108,2110,2113],{"class":730,"line":2100},34,[728,2102,2103],{"class":784},"  paidAt",[728,2105,788],{"class":777},[728,2107,1779],{"class":734},[728,2109,1676],{"class":777},[728,2111,2112],{"class":734}," null",[728,2114,2115],{"class":816},"           \u002F\u002F ISO\n",[728,2117,2119,2122,2124,2126],{"class":730,"line":2118},35,[728,2120,2121],{"class":784},"  createdAt",[728,2123,788],{"class":777},[728,2125,1779],{"class":734},[728,2127,2128],{"class":816},"               \u002F\u002F ISO\n",[728,2130,2132],{"class":730,"line":2131},36,[728,2133,1799],{"class":777},[593,2135,2136,2140,2141,661,2144,2147,2148,2150,2151,2153,2154,2157,2158,599],{},[620,2137,2138],{},[604,2139,643],{}," validates ",[604,2142,2143],{},"successUrl",[604,2145,2146],{},"cancelUrl"," as a relative path or the same origin when you pass ",[604,2149,1075],{},".\nWithout ",[604,2152,1075],{}," they must be absolute ",[604,2155,2156],{},"http(s)"," URLs. An invalid URL throws ",[604,2159,2160],{},"400",[593,2162,2163,2168,2169,2172,2173,2176,2177,2180,2181,2184,2185,2188],{},[620,2164,2165],{},[604,2166,2167],{},"resumePayment"," throws ",[604,2170,2171],{},"404"," for an unknown payment, and ",[604,2174,2175],{},"409"," when it is already paid or refunded. For an expired\nsession it builds a new one from the stored items and the old success and cancel URLs. It runs\n",[604,2178,2179],{},"payments:checkout:before"," and the URL check again. The configured ",[604,2182,2183],{},"checkoutExpiresInMinutes"," applies, because\n",[604,2186,2187],{},"expiresInMinutes"," is not stored.",[593,2190,2191,2168,2195,2197,2198,2200,2201,2203,2204,2206,2207,2210],{},[620,2192,2193],{},[604,2194,647],{},[604,2196,2175],{}," unless the payment is ",[604,2199,1458],{}," or ",[604,2202,1716],{},". An amount that is not positive,\nor more than is left, throws ",[604,2205,2160],{},". The status changes when the ",[604,2208,2209],{},"charge.refunded"," event arrives.",[714,2212,2214],{"id":2213},"subscription-invoices","Subscription invoices",[593,2216,2217,2218,2220,2221,644,2224,644,2227,661,2230,2233],{},"With ",[597,2219,258],{"href":259}," installed, every subscription invoice is stored as a payment too.\nThese are the ",[604,2222,2223],{},"invoice.paid",[604,2225,2226],{},"invoice.payment_failed",[604,2228,2229],{},"invoice.voided",[604,2231,2232],{},"invoice.marked_uncollectible"," events.",[614,2235,2236,2247,2256,2259],{},[617,2237,2238,2239,2242,2243,2246],{},"The payment has ",[604,2240,2241],{},"referenceType: 'subscription'",", and ",[604,2244,2245],{},"referenceId"," is the Stripe subscription id.",[617,2248,2249,2250,2253,2254,599],{},"It fires the ",[604,2251,2252],{},"payments:*"," hooks and shows in the admin tab, the card and ",[604,2255,1541],{},[617,2257,2258],{},"Invoices of zero, such as trials and full discounts, are skipped.",[617,2260,2261],{},"Only invoices received after upgrading are stored.",[593,2263,2264,2267],{},[604,2265,2266],{},"recordInvoicePayment(input: InvoicePaymentInput)"," is the auto-imported helper behind this. It is idempotent per\ninvoice id. Without Payments, Subscriptions records no invoices.",[714,2269,2271],{"id":2270},"mcp-tool","MCP tool",[593,2273,2217,2274,2277,2278,2280,2281,2284,2285,2288,2289,661,2292,2295,2296,2299,2300,2303],{},[604,2275,2276],{},"settings.mcp: true",", the ",[604,2279,1541],{}," tool (scope ",[604,2282,2283],{},"payments:read",") lists the signed-in user's own payments,\nnewest first, with an optional ",[604,2286,2287],{},"limit",". Its ",[604,2290,2291],{},"amount",[604,2293,2294],{},"refundedAmount"," are in whole currency units (",[604,2297,2298],{},"52.2"," is 52.20),\nnot minor units, and ",[604,2301,2302],{},"currency"," is upper-case.",[609,2305,267],{"id":2306},"app",[593,2308,2309,2311,2312,2315],{},[604,2310,651],{}," loads the signed-in user's payments. It is auto-imported, and pages can ",[604,2313,2314],{},"await"," it.",[1474,2317,2318,2330],{},[1477,2319,2320],{},[1480,2321,2322,2325,2328],{},[1483,2323,2324],{},"Composable",[1483,2326,2327],{},"Returns",[1483,2329,1573],{},[1496,2331,2332],{},[1480,2333,2334,2338,2343],{},[1501,2335,2336],{},[604,2337,651],{},[1501,2339,2340],{},[604,2341,2342],{},"{ payments, refresh, status, loading, error, resume(paymentId) }",[1501,2344,2345,2348],{},[604,2346,2347],{},"resume"," sends the user back to Stripe.",[593,2350,2351,2352,2354],{},"With Widget and Admin installed, the module adds a Payments tab (order 20) and a Last payment card to the admin user\npage of ",[597,2353,191],{"href":192},". The tab is read-only: it has no refund action yet. The admin dashboard gets\na 30-day revenue stat and the recent\ntransactions.",[609,2356,234],{"id":1359},[593,2358,2359,2360,2363],{},"Your app answers these Nitro hooks from a server plugin (",[604,2361,2362],{},"server\u002Fplugins\u002F*.ts",").",[1474,2365,2366,2379],{},[1477,2367,2368],{},[1480,2369,2370,2373,2376],{},[1483,2371,2372],{},"Hook",[1483,2374,2375],{},"When",[1483,2377,2378],{},"Payload",[1496,2380,2381,2404,2418,2432,2446],{},[1480,2382,2383,2387,2399],{},[1501,2384,2385],{},[604,2386,2179],{},[1501,2388,2389,2390,2200,2392,2394,2395,2398],{},"Before ",[604,2391,643],{},[604,2393,2167],{}," creates a session. Change ",[604,2396,2397],{},"ctx.params",", or throw to deny.",[1501,2400,2401],{},[604,2402,2403],{},"CheckoutBeforeContext",[1480,2405,2406,2410,2413],{},[1501,2407,2408],{},[604,2409,1371],{},[1501,2411,2412],{},"Once, when the payment is paid.",[1501,2414,2415],{},[604,2416,2417],{},"PaymentHookContext",[1480,2419,2420,2425,2428],{},[1501,2421,2422],{},[604,2423,2424],{},"payments:failed",[1501,2426,2427],{},"An asynchronous payment method failed.",[1501,2429,2430],{},[604,2431,2417],{},[1480,2433,2434,2439,2442],{},[1501,2435,2436],{},[604,2437,2438],{},"payments:expired",[1501,2440,2441],{},"The Checkout session expired unpaid.",[1501,2443,2444],{},[604,2445,2417],{},[1480,2447,2448,2453,2460],{},[1501,2449,2450],{},[604,2451,2452],{},"payments:refunded",[1501,2454,2455,2456,2200,2458,599],{},"A refund changed the payment to ",[604,2457,1716],{},[604,2459,1707],{},[1501,2461,2462],{},[604,2463,2417],{},[719,2465,2467],{"className":752,"code":2466,"language":755,"meta":724,"style":724},"type PaymentHookContext = { payment: PaymentDto }\n\ntype CheckoutBeforeContext = {\n  event?: H3Event\n  userId: number\n  reference?: { type: string, id: string }\n  params: Stripe.Checkout.SessionCreateParams   \u002F\u002F mutable\n}\n",[604,2468,2469,2488,2492,2503,2513,2521,2545,2568],{"__ignoreMap":724},[728,2470,2471,2473,2476,2478,2480,2482,2484,2486],{"class":730,"line":731},[728,2472,1662],{"class":1067},[728,2474,2475],{"class":734}," PaymentHookContext",[728,2477,1094],{"class":777},[728,2479,839],{"class":777},[728,2481,1384],{"class":784},[728,2483,788],{"class":777},[728,2485,1968],{"class":734},[728,2487,1311],{"class":777},[728,2489,2490],{"class":730,"line":781},[728,2491,1725],{"emptyLinePlaceholder":1724},[728,2493,2494,2496,2499,2501],{"class":730,"line":820},[728,2495,1662],{"class":1067},[728,2497,2498],{"class":734}," CheckoutBeforeContext",[728,2500,1094],{"class":777},[728,2502,828],{"class":777},[728,2504,2505,2508,2510],{"class":730,"line":831},[728,2506,2507],{"class":784},"  event",[728,2509,1754],{"class":777},[728,2511,2512],{"class":734}," H3Event\n",[728,2514,2515,2517,2519],{"class":730,"line":854},[728,2516,1820],{"class":784},[728,2518,788],{"class":777},[728,2520,1825],{"class":734},[728,2522,2523,2525,2527,2529,2531,2533,2535,2537,2539,2541,2543],{"class":730,"line":860},[728,2524,1847],{"class":784},[728,2526,1754],{"class":777},[728,2528,839],{"class":777},[728,2530,1229],{"class":784},[728,2532,788],{"class":777},[728,2534,1779],{"class":734},[728,2536,801],{"class":777},[728,2538,1243],{"class":784},[728,2540,788],{"class":777},[728,2542,1779],{"class":734},[728,2544,1311],{"class":777},[728,2546,2547,2550,2552,2555,2557,2560,2562,2565],{"class":730,"line":1016},[728,2548,2549],{"class":784},"  params",[728,2551,788],{"class":777},[728,2553,2554],{"class":734}," Stripe",[728,2556,599],{"class":777},[728,2558,2559],{"class":734},"Checkout",[728,2561,599],{"class":777},[728,2563,2564],{"class":734},"SessionCreateParams",[728,2566,2567],{"class":816},"   \u002F\u002F mutable\n",[728,2569,2570],{"class":730,"line":1273},[728,2571,1799],{"class":777},[593,2573,2574,2575,2577,2578,2580],{},"A status change happens once. A redelivered Stripe event fires no hook twice, and a late ",[604,2576,1698],{}," event never\ndowngrades a ",[604,2579,1458],{}," payment.",[609,2582,2584],{"id":2583},"routes","Routes",[593,2586,2587],{},"Routes the module registers, and who may call them.",[1474,2589,2590,2607],{},[1477,2591,2592],{},[1480,2593,2594,2597,2600,2602,2605],{},[1483,2595,2596],{},"Method",[1483,2598,2599],{},"Path",[1483,2601,168],{},[1483,2603,2604],{},"Status",[1483,2606,1494],{},[1496,2608,2609,2634,2658,2678],{},[1480,2610,2611,2616,2621,2625,2628],{},[1501,2612,2613],{},[604,2614,2615],{},"GET",[1501,2617,2618],{},[604,2619,2620],{},"\u002Fapi\u002Fpayments\u002Fme",[1501,2622,2623],{},[604,2624,2283],{},[1501,2626,2627],{},"200",[1501,2629,2630,2631,2363],{},"The signed-in user's payments (",[604,2632,2633],{},"PaymentDto[]",[1480,2635,2636,2641,2646,2651,2653],{},[1501,2637,2638],{},[604,2639,2640],{},"POST",[1501,2642,2643],{},[604,2644,2645],{},"\u002Fapi\u002Fpayments\u002Fme\u002F:id\u002Fresume",[1501,2647,2648],{},[604,2649,2650],{},"payments:write",[1501,2652,2627],{},[1501,2654,2655,2657],{},[604,2656,1605],{}," for one of the caller's unpaid payments.",[1480,2659,2660,2664,2669,2673,2675],{},[1501,2661,2662],{},[604,2663,2615],{},[1501,2665,2666],{},[604,2667,2668],{},"\u002Fapi\u002Fadmin\u002Fpayments\u002Frecent",[1501,2670,2671],{},[604,2672,630],{},[1501,2674,2627],{},[1501,2676,2677],{},"30-day revenue per currency and the latest settled payments.",[1480,2679,2680,2684,2689,2695,2697],{},[1501,2681,2682],{},[604,2683,2615],{},[1501,2685,2686],{},[604,2687,2688],{},"\u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fpayments",[1501,2690,2691,2694],{},[604,2692,2693],{},"users:read",", and the user must not outrank the caller",[1501,2696,2627],{},[1501,2698,2699,2700,2703],{},"A user's payments, newest first. ",[604,2701,2702],{},"?limit="," is 1 to 500, default 100.",[614,2705,2706,2717,2731],{},[617,2707,2708,2709,2712,2713,2716],{},"The resume route answers ",[604,2710,2711],{},"404 not_found"," for someone else's payment and ",[604,2714,2715],{},"409 conflict"," when it is already paid.",[617,2718,2719,2720,2723,2724,2727,2728,2730],{},"The ",[604,2721,2722],{},"\u002Fme"," routes also accept an ",[597,2725,2726],{"href":87},"API token"," or an access token whose scope covers the\npermission, such as the ",[604,2729,895],{}," scope.",[617,2732,2733,2734,2737,2738,599],{},"Path builders are ",[604,2735,2736],{},"paymentsApi"," from ",[604,2739,2740],{},"@frigear-nu\u002Fpayments\u002Fapi",[609,2742,2744],{"id":2743},"permissions","Permissions",[593,2746,2747,2748,2750,2751,2754,2755,2758],{},"The module registers these permissions with ",[597,2749,199],{"href":200},". A route calls\n",[604,2752,2753],{},"authorize(event, 'payments:read')",", which passes only when the caller's roles, the ",[604,2756,2757],{},"authorization:before"," hook and any\npolicy allow it.",[1474,2760,2761,2777],{},[1477,2762,2763],{},[1480,2764,2765,2768,2771,2774],{},[1483,2766,2767],{},"Permission",[1483,2769,2770],{},"Flags",[1483,2772,2773],{},"Held by default",[1483,2775,2776],{},"What it allows",[1496,2778,2779,2794,2807],{},[1480,2780,2781,2785,2788,2791],{},[1501,2782,2783],{},[604,2784,2283],{},[1501,2786,2787],{},"implicit",[1501,2789,2790],{},"every signed-in user",[1501,2792,2793],{},"Read your own payments.",[1480,2795,2796,2800,2802,2804],{},[1501,2797,2798],{},[604,2799,2650],{},[1501,2801,2787],{},[1501,2803,2790],{},[1501,2805,2806],{},"Resume paying for your own unpaid payments.",[1480,2808,2809,2813,2815,2819],{},[1501,2810,2811],{},[604,2812,630],{},[1501,2814],{},[1501,2816,2817],{},[604,2818,634],{},[1501,2820,2821],{},"See recent payments and revenue on the dashboard.",[614,2823,2824,2830,2843,2854],{},[617,2825,2826,2829],{},[620,2827,2828],{},"Implicit"," permissions work even when Authorization is not installed, so self-service keeps working.",[617,2831,2832,677,2835,2837,2838,661,2840,2842],{},[620,2833,2834],{},"Scope:",[604,2836,895],{}," (label \"Your payments\") expands to ",[604,2839,2283],{},[604,2841,2650],{},". A token or OAuth client\nwith this scope can read and resume the user's own payments, and nothing else.",[617,2844,2845,2848,2849,2851,2852,599],{},[620,2846,2847],{},"Roles and policies:"," the module ships no role, requirement or policy. Staff access comes from the ",[604,2850,634],{}," role, or\nfrom any role of yours that grants ",[604,2853,630],{},[617,2855,2856,2857,2860,2861,2863,2864,2866],{},"Reading another user's payments (",[604,2858,2859],{},"GET \u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fpayments",") needs ",[604,2862,2693],{}," from\n",[597,2865,191],{"href":192},", not a payments permission. The caller must also hold every permission the target\nuser holds, so a coordinator cannot read an admin's payments.",[593,2868,2869,2870,2872,2873,2876,2877,599],{},"For the full model, see ",[597,2871,199],{"href":200},", including\n",[597,2874,2875],{"href":206},"roles and requirements"," and\n",[597,2878,2879],{"href":210},"policies",[609,2881,41],{"id":2882},"database",[593,2884,2885,2886,2889],{},"Tables the module adds. Generate and commit a ",[597,2887,891],{"href":2888},"\u002Fget-started\u002Fdatabase#migrations"," after installing.",[593,2891,2892,2893,2895],{},"The module adds one ",[604,2894,895],{}," table.",[1474,2897,2898,2910],{},[1477,2899,2900],{},[1480,2901,2902,2905,2907],{},[1483,2903,2904],{},"Column",[1483,2906,1488],{},[1483,2908,2909],{},"Notes",[1496,2911,2912,2927,2943,2961,2975,2987,3000,3013,3029,3041,3052,3067,3082],{},[1480,2913,2914,2918,2921],{},[1501,2915,2916],{},[604,2917,1158],{},[1501,2919,2920],{},"text, primary key",[1501,2922,2923,2926],{},[604,2924,2925],{},"pay_"," and a random id.",[1480,2928,2929,2934,2937],{},[1501,2930,2931],{},[604,2932,2933],{},"userId",[1501,2935,2936],{},"integer",[1501,2938,2939,2940,599],{},"Indexed. No foreign key to ",[604,2941,2942],{},"users",[1480,2944,2945,2950,2953],{},[1501,2946,2947],{},[604,2948,2949],{},"status",[1501,2951,2952],{},"text",[1501,2954,2955,2958,2959,599],{},[604,2956,2957],{},"PaymentStatus",", default ",[604,2960,1588],{},[1480,2962,2963,2969,2972],{},[1501,2964,2965,644,2967],{},[604,2966,2291],{},[604,2968,2302],{},[1501,2970,2971],{},"integer, text",[1501,2973,2974],{},"Minor units.",[1480,2976,2977,2982,2985],{},[1501,2978,2979],{},[604,2980,2981],{},"description",[1501,2983,2984],{},"text, nullable",[1501,2986],{},[1480,2988,2989,2995,2997],{},[1501,2990,2991,644,2993],{},[604,2992,1406],{},[604,2994,2245],{},[1501,2996,2984],{},[1501,2998,2999],{},"Indexed together.",[1480,3001,3002,3007,3010],{},[1501,3003,3004],{},[604,3005,3006],{},"checkoutSessionId",[1501,3008,3009],{},"text, unique, nullable",[1501,3011,3012],{},"Follows the new session after a resume. Null for invoices.",[1480,3014,3015,3020,3022],{},[1501,3016,3017],{},[604,3018,3019],{},"invoiceId",[1501,3021,3009],{},[1501,3023,3024,3025,599],{},"The Stripe invoice id of a ",[597,3026,3028],{"href":3027},"#subscription-invoices","subscription invoice",[1480,3030,3031,3036,3038],{},[1501,3032,3033],{},[604,3034,3035],{},"paymentIntentId",[1501,3037,2984],{},[1501,3039,3040],{},"Indexed.",[1480,3042,3043,3047,3049],{},[1501,3044,3045],{},[604,3046,2294],{},[1501,3048,2936],{},[1501,3050,3051],{},"Default 0.",[1480,3053,3054,3059,3062],{},[1501,3055,3056],{},[604,3057,3058],{},"metadata",[1501,3060,3061],{},"JSON, nullable",[1501,3063,3064,599],{},[604,3065,3066],{},"Record\u003Cstring, string>",[1480,3068,3069,3074,3076],{},[1501,3070,3071],{},[604,3072,3073],{},"items",[1501,3075,3061],{},[1501,3077,2719,3078,3081],{},[604,3079,3080],{},"PaymentItem[]"," of the session. Null for older rows.",[1480,3083,3084,3095,3098],{},[1501,3085,3086,644,3089,644,3092],{},[604,3087,3088],{},"paidAt",[604,3090,3091],{},"createdAt",[604,3093,3094],{},"updatedAt",[1501,3096,3097],{},"timestamps",[1501,3099],{},[609,3101,395],{"id":3102},"translations",[593,3104,3105,3106,599],{},"Override any string in your app's ",[604,3107,3108],{},"i18n\u002Flocales\u002F\u003Ccode>.json",[593,3110,3111,3112,661,3115,3118,3119,3121,3122,3125,3126,644,3129,661,3132,3135],{},"The module registers ",[604,3113,3114],{},"da",[604,3116,3117],{},"en"," files with ",[597,3120,381],{"href":396}," under ",[604,3123,3124],{},"payments.*",". The\nkeys are ",[604,3127,3128],{},"payments.status.\u003Cstatus>",[604,3130,3131],{},"payments.defaultDescription",[604,3133,3134],{},"payments.admin.*",". API error messages stay in\nEnglish.",[719,3137,3141],{"className":3138,"code":3139,"language":3140,"meta":724,"style":724},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{ \"payments\": { \"status\": { \"partially_refunded\": \"Partly refunded\" } } }\n","json",[604,3142,3143],{"__ignoreMap":724},[728,3144,3145,3147,3150,3152,3155,3157,3159,3161,3163,3165,3167,3169,3171,3173,3175,3177,3179,3182,3184,3186,3188],{"class":730,"line":731},[728,3146,1172],{"class":777},[728,3148,3149],{"class":777}," \"",[728,3151,895],{"class":1067},[728,3153,3154],{"class":777},"\"",[728,3156,788],{"class":777},[728,3158,839],{"class":777},[728,3160,3149],{"class":777},[728,3162,2949],{"class":734},[728,3164,3154],{"class":777},[728,3166,788],{"class":777},[728,3168,839],{"class":777},[728,3170,3149],{"class":777},[728,3172,1716],{"class":847},[728,3174,3154],{"class":777},[728,3176,788],{"class":777},[728,3178,3149],{"class":777},[728,3180,3181],{"class":738},"Partly refunded",[728,3183,3154],{"class":777},[728,3185,1120],{"class":777},[728,3187,1120],{"class":777},[728,3189,1311],{"class":777},[609,3191,3193],{"id":3192},"next-steps","Next steps",[614,3195,3196,3201],{},[617,3197,3198,3200],{},[597,3199,146],{"href":147}," – connect Stripe so payments are marked as paid.",[617,3202,3203,3205],{},[597,3204,490],{"href":491}," – see Events take payments through this module.",[3207,3208,3209],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":724,"searchDepth":781,"depth":781,"links":3211},[3212,3213,3221,3222,3226,3227,3228,3229,3230,3231,3232],{"id":611,"depth":781,"text":612},{"id":708,"depth":781,"text":709,"children":3214},[3215,3216,3217,3218,3219,3220],{"id":716,"depth":820,"text":717},{"id":748,"depth":820,"text":749},{"id":877,"depth":820,"text":878},{"id":899,"depth":820,"text":900},{"id":915,"depth":820,"text":916},{"id":1032,"depth":820,"text":1033},{"id":1465,"depth":781,"text":1466},{"id":1554,"depth":781,"text":1555,"children":3223},[3224,3225],{"id":2213,"depth":820,"text":2214},{"id":2270,"depth":820,"text":2271},{"id":2306,"depth":781,"text":267},{"id":1359,"depth":781,"text":234},{"id":2583,"depth":781,"text":2584},{"id":2743,"depth":781,"text":2744},{"id":2882,"depth":781,"text":41},{"id":3102,"depth":781,"text":395},{"id":3192,"depth":781,"text":3193},"Charge a signed-in user once through Stripe Checkout, and hear through a hook when the money arrives.","md",null,{},{"title":254,"description":3233},"aDC4fi1u20Ha0fAMTjsDi7lN7iB0A7M02inQoTki9EE",[3240,3242],{"title":250,"path":251,"stem":252,"description":3241,"children":-1},"Gives your app one verified Stripe webhook and a Stripe customer per user, for Payments and Subscriptions.",{"title":173,"path":259,"stem":260,"description":3243,"children":-1},"Sell recurring plans, such as a yearly membership, through Stripe, and check which plan a user holds.",1794503148432]