---
title: "Change the subscription plan"
method: POST
path: "/v1/billing/subscription/plan"
tags: ["Billing"]
---

# Change the subscription plan

`POST /v1/billing/subscription/plan`

## Request

- Base URL: `https://api.recruitmcp.com`
- URL: `https://api.recruitmcp.com/v1/billing/subscription/plan`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://recruitmcp.com/oauth/authorize`, token URL `https://recruitmcp.com/oauth/token`, scopes: `billing:manage`)

An upgrade charges the prorated price difference right away. The plan changes only once that invoice is paid; then the workspace gets the new plan's monthly credits minus the old plan's, once per change. status is upgraded when the payment went through, requires_action when the card needs authentication on hosted_invoice_url, and payment_failed when it was declined (the plan does not change). A downgrade (status scheduled_downgrade) is not prorated: there is no refund and no credits are taken back. The plan stays as it is until the next cycle, effective_at; then the lower price and credits start. Asking for the current plan while a downgrade is scheduled cancels the downgrade (status downgrade_canceled). An upgrade while a downgrade is scheduled is refused with status downgrade_scheduled (scheduled_plan and effective_at name the downgrade): cancel the downgrade first. While an upgrade payment is still pending, any change is refused with status payment_pending and hosted_invoice_url. While the plan is set to cancel in the billing portal, any change is refused with status cancel_scheduled, effective_at (the cancel date) and a message: resume the plan in the billing portal first. A subscription without automatic tax is refused with status tax_location_required and a message while the billing address cannot be used to add VAT: add it in the billing portal, then try again. Nothing is changed or charged on a refusal.

Scope: `billing:manage`. Acts on the account; keys bound to a customer are refused.

## Headers

- `Idempotency-Key` string
- `RecruitMCP-Version` '2026-10-13'

## Request body

- object
  - `plan` string, required: Plan id: starter, growth, or scale.

## Response `200`

The updated subscription.

- object

## Other responses

- `400`: `invalid_request` (do not retry): A field is missing or has a value this endpoint does not accept. `unsupported_version` (do not retry): RecruitMCP-Version is not a supported version.
- `401`: `unauthorized` (do not retry): Missing bearer API key.
- `403`: `forbidden` (do not retry): This route acts on the account. Keys bound to a customer cannot use it. `insufficient_scope` (do not retry): This key does not include the scope this endpoint requires.
- `409`: `conflict` (do not retry): The resource is in a state that refuses this change.
- `429`: `rate_limited` (retry): Per-key rate limit exceeded.

## Changes

- **2026-10-20** `ad27b35513a6`: 5 warning
  - added the new `approval_forced` enum value to the `error/code` response property for the response status `400`
  - added the new `approval_forced` enum value to the `error/code` response property for the response status `401`
  - added the new `approval_forced` enum value to the `error/code` response property for the response status `403`
  - added the new `approval_forced` enum value to the `error/code` response property for the response status `409`
  - …1 more

[Operation history](https://skmtc.dev/recruitmcp/apis/recruitmcp-api/changes/v1/billing/subscription/plan/post.md)

---

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