# Client Account

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /client-data/dashboard

**Get my dashboard**

`operationId: ClientAccountController_getClientDashboard`

A consolidated view for the signed-in customer — recent orders, upcoming reservations, open tickets and unread messages in one call, so an account home page does not need six requests.

#### Signature

```http
GET /client-data/dashboard () -> The dashboard
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/all`

### 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` | The dashboard |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/shared-accounts/{accountId}/members

**List shared account members**

`operationId: ClientAccountController_getSharedAccountMembers`

Managers only. Everyone associated with the account, suspended members included. A member whose customer record is gone is kept (`missing: true`) so it can still be removed.

#### Signature

```http
GET /client-data/shared-accounts/{accountId}/members (accountId: string) -> [{ associationId, customerId, name, email, role, status, missing }]
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |
| `403` | NOT_MANAGER | You do not manage this account | The caller has no active manager association with this account. | — |

Plus the standard platform errors: `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. |
| `accountId` | path | string | yes | Shared account id (the account `customer` record). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | [{ associationId, customerId, name, email, role, status, missing }] |
| `401` | Customer required — No signed-in customer could be resolved. |
| `403` | You do not manage this account — The caller has no active manager association with this account. |
| `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 /client-data/shared-accounts/{accountId}/orders

**List shared account orders**

`operationId: ClientAccountController_getSharedAccountOrders`

Managers only. Orders placed on the account by any member.

#### Signature

```http
GET /client-data/shared-accounts/{accountId}/orders (accountId: string, page?: integer, limit?: integer) -> Paged orders
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |
| `403` | NOT_MANAGER | You do not manage this account | The caller has no active manager association with this account. | — |

Plus the standard platform errors: `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. |
| `accountId` | path | string | yes | Shared account id (the account `customer` record). |
| `page` | query | integer | — |  |
| `limit` | query | integer | — | Rows per page. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Paged orders |
| `401` | Customer required — No signed-in customer could be resolved. |
| `403` | You do not manage this account — The caller has no active manager association with this account. |
| `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. |

## PUT /client-data/shared-accounts/{accountId}/members/{associationId}

**Change a shared account member**

`operationId: ClientAccountController_updateSharedAccountMember`

Managers only. Changes a member's `role` (manager | buyer) or `status` (active | suspended). Suspending keeps the association so their past orders still explain themselves. The account must keep at least one active manager.

#### Signature

```http
PUT /client-data/shared-accounts/{accountId}/members/{associationId} (accountId: string, associationId: string, body) -> The association
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |
| `403` | NOT_MANAGER | You do not manage this account | The caller has no active manager association with this account. | — |
| `404` | MEMBER_NOT_FOUND | Member not found on this account | The association does not exist or belongs to another account. | — |
| `400` | LAST_MANAGER | The account must keep at least one manager | The change would leave no active manager. | — |

Plus the standard platform errors: `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. |
| `accountId` | path | string | yes | Shared account id (the account `customer` record). |
| `associationId` | path | string | yes | customer_association sk. |

### Request body

```json
{
  "status": "suspended"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The association |
| `400` | The account must keep at least one manager — The change would leave no active manager. |
| `401` | Customer required — No signed-in customer could be resolved. |
| `403` | You do not manage this account — The caller has no active manager association with this account. |
| `404` | Member not found on this account — The association does not exist or belongs to another account. |
| `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 /client-data/shared-accounts/{accountId}/invites

**Invite someone to a shared account**

`operationId: ClientAccountController_inviteToSharedAccount`

Managers only. An email that already belongs to a customer is associated straight away (a suspended member is reinstated) and told by email; a new email gets a pending invitation with a sign-up link on the storefront the manager is on (`x-client-host`). Resending to a pending invite re-sends it. `role` defaults to buyer.

#### Signature

```http
POST /client-data/shared-accounts/{accountId}/invites (accountId: string, body) -> `{ added, reinstated, customerId }` or `{ invited, resent, email }`, plus the assembled `account`
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |
| `403` | NOT_MANAGER | You do not manage this account | The caller has no active manager association with this account. | — |
| `400` | EMAIL_REQUIRED | A valid email is required | `email` missing or has no @. | — |

Plus the standard platform errors: `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. |
| `accountId` | path | string | yes | Shared account id (the account `customer` record). |
| `x-client-host` | header | string | — | The storefront host the invitation link points at. |

