---
title: "Upgrade plan (Pro or Scale)"
method: POST
path: "/api/billing/upgrade"
tags: ["Billing"]
---

# Upgrade plan (Pro or Scale)

`POST /api/billing/upgrade`

## Request

- Base URL: `https://trydock.ai`
- URL: `https://trydock.ai/api/billing/upgrade`
- Auth: HTTP bearer

Upgrade or switch to a paid plan. **Behavior depends on principal type:**

- **HUMAN** (session cookie): one-call execution. The Settings UI click is itself the consent signal.
- **AGENT** (DK key): a plan switch, or a same-plan call while a downgrade is scheduled, returns `{ status: "approval_required", approval_url, polling_url, expires_at }`. The agent prints the approval URL in chat; only the org owner can approve it, and the agent polls `/api/web-approve/status`. `confirm_token` and `mode` are ignored.

**Fast paths** (both principal types): no existing subscription returns a Checkout URL; same-plan + scheduled-cancel resumes; design-partner orgs no-op at Scale.

## Request body

- object
  - `plan` 'pro' | 'scale': Target plan. Defaults to `pro`.
  - `confirm_token` string: Ignored. Agents always get a web approval; people execute directly.
  - `mode` 'chat' | 'web': Ignored. Agents always get a web approval; people execute directly.

## Response `200`

Discriminated by `status`: `switched` | `resumed` | `checkout-required` | `approval_required` | `design-partner`.

- object
  - `plan` 'free' | 'pro' | 'scale': Plan tier. Caps live in `src/lib/plan.ts`.
  - `status` string, required
  - `checkoutUrl` string, uri
  - `targetPlan` 'pro' | 'scale'
  - `message` string
  - `approval_url` string, uri: Agents only: the page the org owner opens to approve.
  - `polling_url` string, uri
  - `expires_at` string

## Other responses

- `400`: Stripe not configured, or a seat org.

## Changes

- **2026-11-05** `767beae124a8`: 3 warning, 3 info
  - removed the optional property `confirm_token` from the response with the `200` status
  - removed the optional property `expires_in` from the response with the `200` status
  - removed the optional property `url` from the response with the `200` status
  - added the optional property `approval_url` to the response with the `200` status
  - …2 more

[Operation history](https://skmtc.dev/trydock/apis/dock-rest-api/changes/api/billing/upgrade/post.md)

---

[API](https://skmtc.dev/trydock/apis/dock-rest-api.md) - [All operations](https://skmtc.dev/trydock/apis/dock-rest-api/llms.txt) - [OpenAPI document](https://skmtc.dev/trydock/apis/dock-rest-api/revisions/dd96ae96a412?raw)
