{"record":{"id":"3f33f8954ad4c6be","repo":"Significant-Gravitas/AutoGPT","slug":"enterprise-subscription-changes-must-be-managed-by","errorCode":null,"errorMessage":"ENTERPRISE subscription changes must be managed by an administrator","messagePattern":"ENTERPRISE subscription changes must be managed by an administrator","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"warning","filePath":"autogpt_platform/backend/backend/api/features/v1.py","lineNumber":1086,"sourceCode":"async def update_subscription_tier(\n    request: SubscriptionTierRequest,\n    user_id: Annotated[str, Security(get_user_id)],\n    x_datafast_visitor_id: Annotated[\n        str | None, Header(include_in_schema=False)\n    ] = None,\n    x_datafast_session_id: Annotated[\n        str | None, Header(include_in_schema=False)\n    ] = None,\n) -> SubscriptionStatusResponse:\n    # Pydantic validates tier is one of BASIC/PRO/MAX/BUSINESS via Literal type.\n    tier = SubscriptionTier(request.tier)\n\n    # ENTERPRISE tier is admin-managed — block self-service changes from ENTERPRISE users.\n    user = await get_user_by_id(user_id)\n    if (\n        user.subscription_tier or SubscriptionTier.NO_TIER\n    ) == SubscriptionTier.ENTERPRISE:\n        raise HTTPException(\n            status_code=403,\n            detail=\"ENTERPRISE subscription changes must be managed by an administrator\",\n        )\n\n    # Same-tier + same-cycle request = \"stay on my current tier\" = cancel any\n    # pending scheduled change (paid→paid downgrade or paid→BASIC cancel). This\n    # replaces the old /credits/subscription/cancel-pending route. Safe when no\n    # pending change exists: release_pending_subscription_schedule returns\n    # False and we simply return the current status.\n    #\n    # Same-tier-DIFFERENT-cycle (monthly Pro → yearly Pro, or vice versa) must\n    # fall through to modify_stripe_subscription_for_tier so Stripe swaps the\n    # price ID for the cycle the user actually requested.\n    #\n    # Gate the short-circuit on an actual active/trialing Stripe subscription:\n    # admin-granted tiers (DB tier set, no Stripe sub) must fall through to the\n    # Checkout flow so \"start paying for my current tier\" is not a no-op.\n    current_tier = user.subscription_tier or SubscriptionTier.NO_TIER","sourceCodeStart":1068,"sourceCodeEnd":1104,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/v1.py#L1068-L1104","documentation":"HTTP 403 from POST /credits/subscription when the caller's current subscription_tier is ENTERPRISE. Enterprise contracts are provisioned and changed by administrators (custom Stripe pricing, invoices, contracts), so self-service tier changes are blocked for those users regardless of the requested target tier.","triggerScenarios":"Any POST /credits/subscription (upgrade, downgrade, or cancel) issued by a user whose user.subscription_tier == ENTERPRISE.","commonSituations":"Enterprise users clicking through the pricing page after their org was migrated to ENTERPRISE; stale frontend still showing tier-change buttons for enterprise accounts; test users upgraded to ENTERPRISE by an admin script while old UI sessions remain open.","solutions":["Hide the self-service subscription controls in the frontend when the current tier is ENTERPRISE","Contact the platform administrator / support to change an ENTERPRISE subscription","For testing: have an admin reset the user's tier before retrying self-service flows"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function canSelfServeSubscription(tier: SubscriptionTier): boolean {\n  return tier !== \"ENTERPRISE\";\n}","tryCatchPattern":"try { await api.setSubscription(req); }\ncatch (e) { if (e.status === 403 && /ENTERPRISE/.test(e.detail)) showContactAdmin(); else throw e; }","preventionTips":["Gate tier-change UI on the current tier from GET /credits/subscription","Show 'managed by your administrator' messaging for ENTERPRISE users"],"tags":["billing","subscription","enterprise","http-403","authorization"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}