### Request body

```json
{
  "email": "buyer@acme.com",
  "role": "buyer",
  "message": "Welcome to the Acme account"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | `{ added, reinstated, customerId }` or `{ invited, resent, email }`, plus the assembled `account` |
| `400` | A valid email is required — `email` missing or has no @. |
| `401` | Customer required — No signed-in customer could be resolved. |
| `403` | You do not manage this account — The caller has no active manager association with this account. |
| `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 /client-data/shared-accounts/invites/validate/{invitationToken}

**Check a shared account invitation**

`operationId: ClientAccountController_validateSharedAccountInvitation`

Public. Validates an invitation link before the sign-up form is shown. An expired link is marked expired and refused.

#### Signature

```http
GET /client-data/shared-accounts/invites/validate/{invitationToken} (invitationToken: string) -> { email, firstName, lastName, invitedByName, message, accountName }
```

#### Access

Public — no credentials required.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | INVITE_INVALID | Invalid or expired invitation | No pending invitation has that token. | — |

Plus the standard platform errors: `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. |
| `invitationToken` | path | string | yes | Token from the invitation email. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { email, firstName, lastName, invitedByName, message, accountName } |
| `400` | Invalid or expired invitation — No pending invitation has that token. |
| `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 /client-data/shared-accounts/invites/accept/{invitationToken}

**Accept a shared account invitation**

`operationId: ClientAccountController_acceptSharedAccountInvitation`

Once the invitee is signed in (just signed up through the link, or already had an account), associates them with the account named on the invitation with its role.

#### Signature

```http
POST /client-data/shared-accounts/invites/accept/{invitationToken} (invitationToken: string) -> { accepted: true, accountId, role }
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | NOT_SIGNED_IN | Not signed in | No signed-in customer. | — |
| `400` | INVITE_INVALID | Invalid or expired invitation | No pending invitation has that token. | — |
| `403` | WRONG_EMAIL | This invitation was sent to a different email | The signed-in email is not the invited one. | — |

Plus the standard platform errors: `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. |
| `invitationToken` | path | string | yes | Token from the invitation email. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { accepted: true, accountId, role } |
| `400` | Invalid or expired invitation — No pending invitation has that token. |
| `401` | Not signed in — No signed-in customer. |
| `403` | This invitation was sent to a different email — The signed-in email is not the invited one. |
| `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 /client-data/profile

**Get my profile**

`operationId: ClientAccountController_getProfile`

The signed-in customer's profile.

#### Signature

```http
GET /client-data/profile () -> The profile
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `PUT /client-data/profile`

### 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` | The profile |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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. |

## PUT /client-data/profile

**Update my profile**

`operationId: ClientAccountController_updateProfile`

Updates the customer's own profile. Changing an email here does not re-verify it — use the verification endpoints if the new address needs proving.

#### Signature

```http
PUT /client-data/profile (body) -> The updated profile
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/verification/email/send`

### 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

Fields to change.

```json
{
  "firstName": "Ada",
  "lastName": "Lovelace",
  "phone": "+15551234567"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated profile |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/orders

**Get my orders**

`operationId: ClientAccountController_getOrders`

The customer's order history, paged.

#### Signature

```http
GET /client-data/orders (page?: integer, limit?: integer, status?: string, sortBy?: string, sortOrder?: string) -> Orders
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/orders/{orderId}`

### 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. |
| `page` | query | integer | — |  |
| `limit` | query | integer | — | Rows per page. |
| `status` | query | string | — | Order status. |
| `sortBy` | query | string | — |  |
| `sortOrder` | query | "asc" \| "desc" | — |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Orders |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/forms

**Get my forms**

`operationId: ClientAccountController_getForms`

Forms this customer has submitted and any still waiting on them, matched on their email. A `pending` row is a link that was asked for and not used yet (`submittedAt` null).

#### Signature

```http
GET /client-data/forms (page?: integer, limit?: integer, status?: string) -> { data, total, page, pageSize }
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

