> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tuco.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscribe a Client to a Plan

> Put a client workspace on a Tuco plan, charged to your agency card — one call, no checkout page.

<Note>
  This is **not** a hosted-checkout redirect. The subscription is created directly
  against your agency's saved card, so a script can run it. It was the last step of
  client onboarding that needed a browser.
</Note>

## Endpoint

* **Method**: `POST`
* **Path**: `/api/agency/billing/subscribe`
* **Auth**: `Authorization: Bearer tucoagency_xxxxxxxxxxxxx` ([agency key](/api-reference/agency-api-keys))

## Body

| Field | Type | Required | Notes |
| - | - | - | - |
| `workspaceId` | string | yes | A client workspace in your agency |
| `plan` | string | yes | `starter` or `growth`. Mini is retired for agencies |

```bash theme={null}
curl https://app.tuco.ai/api/agency/billing/subscribe \
  -H "Authorization: Bearer tucoagency_xxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"workspaceId":"org_3KKJKupHJ8Y9I2NXVAga0c6ZqgT","plan":"starter"}'
```

```json theme={null}
{ "success": true, "subscriptionId": "sub_1QX…", "status": "active", "plan": "starter" }
```

## You need a card on file first

The charge goes to the **agency owner's** saved payment method, off-session. If
there isn't one, you get `400 no_card` — add it from Agency view → Billing, then
retry. Any agency member (or key) can subscribe a workspace; the charge always
lands on the owner's card, so nobody can mis-bill anyone else.

The setup fee, if your agency pays one, lands on the subscription's first invoice
together with the first month — the same site pricing a direct customer pays,
minus whatever discount is attached to your agency.

## If Tuco invoices your agency directly

Agencies on **invoice billing** don't need a card at all. The same call puts the
client on a plan, creates **no Stripe subscription**, and charges nothing — Tuco
bills your agency offline for the whole group.

```json theme={null}
{ "success": true, "subscriptionId": null, "status": "active", "plan": "growth", "billingMode": "invoice" }
```

`subscriptionId` is `null` and the client workspace gets no `stripeCustomerId`.
That absence is the point: **your clients cannot be dunned, emailed about a
failed payment, or sent to a checkout page, because they do not exist in Stripe
at all.** Add-on lines work the same way — the slot is granted and appears on
your agency's next invoice.

Invoice billing is set by Tuco on your agency account, not self-serve. Ask us.

## Why the plan is still required either way

It's tempting to read "we invoice our own clients" as "no subscription record
at all". That breaks the product: a workspace's **plan is what grants its
entitlements**. `organizations.plan` sets how many phone and email lines it may
hold, and an agency workspace left at `subscriptionStatus: 'none'` is refused
outright by the line guard — it cannot order a line, and a transfer into it is
rejected with "Target workspace has no active subscription".

So subscribe every client, in either mode. A plan is an **entitlement**, not a
charge. What you control is the **price**: on Stripe billing that's your
agency's discount coupon; on invoice billing it's whatever we agreed. Either
way, what you charge your client on your own invoice is separate and Tuco never
sees it.

## Error responses

| Status | Code | When |
| - | - | - |
| `400` | `no_card` | No saved payment method on the agency. **Not possible on invoice billing** — no card is needed |
| `400` | `already_subscribed` | That workspace already has a subscription |
| `400` | — | Missing `workspaceId`/`plan`, or a retired plan |
| `401` | `UNAUTHORIZED` | Missing, unknown, revoked or expired key |
| `403` | `AGENCY_KEY_REQUIRED` | A workspace key (`tuco_…`) was used |
| `403` | — | That workspace is not part of your agency |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.