Membership Downgrades
A downgrade takes effect at the end of the current billing cycle: the user requests it, the membership is marked pending, and the Subscription Service calls back to finalize it when the cycle ends. Error bodies are the ErrorResponse schema (error_code 9 for initiate, 10 for finalize, with an error_string) in the API Specification; the M… names below identify the branch that produced them.
Initiate
POST /{user_id}/user/membership/downgrade with downgrade_tier.
-
Load the GrowthBook tier configuration (
500 M2_CONFIG_FETCH_FAILED) and resolve the tier’s current version (400 M8_INVALID_TIER/M9_TIER_VERSION_NOT_FOUND). -
The user must exist (
404 M3_USER_NOT_FOUND) and beACTIVE(403 M4_USER_NOT_ACTIVE); a membership must exist (404 M5_MEMBERSHIP_NOT_FOUND). -
Schedule the downgrade in the Subscription Service with the tier and version; it returns the date the downgrade takes effect (
500 M19_DOWNGRADE_FAILEDon failure, a reply other than201, or an unparseable date). -
Re-write the current membership with event
MEMBERSHIP_DOWNGRADE,is_pending_downgradetrue,downgrade_dateand the caller-derived source (500 M18_MEMBERSHIP_RECORD_CREATE_FAILED). -
201with the membership. Itstieris still the current tier; the target tier is only known to the Subscription Service until finalization. Metricuser.membership.downgradewithfrom_tier:andto_tier:.
Finalize
POST /{user_id}/user/membership/downgrade/finalize with downgrade_tier and downgrade_version, called by the Subscription Service at the end of the cycle. Internal only; it is not exposed to the mobile app.
-
A membership must exist (
404 M5_MEMBERSHIP_NOT_FOUND) and be pending a downgrade (403 M20_MEMBERSHIP_NOT_PENDING_DOWNGRADE). -
Write a new membership:
<DOWNGRADE_TIER>/MONTHLYatdowngrade_version, eventMEMBERSHIP_DOWNGRADE_FINALIZED, caller-derived source (500 M18_MEMBERSHIP_RECORD_CREATE_FAILED). -
201with an empty body. Metricuser.membership.finalize_downgrade.
Retraction
A pending downgrade is cancelled by upgrading back to the current tier, which costs nothing. A scheduled downgrade does not survive a pause: the pause record (self-service or admin) is written without is_pending_downgrade and downgrade_date, so the flag is cleared and a later finalize call is answered 403 M20_MEMBERSHIP_NOT_PENDING_DOWNGRADE. Unpause carries forward whatever the paused record holds.