Plus the standard platform errors: `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. |
| `page` | query | integer | — |  |
| `limit` | query | integer | — | Rows per page. |
| `status` | query | string | — | Submission status, e.g. `pending`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { data, total, page, pageSize } |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/orders/{orderId}

**Get one of my orders**

`operationId: ClientAccountController_getOrder`

Fetches one of the customer's own orders. An order belonging to someone else is not returned.

#### Signature

```http
GET /client-data/orders/{orderId} (orderId: string) -> The order
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/transactions`

### 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. |
| `orderId` | path | string | yes | Order id or number. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The order |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/reservations

**Get my reservations**

`operationId: ClientAccountController_getReservations`

The customer's bookings, past and upcoming.

#### Signature

```http
GET /client-data/reservations () -> Reservations
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/reservations`

### 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` | Reservations |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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. |

## PUT /client-data/reservations

**Update my reservation**

`operationId: ClientAccountController_updateReservation`

Reschedules or amends one of the customer's reservations. Availability is not re-checked automatically — confirm the new slot is free first.

#### Signature

```http
PUT /client-data/reservations (body) -> The updated reservation
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `DELETE /client-data/reservations/{reservationId}`

### 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. |
| `x-client-info` | header | string | yes |  |

### Request body

The reservation to update.

```json
{
  "reservationId": "RES-4821",
  "startDate": "2026-10-06T10:00:00.000Z"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated reservation |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/reservations

**Make a reservation**

`operationId: ClientAccountController_createReservation`

Books a reservation for the customer.

#### Signature

```http
POST /client-data/reservations (body) -> The created reservation
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/reservations/available-slots`

### 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. |
| `x-client-info` | header | string | yes |  |

### Request body

The reservation.

```json
{
  "servicePointId": "sp_t7",
  "startDate": "2026-10-05T10:00:00.000Z",
  "endDate": "2026-10-05T10:30:00.000Z"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created reservation |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/reservations/{reservationId}

**Get one of my reservations**

`operationId: ClientAccountController_getReservation`

Fetches one of the customer's own reservations.

#### Signature

```http
GET /client-data/reservations/{reservationId} (reservationId: string) -> The reservation
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `PUT /client-data/reservations`

### 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. |
| `reservationId` | path | string | yes | Reservation id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The reservation |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/reservations/{reservationId}

**Cancel my reservation**

`operationId: ClientAccountController_cancelReservation`

Cancels one of the customer's reservations, freeing the slot.

#### Signature

```http
DELETE /client-data/reservations/{reservationId} (reservationId: string) -> Cancellation result
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/reservations`

### 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. |
| `x-client-info` | header | string | yes |  |
| `reservationId` | path | string | yes | Reservation id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Cancellation result |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/reservations/available-slots

**Find available slots**

`operationId: ClientAccountController_getAvailableSlots`

Computes bookable slots for a service or location. Slots are calculated, not held — one shown here can be taken before the customer books it.

#### Signature

```http
POST /client-data/reservations/available-slots (body) -> Available slots
```

#### Access

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

#### Notes

- No hold is placed — handle a conflict on booking.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/reservations`

### 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

What to check availability for.

```json
{
  "servicePointId": "sp_t7",
  "startDate": "2026-10-05",
  "endDate": "2026-10-06",
  "duration": 30
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Available slots |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/tickets

**Get my support tickets**

`operationId: ClientAccountController_getTickets`

The customer's own support tickets.

#### Signature

```http
GET /client-data/tickets (status?: string, enrich?: string) -> Tickets
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/tickets`

### 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 | — |  |
| `enrich` | query | "true" \| "false" | — | Include linked records. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Tickets |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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. |

## PUT /client-data/tickets

**Update my ticket**

`operationId: ClientAccountController_updateTicket`

Adds to or amends one of the customer's tickets — replying, or supplying detail that was asked for.

#### Signature

```http
PUT /client-data/tickets (body) -> The updated ticket
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/tickets/{ticketNumber}`

### 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 ticket update.

```json
{
  "ticketNumber": "TKT-4821",
  "message": "Tracking updated today — please close this"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated ticket |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/tickets

**Raise a support ticket**

`operationId: ClientAccountController_createTicket`

Creates a support ticket as the signed-in customer.

#### Signature

```http
POST /client-data/tickets (body) -> The created ticket
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/tickets/with-attachments`

### 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 ticket.

```json
{
  "title": "Order never arrived",
  "description": "Tracking has not updated in a week",
  "orderNumber": "A7K2M9QX4"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created ticket |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/tickets/{ticketNumber}

**Get one of my tickets**

`operationId: ClientAccountController_getTicket`

Fetches one ticket with its customer-visible conversation. Internal staff comments are not included.

#### Signature

```http
GET /client-data/tickets/{ticketNumber} (ticketNumber: string) -> The ticket
```

#### Access

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

#### Notes

- Only the customer-facing thread is returned — internal comments stay internal.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `PUT /client-data/tickets`

### 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. |
| `ticketNumber` | path | string | yes | Ticket number. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The ticket |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/tickets/with-attachments

**Raise a ticket with attachments**

`operationId: ClientAccountController_createTicketWithAttachments`

Creates a ticket and uploads supporting files in one multipart request — screenshots and photos, which is what most support issues need.

#### Signature

```http
POST /client-data/tickets/with-attachments (body) -> The created ticket
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/tickets`

### 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

Multipart form with the ticket fields and files.

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created ticket |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/messages

**Get my messages**

`operationId: ClientAccountController_getMessages`

Messages sent to and from the customer.

#### Signature

```http
GET /client-data/messages (page?: integer, pageSize?: integer, sort?: string, sortType?: string, conversationWith?: string) -> Messages
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/conversations`

### 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. |
| `conversationWith` | query | string | — | Only the thread with this address. |
| `page` | query | integer | — |  |
| `pageSize` | query | integer | — |  |
| `sort` | query | string | — | Field to sort by. |
| `sortType` | query | "asc" \| "desc" | — |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Messages |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/messages

**Send a message**

`operationId: ClientAccountController_sendMessage`

Sends a message as the customer.

#### Signature

```http
POST /client-data/messages (send?: boolean, body) -> The sent message
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/messages`

### 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. |
| `send` | query | boolean | — | true to send immediately; otherwise saved as a draft. |

### Request body

The message.

```json
{
  "subject": "Question about delivery",
  "body": "When do you ship to Ireland?"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The sent message |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/conversations

**Get my conversations**

`operationId: ClientAccountController_getConversations`

The customer's messages grouped into threads — the inbox list view.

#### Signature

```http
GET /client-data/conversations () -> Conversations
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/messages`

### 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` | Conversations |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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. |

## PUT /client-data/messages/{messageId}/status/{status}

**Set a message status**

`operationId: ClientAccountController_updateMessageStatus`

Marks one of the customer's messages read, archived or similar. Both values are path segments rather than a body.

#### Signature

```http
PUT /client-data/messages/{messageId}/status/{status} (messageId: string, status: string) -> The updated message
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/messages`

### 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. |
| `messageId` | path | string | yes | Message id. |
| `status` | path | string | yes | New status. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated message |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/notifications

**Get my notifications**

`operationId: ClientAccountController_getNotifications`

Notifications for the signed-in customer.

#### Signature

```http
GET /client-data/notifications (unreadOnly?: boolean) -> Notifications
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/notifications/push-token`

### 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. |
| `unreadOnly` | query | boolean | — | true for unread notifications only. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Notifications |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/notifications/push-token

**Register a push token**

`operationId: ClientAccountController_savePushToken`

Registers a device for push notifications. Call it on every app launch — platform tokens rotate, and a stale one silently stops delivering.

#### Signature

```http
POST /client-data/notifications/push-token (body) -> The registered token
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/notifications`

### 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 device token.

```json
{
  "token": "fcm_dGhpcyBpcyBhIHRva2Vu",
  "platform": "ios"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The registered token |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/payment-methods

**Get my payment methods**

`operationId: ClientAccountController_getPaymentMethods`

The customer's saved payment methods. Card details are masked — expect a last-four, never a full number.

#### Signature

```http
GET /client-data/payment-methods () -> Payment methods
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/payment-methods`

### 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` | Payment methods |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/payment-methods

**Add a payment method**

`operationId: ClientAccountController_addPaymentMethod`

Saves a payment method for the customer. Send a gateway token rather than raw card details — the card should reach the payment provider, not this API.

#### Signature

```http
POST /client-data/payment-methods (body) -> The saved method
```

#### Access

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

#### Notes

- Tokenise on the client. Raw card data here would pull the platform into PCI scope.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `PUT /client-data/payment-methods/{paymentMethodId}/default`

### 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 payment method.

```json
{
  "token": "pm_1PabcXYZ",
  "gateway": "stripe",
  "isDefault": true
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The saved method |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/payment-methods/{paymentMethodId}

**Remove a payment method**

`operationId: ClientAccountController_removePaymentMethod`

Deletes a saved payment method. Any subscription billing against it will fail at its next renewal — check before removing the only method on file.

#### Signature

```http
DELETE /client-data/payment-methods/{paymentMethodId} (paymentMethodId: string) -> Removal result
```

#### Access

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

#### Notes

- Recurring charges using it will start failing.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/payment-methods`

### 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. |
| `paymentMethodId` | path | string | yes | Payment method id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Removal result |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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. |

## PUT /client-data/payment-methods/{paymentMethodId}/default

**Set the default payment method**

`operationId: ClientAccountController_setDefaultPaymentMethod`

Makes one method the default for future purchases and renewals.

#### Signature

```http
PUT /client-data/payment-methods/{paymentMethodId}/default (paymentMethodId: string) -> The updated method
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/payment-methods`

### 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. |
| `paymentMethodId` | path | string | yes | Payment method id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated method |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/addresses

**Get my addresses**

`operationId: ClientAccountController_getAddresses`

The customer's saved addresses.

#### Signature

```http
GET /client-data/addresses () -> Addresses
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/addresses`

### 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` | Addresses |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/addresses

**Add an address**

`operationId: ClientAccountController_saveAddress`

Saves an address for the customer.

#### Signature

```http
POST /client-data/addresses (body) -> The saved address
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/addresses/autocomplete`

### 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 address.

```json
{
  "line1": "12 Ada Way",
  "city": "London",
  "postcode": "E1 6AN",
  "country": "GB",
  "isDefault": true
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The saved address |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/addresses/{addressId}

**Remove an address**

`operationId: ClientAccountController_deleteAddress`

Deletes a saved address. Orders already placed keep the address they shipped to.

#### Signature

```http
DELETE /client-data/addresses/{addressId} (addressId: string) -> Removal result
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/addresses`

### 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. |
| `addressId` | path | string | yes | Address id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Removal result |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/addresses/autocomplete

**Autocomplete an address**

`operationId: ClientAccountController_getAddressAutocomplete`

Returns address suggestions as the customer types. Backed by a billable maps provider — debounce it rather than calling per keystroke.

#### Signature

```http
POST /client-data/addresses/autocomplete (body) -> Address suggestions
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/addresses/place/{placeId}`

### 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

What has been typed.

```json
{
  "input": "12 Ada W",
  "sessiontoken": "b1f2c3d4"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Address suggestions |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/addresses/place/{placeId}

**Get address details for a place**

`operationId: ClientAccountController_getPlaceDetails`

Expands a place id from autocomplete into a full structured address.

#### Signature

```http
GET /client-data/addresses/place/{placeId} (placeId: string) -> The structured address
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |
| `400` | PLACE_ID_REQUIRED | place_id is required | The place id is missing. | Take it from an autocomplete suggestion. |

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

#### See also

- `POST /client-data/addresses/autocomplete`

### 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. |
| `placeId` | path | string | yes | Place id from an autocomplete suggestion. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The structured address |
| `400` | place_id is required — The place id is missing. |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/wishlist

**Get my wishlist**

`operationId: ClientAccountController_getWishlist`

The customer's saved products.

#### Signature

```http
GET /client-data/wishlist () -> Wishlist
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/wishlist/{productId}`

### 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` | Wishlist |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/wishlist

**Create a wishlist**

`operationId: ClientAccountController_createWishlist`

Creates a named wishlist, for customers keeping more than one list.

#### Signature

```http
POST /client-data/wishlist (body) -> The created wishlist
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `DELETE /client-data/wishlist-list/{wishlistId}`

### 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 wishlist to create.

```json
{
  "name": "Christmas"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created wishlist |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/wishlist/{productId}

**Add a product to my wishlist**

`operationId: ClientAccountController_addToWishlist`

Saves a product to the wishlist. The product must carry a SKU — that is what the wishlist keys on.

#### Signature

```http
POST /client-data/wishlist/{productId} (productId: string, body) -> The updated wishlist
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |
| `400` | SKU_REQUIRED | product.sku is required | The product has no SKU. | Wishlist entries are keyed on SKU. |

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

#### See also

- `DELETE /client-data/wishlist/{productId}`

### 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. |
| `productId` | path | string | yes | Product id or SKU. |

### Request body

Optional product detail.

```json
{
  "product": {
    "sku": "DRK-COLA-330"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated wishlist |
| `400` | product.sku is required — The product has no SKU. |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/wishlist/{productId}

**Remove a product from my wishlist**

`operationId: ClientAccountController_removeFromWishlist`

Removes a product from the wishlist.

#### Signature

```http
DELETE /client-data/wishlist/{productId} (productId: string, wishlistId?: string) -> The updated wishlist
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |
| `400` | SKU_REQUIRED | sku is required | No SKU was resolved from the path. | Supply the product SKU. |

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

#### See also

- `GET /client-data/wishlist`

### 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. |
| `productId` | path | string | yes | Product id or SKU. |
| `wishlistId` | query | string | — | A named wishlist; omit for the default one. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated wishlist |
| `400` | sku is required — No SKU was resolved from the path. |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/wishlist-list/{wishlistId}

**Delete a wishlist**

`operationId: ClientAccountController_deleteWishlist`

Deletes one of the customer's named wishlists. Ownership is checked — deleting someone else's list is refused with `Not your wishlist`.

#### Signature

```http
DELETE /client-data/wishlist-list/{wishlistId} (wishlistId: string) -> Deletion result
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |
| `404` | WISHLIST_NOT_FOUND | Wishlist not found | No wishlist has that id. | Check the id. |
| `400` | NOT_YOUR_WISHLIST | Not your wishlist | The wishlist belongs to another customer. | Ownership is enforced — you can only delete your own. |

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

#### See also

- `POST /client-data/wishlist`

### 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. |
| `wishlistId` | path | string | yes | Wishlist id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `400` | Not your wishlist — The wishlist belongs to another customer. |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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` | Wishlist not found — No wishlist 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 /client-data/all

**Get everything about my account**

`operationId: ClientAccountController_getAllClientData`

The customer's full account data in one response. Heavier than the dashboard — intended for a data-export or "download my data" flow rather than routine page loads.

#### Signature

```http
GET /client-data/all () -> All account data
```

#### Access

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

#### Notes

- Large response. Do not call it on every page.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/dashboard`

### 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. |
| `x-client-info` | header | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | All account data |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/transactions

**Get my transactions**

`operationId: ClientAccountController_getTransactions`

The customer's payment history across orders and subscriptions.

#### Signature

```http
GET /client-data/transactions (page?: integer, limit?: integer, status?: string, paymentMethodId?: string) -> Transactions
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/orders`

### 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. |
| `paymentMethodId` | query | string | — | Only transactions paid with this saved method. |
| `page` | query | integer | — |  |
| `limit` | query | integer | — | Rows per page. |
| `status` | query | string | — |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Transactions |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/verification/status

**Get my verification status**

`operationId: ClientAccountController_getVerificationStatus`

Whether the customer's email and phone have been verified.

#### Signature

```http
GET /client-data/verification/status () -> Verification status
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/verification/email/send`

### 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` | Verification status |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/verification/email/send

**Send an email verification code**

`operationId: ClientAccountController_sendEmailVerification`

Sends a verification code to the customer's email. Rate-limit it — otherwise it doubles as a way to send mail to an address repeatedly.

#### Signature

```http
POST /client-data/verification/email/send (body) -> The result
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/verification/email/verify`

### 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

Optional target.

```json
{}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The result |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/verification/email/verify

**Verify an email code**

`operationId: ClientAccountController_verifyEmail`

Confirms the code sent to the customer's email, marking it verified.

#### Signature

```http
POST /client-data/verification/email/verify (body) -> The result
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/verification/status`

### 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 code.

```json
{
  "code": "481625"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The result |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/verification/phone/send

**Send a phone verification code**

`operationId: ClientAccountController_sendPhoneVerification`

Sends a verification code by SMS. Each send costs money and lands on someone's phone — rate-limit per number, not just per account.

#### Signature

```http
POST /client-data/verification/phone/send (body) -> The result
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/verification/phone/verify`

### 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 number to verify.

```json
{
  "phone": "+15551234567"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The result |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/verification/phone/verify

**Verify a phone code**

`operationId: ClientAccountController_verifyPhone`

Confirms the SMS code, marking the number verified.

#### Signature

```http
POST /client-data/verification/phone/verify (body) -> The result
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/verification/status`

### 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 code.

```json
{
  "code": "481625"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The result |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/analytics

**Get my account analytics**

`operationId: ClientAccountController_getAnalytics`

Summary figures about the customer's own activity — spend, order count, engagement.

#### Signature

```http
GET /client-data/analytics () -> Account analytics
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/dashboard`

### 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` | Account analytics |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/expert/messages

**Get my expert messages**

`operationId: ClientAccountController_getExpertMessages`

Messages exchanged with experts.

#### Signature

```http
GET /client-data/expert/messages (page?: integer, pageSize?: integer, sort?: string, sortType?: string, conversationWith?: string) -> Expert messages
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/expert/messages`

### 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. |
| `conversationWith` | query | string | — | Only the thread with this address. |
| `page` | query | integer | — |  |
| `pageSize` | query | integer | — |  |
| `sort` | query | string | — | Field to sort by. |
| `sortType` | query | "asc" \| "desc" | — |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Expert messages |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/expert/messages

**Message an expert**

`operationId: ClientAccountController_sendMessageToExpert`

Sends a message to an expert.

#### Signature

```http
POST /client-data/expert/messages (send?: boolean, body) -> The sent message
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/expert/hire`

### 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. |
| `send` | query | boolean | — | true to send immediately; otherwise saved as a draft. |

### Request body

The message.

```json
{
  "expertId": "EXP-4821",
  "message": "Can you advise on sizing?"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The sent message |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/expert/hire

**Hire an expert**

`operationId: ClientAccountController_hireExpert`

Engages an expert. This commits the customer to a paid engagement, so confirm terms before calling it.

#### Signature

```http
POST /client-data/expert/hire (body) -> The engagement
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/expert/messages`

### 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 engagement.

```json
{
  "expertId": "EXP-4821",
  "scope": "One-hour consultation"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The engagement |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/files

**Get my files**

`operationId: ClientAccountController_getFiles`

Files the customer has uploaded, in their own storage area.

#### Signature

```http
GET /client-data/files () -> Files
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/files/upload`

### 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` | Files |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/files/{path}

**Delete a file**

`operationId: ClientAccountController_deleteFile`

Deletes one of the customer's files. The path is a segment, so it must be URL-encoded if it contains slashes.

#### Signature

```http
DELETE /client-data/files/{path} (path: string) -> Deletion result
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/files`

### 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. |
| `path` | path | string | yes | File path within the customer's area. URL-encode any slashes. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/files/upload

**Upload a file**

`operationId: ClientAccountController_upload`

Uploads a file to the customer's own storage area.

#### Signature

```http
POST /client-data/files/upload (body) -> The uploaded file
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `DELETE /client-data/files/{path}`

### 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

Multipart form with the file.

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The uploaded file |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/benefits

**Get available benefits**

`operationId: ClientAccountController_getCustomerBenefits`

Benefits the customer can enrol in.

#### Signature

```http
GET /client-data/benefits () -> Available benefits
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/benefits/enroll`

### 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` | Available benefits |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/benefits/enroll

**Enrol in a benefit**

`operationId: ClientAccountController_applyForBenefit`

Enrols the customer in a benefit. Enrolment may require an application form and a legal agreement — the CRM benefit endpoints enforce those rules.

#### Signature

```http
POST /client-data/benefits/enroll (body) -> The enrolment
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `GET /client-data/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 enrolment.

```json
{
  "benefit": "health-plan",
  "agreementAccepted": true
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The enrolment |
| `401` | Customer required — No signed-in customer could be resolved. |
| `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 /client-data/benefits/enrollments

**Get my benefit enrolments**

`operationId: ClientAccountController_getMyEnrollments`

The customer's benefit enrolments and their status.

#### Signature

```http
GET /client-data/benefits/enrollments () -> Enrolments
```

#### Access

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

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | CUSTOMER_REQUIRED | Customer required | No signed-in customer could be resolved. | Sign in. Every endpoint here is scoped to the caller and none work anonymously. |

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

#### See also

- `POST /client-data/benefits/enroll`

### 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` | Customer required — No signed-in customer could be resolved. |
| `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. |

