---
title: "Assign a plan to a company"
method: POST
path: "/companies/{id}/plan-assignments"
tags: ["Companies"]
---

# Assign a plan to a company

`POST /companies/{id}/plan-assignments`

## Request

- Base URL: `https://api.cavuno.com/v1`
- URL: `https://api.cavuno.com/v1/companies/{id}/plan-assignments`
- Auth: HTTP bearer

Gives a company a membership plan at no charge, the same as **Assign** in the company plan dialog. The plan must be an active membership plan. A company holds one membership at a time: assigning while it has an active membership, or a membership invoice awaiting payment, returns 409 `company_plan_membership_taken`. To charge for the plan, create a plan invoice instead. Accepts an optional `Idempotency-Key` header. Requires `plans.manage`.

## Path parameters

- `id` string, required: The company's opaque object `id`: the `id` field returned by the company endpoints (e.g. `p17xq4c2b9r5gz3e8j0r6t4k7m2n9d5w`). This is NOT the `slug` or display name; passing a slug like `antler` returns 404. To look up a company by name or slug, use `GET /v1/companies`, `POST /v1/companies/search`, or `POST /v1/companies/find-or-create` and read the returned `id`.

## Request body

- CreateCompanyPlanAssignmentBody
  - `planId` string, required: An active (not archived) plan with `purpose: membership` on this board.
  - `expiresAt` string, date-time: ISO-8601 time the assignment ends; must be in the future. Omit for no end.

## Response `201`

The new plan assignment.

- CompanyPlanAssignment
  - `id` string, required: The plan assignment ID.
  - `object` 'company_plan_assignment', required
  - `companyId` string, required
  - `planId` string, nullable, required: The assigned plan. Null for a custom level granted in the dashboard without a plan.
  - `planName` string, nullable, required
  - `source` 'manual' | 'purchase' | 'invoice' | 'synced', required: `manual`: assigned by an operator. `purchase`: bought at checkout. `invoice`: granted when a plan invoice was paid. `synced`: set by a membership sync.
  - `status` 'active' | 'expired' | 'revoked', required: Only `active` assignments give the company its plan benefits.
  - `expiresAt` string, nullable, required: ISO-8601 time the assignment ends, or null for no end.
  - `createdAt` string, required: ISO-8601 creation time.
  - `updatedAt` string, required: ISO-8601 time of the last change.

## Other responses

- `400`: Invalid body, or `expiresAt` is not in the future.
- `404`: Company or plan not found.
- `409`: The plan is archived or not a membership plan (`company_plan_not_assignable`), or the company already has a membership or a membership invoice awaiting payment (`company_plan_membership_taken`).

## Changes

- **2026-10-20** `de39bd3242e2`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/cavuno/apis/cavuno-v1-rest-api/changes/companies/:id/plan-assignments/post.md)

---

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