### Create a plan

`POST /api/v1/profiles`

name and type are the only required fields; everything else has a schema default. A plan created with no enforce toggles on is an unlimited plan.

- Authentication: manager session (JWT) or API token
- Permission: `prm_profiles_create` (Create profiles)
- Risk: write
- Rate limit bucket: `t_mutate`

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `name` | body | string | yes | Display name. |
| `type` | body | enum | yes | prepaid, postpaid, fup, extension or addon. |
| `base_fee` | body | number | no | Wholesale price to the reseller, major units. |
| `end_user_price` | body | number | no | Retail price, major units. |
| `expiration_value` | body | integer | no | Period length, paired with expiration_unit. |
| `expiration_unit` | body | enum | no | hours, days or months. |

#### Request

```json
{
  "name": "Home 20M",
  "type": "prepaid",
  "base_fee": 150.00,
  "end_user_price": 180.00,
  "enforce_expiration": true,
  "expiration_value": 30,
  "expiration_unit": "days",
  "enforce_combined_bytes": true,
  "combined_bytes_limit": 107374182400,
  "download_kbps": 20480,
  "upload_kbps": 4096
}
```

#### Errors

| Code | Status | When |
| --- | --- | --- |
| `ERR_VALIDATION` | 400 | name or type missing, or an out-of-range value |

#### Note

A quota limit does nothing until its enforce toggle is on. Setting combined_bytes_limit while enforce_combined_bytes is false leaves the plan unlimited on data, and the number sits there looking like a cap. The two always travel together.

