# Business Made · Benefits

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /business-made/benefits/view/plans

**Benefit plans for the HR screen**

`operationId: BenefitsController_viewPlans`

Every plan as a finished row (active first, then by title) with counts by status and org totals: active plans, people enrolled, pending enrollments, and what employer and employees pay a year. `status` filters the rows.

#### Signature

```http
GET /business-made/benefits/view/plans (status?: string) -> `{ rows, counts, summary:{activePlans, enrolledPeople, pendingEnrollments, employerAnnualLabel, employeeAnnualLabel} }`
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `status` | query | string | — |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | `{ rows, counts, summary:{activePlans, enrolledPeople, pendingEnrollments, employerAnnualLabel, employeeAnnualLabel} }` |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/view/plans/{id}

**One benefit plan for the HR screen**

`operationId: BenefitsController_viewPlan`

The plan row plus description, provider, the coverage tiers with employee and employer cost labels, the key terms (deductible, out-of-pocket max, coinsurance, copay, waiting period, who can join, minimum hours, plan year, dates), notes, the enrollments on it, and `offeredTiers` for an enroll form.

#### Signature

```http
GET /business-made/benefits/view/plans/{id} (id: string) -> The plan detail
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | BENEFIT_PLAN_NOT_FOUND | Benefit plan not found. | No benefit plan has that id. | The body carries `code: "BENEFIT_PLAN_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The plan detail |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Benefit plan not found. — No benefit plan has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/view/enrollments

**Benefit enrollments for the HR screen**

`operationId: BenefitsController_viewEnrollments`

Every enrollment as a finished row with counts by status, and `activePlans` (with their tiers) for the enroll form. `status` filters the rows.

#### Signature

```http
GET /business-made/benefits/view/enrollments (status?: string) -> `{ rows, counts, activePlans:[{value, label, tiers}] }`
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `status` | query | string | — |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | `{ rows, counts, activePlans:[{value, label, tiers}] }` |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/view/enrollments/{id}

**One benefit enrollment for the HR screen**

`operationId: BenefitsController_viewEnrollment`

The enrollment row plus its type, the payroll-deduction label, dependents and beneficiaries, the termination or waiver reason, and notes.

#### Signature

```http
GET /business-made/benefits/view/enrollments/{id} (id: string) -> The enrollment detail
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found. | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The enrollment detail |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found. — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/plans

**List benefit plans**

`operationId: BenefitsController_getBenefitPlans`

Every benefit plan defined for the org, active or not.

#### Signature

```http
GET /business-made/benefits/plans () -> Benefit plans
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/benefits/plans/active`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Benefit plans |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/plans

**Create a benefit plan**

`operationId: BenefitsController_createBenefitPlan`

Defines a benefit plan. Its employee-contribution figures feed payroll deductions, so they must match what the carrier actually charges.

#### Signature

```http
POST /business-made/benefits/plans (body) -> The created plan
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | PLAN_TITLE_REQUIRED | Give the plan a name. | `title` is missing. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/plans/{id}/activate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The plan to create.

```json
{
  "code": "HEALTH-PPO",
  "name": "Health PPO",
  "carrier": "Acme Health",
  "employeeCost": 120,
  "employerCost": 380,
  "coverageType": "medical"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created plan |
| `400` | Give the plan a name. — `title` is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/plans/active

**List active benefit plans**

`operationId: BenefitsController_getActivePlans`

Plans currently available to enrol in — what an enrolment screen should offer.

#### Signature

```http
GET /business-made/benefits/plans/active () -> Active plans
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Active plans |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/plans/{id}

**Get a benefit plan**

`operationId: BenefitsController_getBenefitPlan`

Fetches one plan with its coverage, costs and eligibility rules.

#### Signature

```http
GET /business-made/benefits/plans/{id} (id: string) -> The plan
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | INVALID_ID | invalid id <id> | The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/plans/update`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The plan |
| `400` | invalid id <id> — The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /business-made/benefits/plans/{id}

**Delete a benefit plan**

`operationId: BenefitsController_deleteBenefitPlan`

Deletes a plan. Existing enrolments are not terminated — deactivate it instead to stop new enrolments while honouring current ones.

#### Signature

