---
title: "Switch subscription plan"
method: POST
path: "/billing/switch_plan/"
tags: ["billing"]
---

# Switch subscription plan

`POST /billing/switch_plan/`

## Request

- Base URL: `https://api.getoneprofile.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.getoneprofile.ai/billing/switch_plan/`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Switch the organization to a new subscription plan, credit volume, or billing interval. Returns the Stripe URL to send the customer to: hosted Checkout for a first paid subscription, or the billing portal's confirmation flow for a change to an existing one, where Stripe shows the proration and takes the confirmation.

## Request body

- SwitchPlanRequest: Request schema for switching subscription plan.
  - `billing_interval` 'month' | 'year': The billing interval to subscribe with.
  - `cancel_path` string, required: Partial path (e.g. /billing/plans) of where the stripe Checkout session should redirect the user if payment is cancelled.
  - `credit_tier_key` string, nullable: The credit tier to subscribe to (e.g. 'tier_20k'). Required for products with selectable credit tiers (the Team plan).
  - `new_product` 'free_plan' | 'team_plan' | 'pro_plan' | 'enterprise_plan', required: The tier of a product in Stripe. Declared cheapest-first. Free and Enterprise never touch Stripe: Free is free, Enterprise is sales-led and has no self-serve price. A subscription's tier is recovered from its price's ``product_tier`` metadata, never by reverse-parsing a Stripe product name: a product is named for the plan AND the credit volume it sells ("Team Plan (10,000 credits)"), so the name has not round-tripped to a tier since prices collapsed to one per plan+volume.
  - `success_path` string, required: Partial path (e.g. /billing/complete) of where the stripe Checkout session should redirect the user if payment is successful.

## Response `200`

Successful Response

- SwitchPlanRedirectResponse: Where to send the customer to complete the plan change. There is no "completed" case: Stripe confirms every plan change, so this always carries a URL to leave for.
  - `redirect_url` string, uri, required: The URL to redirect the customer to.
  - `type` 'checkout' | 'portal', required: Which Stripe surface completes the change: 'checkout' for a first paid subscription, 'portal' for a change to an existing one.

## Other responses

- `401`: Unauthorized
- `403`: Forbidden
- `422`: Invalid plan switch request
- `500`: Internal server error.
- `502`: Bad gateway error.
- `503`: Service unavailable.

---

[API](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile.md) · [All operations](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile/llms.txt) · [OpenAPI document](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile/revisions/dc5ac3c84444?raw)
