{"record":{"id":"9a2e5aca9ba71364","repo":"gitroomhq/postiz-app","slug":"unauthorized-9a2e5a","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":"HttpException","httpStatus":400,"severity":"error","filePath":"apps/backend/src/api/routes/billing.controller.ts","lineNumber":162,"sourceCode":"\n    return this._stripeService.setToCancel(org.id);\n  }\n\n  @Post('/prorate')\n  prorate(\n    @GetOrgFromRequest() org: Organization,\n    @Body() body: BillingSubscribeDto\n  ) {\n    return this._stripeService.prorate(org.id, body);\n  }\n\n  @Get('/charges')\n  async getCharges(\n    @GetUserFromRequest() user: User,\n    @GetOrgFromRequest() org: Organization\n  ) {\n    if (!user.isSuperAdmin) {\n      throw new HttpException('Unauthorized', 400);\n    }\n\n    return this._stripeService.getCharges(org.id);\n  }\n\n  @Post('/refund-charges')\n  async refundCharges(\n    @GetUserFromRequest() user: User,\n    @GetOrgFromRequest() org: Organization,\n    @Body() body: { chargeIds: string[] }\n  ) {\n    if (!user.isSuperAdmin) {\n      throw new HttpException('Unauthorized', 400);\n    }\n\n    return this._stripeService.refundCharges(org.id, body.chargeIds);\n  }\n","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/apps/backend/src/api/routes/billing.controller.ts#L144-L180","documentation":"GET /billing/charges returns Stripe charges for the current organization but is gated to super admins (instance operators), not org members. Non-super-admin users receive HttpException('Unauthorized', 400).","triggerScenarios":"A regular org user or org admin hitting GET /billing/charges for their organization; only the platform super admin may view raw Stripe charges.","commonSituations":"Building custom billing UI on a self-hosted instance and assuming org admins can list charges; using a normal user's API token.","solutions":["Authenticate as the instance super admin before calling this endpoint","If you need org-level billing history as a normal user, use the user-facing billing endpoints instead of /billing/charges","Verify isSuperAdmin on your User record"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"const user = await getMe();\nif (user.isSuperAdmin) await fetchCharges(orgId);","typeGuard":"const canViewCharges = (u: User) => u.isSuperAdmin === true;","tryCatchPattern":"try { await getCharges(); } catch (e) { if (unauthorized(e)) redirect('/settings/billing'); else throw e; }","preventionTips":["Use user-facing billing endpoints for org members","Keep operator tooling on a dedicated super-admin account"],"tags":["authorization","billing","stripe","super-admin"],"backgroundTag":"authorization-denied","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}