```http
DELETE /business-made/benefits/plans/{id} (id: string) -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Orphans active enrolments.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | BENEFIT_PLAN_NOT_FOUND | Benefit plan not found | No benefit plan has that id. | The body carries `code: "BENEFIT_PLAN_NOT_FOUND"` and the id. |
| `400` | PLAN_IN_USE | People have enrolled in this plan — deactivate it instead of deleting it. | The plan has enrollments. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/plans/{id}/deactivate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `400` | People have enrolled in this plan — deactivate it instead of deleting it. — The plan has enrollments. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Benefit plan not found — No benefit plan has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/plans/update

**Update a benefit plan**

`operationId: BenefitsController_updateBenefitPlan`

Edits a plan (body: `sk` plus `data`; the plan keeps its status and the same checks as create run). Changing contribution amounts affects payroll deductions from the next run — existing enrolments are not re-priced retrospectively.

#### Signature

```http
POST /business-made/benefits/plans/update (body) -> The updated plan
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Tell employees before their deduction changes.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | BENEFIT_PLAN_NOT_FOUND | Benefit plan not found | No benefit plan has that id. | The body carries `code: "BENEFIT_PLAN_NOT_FOUND"` and the id. |
| `400` | PLAN_TITLE_REQUIRED | Give the plan a name. | `title` is missing. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/benefits/enrollments`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The plan to update.

```json
{
  "sk": "66f0c3a1e4b0a1b2c3d4e5f6",
  "data": {
    "title": "Health — PPO",
    "coverage": {
      "tiers": [
        {
          "tier": "employee",
          "employeeCost": 135,
          "employerCost": 420,
          "frequency": "monthly"
        }
      ]
    }
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated plan |
| `400` | Give the plan a name. — `title` is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Benefit plan not found — No benefit plan has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/plans/{id}/activate

**Activate a benefit plan**

`operationId: BenefitsController_activateBenefitPlan`

Makes a plan available to enrol in.

#### Signature

```http
POST /business-made/benefits/plans/{id}/activate (id: string) -> The activated plan
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | BENEFIT_PLAN_NOT_FOUND | Benefit plan not found | No benefit plan has that id. | The body carries `code: "BENEFIT_PLAN_NOT_FOUND"` and the id. |
| `400` | PLAN_TIERS_REQUIRED | Add at least one coverage level with its cost before switching the plan on. | The plan has no coverage tiers. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/plans/{id}/open-enrollment`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The activated plan |
| `400` | Add at least one coverage level with its cost before switching the plan on. — The plan has no coverage tiers. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Benefit plan not found — No benefit plan has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/plans/{id}/deactivate

**Deactivate a benefit plan**

`operationId: BenefitsController_deactivateBenefitPlan`

Stops new enrolments while leaving existing ones in force. The reversible way to retire a plan without cutting anyone off mid-year.

#### Signature

```http
POST /business-made/benefits/plans/{id}/deactivate (id: string) -> The deactivated plan
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | BENEFIT_PLAN_NOT_FOUND | Benefit plan not found | No benefit plan has that id. | The body carries `code: "BENEFIT_PLAN_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/plans/{id}/activate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The deactivated plan |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Benefit plan not found — No benefit plan has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/plans/{id}/open-enrollment

**Open enrolment for a plan**

`operationId: BenefitsController_startOpenEnrollment`

Opens an enrolment window — the period during which employees may join or change plans. Outside it, enrolment normally requires a qualifying life event.

#### Signature

```http
POST /business-made/benefits/plans/{id}/open-enrollment (id: string, body) -> The updated plan
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | BENEFIT_PLAN_NOT_FOUND | Benefit plan not found | No benefit plan has that id. | The body carries `code: "BENEFIT_PLAN_NOT_FOUND"` and the id. |
| `400` | WINDOW_REQUIRED | Pick the first and last day of the enrollment window. | A window date is missing. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

The enrolment window.

```json
{
  "startDate": "2026-11-01",
  "endDate": "2026-11-30",
  "effectiveDate": "2027-01-01"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated plan |
| `400` | Pick the first and last day of the enrollment window. — A window date is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Benefit plan not found — No benefit plan has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/enrollments

**List benefit enrolments**

`operationId: BenefitsController_getEnrollments`

Enrolments across the org. These identify who has which coverage — sensitive personal data, particularly for medical plans.

#### Signature

```http
GET /business-made/benefits/enrollments () -> Enrolments
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Medical enrolment data is special-category personal data in many jurisdictions.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/benefits/enrollments/employee/{employeeId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Enrolments |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/enrollments

**Create a benefit enrolment**

`operationId: BenefitsController_createEnrollment`

Enrols an employee in a plan. The enrolment starts pending — activation is what makes coverage effective and starts the payroll deduction.

#### Signature

```http
POST /business-made/benefits/enrollments (body) -> The created enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | EMPLOYEE_REQUIRED | Pick the person to enroll. | No employee is named. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments/{id}/activate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The enrolment to create.

```json
{
  "employeeId": "EMP-4821",
  "planId": "PLN-health",
  "coverageLevel": "employee-plus-spouse",
  "effectiveDate": "2027-01-01"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created enrolment |
| `400` | Pick the person to enroll. — No employee is named. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/enrollments/{id}

**Get a benefit enrolment**

`operationId: BenefitsController_getEnrollment`

Fetches one enrolment with its dependants and beneficiaries.

#### Signature

```http
GET /business-made/benefits/enrollments/{id} (id: string) -> The enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | INVALID_ID | invalid id <id> | The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments/{id}/activate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The enrolment |
| `400` | invalid id <id> — The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /business-made/benefits/enrollments/{id}

**Delete a benefit enrolment**

`operationId: BenefitsController_deleteEnrollment`

Deletes an enrolment record. Terminate instead where the person genuinely had coverage — the record matters for claims and continuation rights.

#### Signature

```http
DELETE /business-made/benefits/enrollments/{id} (id: string) -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |
| `400` | KEEP_HISTORY | Coverage that started is part of the record — end it instead. | The enrollment is not pending. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments/{id}/terminate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `400` | Coverage that started is part of the record — end it instead. — The enrollment is not pending. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/enrollments/update

**Update a benefit enrolment**

`operationId: BenefitsController_updateEnrollment`

Updates an enrolment — changing coverage level, for instance. Outside an open-enrolment window this normally requires a qualifying life event, which this endpoint does not enforce. **Replaces the stored record** — send the whole record as read (`sk` plus `data`), not just the changed fields.

#### Signature

```http
POST /business-made/benefits/enrollments/update (body) -> The updated enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Eligibility rules are not enforced here — check them before changing coverage.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/plans/{id}/open-enrollment`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The enrolment to update.

```json
{
  "sk": "ENR-4821",
  "data": {
    "coverageLevel": "family"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated enrolment |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/enrollments/{id}/activate

**Activate an enrolment**

`operationId: BenefitsController_activateEnrollment`

Makes coverage effective and starts the associated payroll deduction. The point the employee is genuinely covered.

#### Signature

```http
POST /business-made/benefits/enrollments/{id}/activate (id: string) -> The activated enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |
| `400` | NOT_PENDING | Only a pending enrollment can be made active. | The enrollment is not pending. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments/{id}/terminate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The activated enrolment |
| `400` | Only a pending enrollment can be made active. — The enrollment is not pending. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/enrollments/{id}/terminate

**Terminate an enrolment**

`operationId: BenefitsController_terminateEnrollment`

Ends coverage and stops the payroll deduction, keeping the record.

The termination date matters: coverage often runs to the end of a month rather than a leaving date, and continuation rights may follow. Set it deliberately rather than accepting a default.

#### Signature

```http
POST /business-made/benefits/enrollments/{id}/terminate (id: string, body) -> The terminated enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |
| `400` | NOT_ACTIVE | Only active coverage can be ended. | The enrollment is not active. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/offboarding/{id}/complete`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

Termination details.

```json
{
  "terminationDate": "2026-09-30",
  "reason": "Employment ended"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The terminated enrolment |
| `400` | Only active coverage can be ended. — The enrollment is not active. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/enrollments/{id}/waive

**Waive coverage**

`operationId: BenefitsController_waiveEnrollment`

Records that an employee declined a benefit. Worth capturing explicitly — a documented waiver is different from never having been offered, and it is the difference that matters if it is ever questioned.

#### Signature

```http
POST /business-made/benefits/enrollments/{id}/waive (id: string, body) -> The waived enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |
| `400` | NOT_PENDING | Only a pending enrollment can be waived. | The enrollment is not pending. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments/{id}/activate`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

Waiver details.

```json
{
  "reason": "Covered under spouse's plan"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The waived enrolment |
| `400` | Only a pending enrollment can be waived. — The enrollment is not pending. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/enrollments/employee/{employeeId}

**Get an employee's enrolments**

`operationId: BenefitsController_getEmployeeEnrollments`

One employee's benefit enrolments — what a self-service benefits screen shows.

#### Signature

```http
GET /business-made/benefits/enrollments/employee/{employeeId} (employeeId: string) -> The employee's enrolments
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `employeeId` | path | string | yes | Employee id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The employee's enrolments |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/enrollments/{id}/dependents

**Add a dependant**

`operationId: BenefitsController_addDependent`

Adds a dependant to an enrolment. Dependant details are personal data about people who are not employees — hold only what the plan requires.

#### Signature

```http
POST /business-made/benefits/enrollments/{id}/dependents (id: string, body) -> The updated enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |
| `400` | DEPENDENT_RELATIONSHIP_REQUIRED | Pick how they are related. | `relationship` is missing. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /business-made/benefits/enrollments/{id}/dependents/{dependentId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

The dependant.

```json
{
  "name": "Byron Lovelace",
  "relationship": "child",
  "dateOfBirth": "2018-04-12"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated enrolment |
| `400` | Pick how they are related. — `relationship` is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /business-made/benefits/enrollments/{id}/dependents/{dependentId}

**Remove a dependant**

`operationId: BenefitsController_removeDependent`

Removes a dependant from an enrolment. Coverage level may need adjusting separately — removing a dependant does not re-price the enrolment.

#### Signature

```http
DELETE /business-made/benefits/enrollments/{id}/dependents/{dependentId} (id: string, dependentId: string) -> The updated enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- The coverage level and its cost are unchanged — update them if the tier should drop.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments/update`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |
| `dependentId` | path | string | yes | Dependant id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated enrolment |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/benefits/enrollments/{id}/beneficiaries

**Add a beneficiary**

`operationId: BenefitsController_addBeneficiary`

Adds a beneficiary to an enrolment — who receives a benefit on death. Accuracy matters more here than almost anywhere else in the module, and it is rarely revisited once set.

#### Signature

```http
POST /business-made/benefits/enrollments/{id}/beneficiaries (id: string, body) -> The updated enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Nothing checks that percentages total 100 — verify before relying on the allocation.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |
| `400` | BENEFICIARY_SHARE_REQUIRED | Enter their share as a percentage between 1 and 100. | `percentage` is missing or out of range. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /business-made/benefits/enrollments/{id}/beneficiaries/{beneficiaryId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

The beneficiary.

```json
{
  "name": "Grace Hopper",
  "relationship": "spouse",
  "percentage": 100
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated enrolment |
| `400` | Enter their share as a percentage between 1 and 100. — `percentage` is missing or out of range. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /business-made/benefits/enrollments/{id}/beneficiaries/{beneficiaryId}

**Remove a beneficiary**

`operationId: BenefitsController_removeBeneficiary`

Removes a beneficiary. Removing one without adding a replacement can leave the allocation summing to less than 100%.

#### Signature

```http
DELETE /business-made/benefits/enrollments/{id}/beneficiaries/{beneficiaryId} (id: string, beneficiaryId: string) -> The updated enrolment
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ENROLLMENT_NOT_FOUND | Enrollment not found | No enrollment has that id. | The body carries `code: "ENROLLMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/benefits/enrollments/{id}/beneficiaries`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |
| `beneficiaryId` | path | string | yes | Beneficiary id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated enrolment |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Enrollment not found — No enrollment has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/benefits/metrics

**Get benefits metrics**

`operationId: BenefitsController_getBenefitsMetrics`

Aggregate benefits figures — take-up rates, cost by plan and employer contribution totals.

#### Signature

```http
GET /business-made/benefits/metrics () -> Benefits metrics
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/benefits/enrollments`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Benefits metrics |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

