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

# Customer Group API

> Customer group management API for organizing customers, assigning them to groups, and maintaining default price list associations for optical stores

# Customer Group API

The Customer Group API enables optical stores to organize customers into groups, manage group memberships, and associate default price lists with customer groups.

<Note>
  All Customer Group API endpoints require authentication. Routes that operate in a store context also require a valid `x-store-id` header.
</Note>

## Overview

Customer groups can be:

* Created with a name, description, and default price list
* Listed with pagination, filtering, and sorting
* Retrieved by ID for individual group details
* Deleted in bulk operations
* Used to assign customers to groups for pricing and organization
* Associated with default price lists for automatic pricing

## Endpoint Details

**Base URL:** `https://joptic.jethings.com`\
**Content-Type:** `application/json`

### Required Headers

```
x-store-id: <store_id>
Authorization: Bearer <token>
```

<Warning>
  Endpoints that require `x-store-id` enforce store-level access control. Ensure the requesting user has an active relation with the store.
</Warning>

***

## Authentication

All endpoints require user authentication. The user ID is extracted from the JWT token (`req.user.sub`), and store access is validated via the `@StoreId()` decorator.

## Rate Limiting

Endpoints are protected with rate limiting:

* **GET** endpoints: 60 requests per minute (long throttle)
* **POST** endpoints: 10 requests per minute (medium throttle)
* **DELETE** endpoints: 3 requests per minute (short throttle)

***

## Create Customer Group

**POST** `/customer-group`

Create a new customer group with an optional description and default price list association.

**Requires Authentication:** Bearer token in Authorization header\
**Requires Header:** `x-store-id`

**Rate Limited:** 10 requests per minute

### Required Headers

| Key          | Value    | Required | Description                                       |
| ------------ | -------- | -------- | ------------------------------------------------- |
| `x-store-id` | `string` | Yes      | Store identifier (used by `@StoreId()` decorator) |

### Request Body

| Field                | Type     | Required | Description                                 |
| -------------------- | -------- | -------- | ------------------------------------------- |
| `name`               | `string` | ✅ Yes    | Customer group name (max 255 characters)    |
| `defaultPriceListId` | `string` | ✅ Yes    | ID of the default price list for this group |
| `description`        | `string` | No       | Optional description of the customer group  |

### Request Body Example

```json theme={null}
{
  "name": "VIP Customers",
  "defaultPriceListId": "price_list_123",
  "description": "Premium customers with special pricing"
}
```

### Success Response

**Status Code:** `201 Created`

```json theme={null}
{
  "id": "cgrp_abc123",
  "groupName": "VIP Customers",
  "description": "Premium customers with special pricing",
  "defaultPriceList": "price_list_123",
  "createdAt": "2025-11-03T10:00:00.000Z",
  "updatedAt": "2025-11-03T10:00:00.000Z"
}
```

### Response Fields

| Field              | Type     | Description                      |
| ------------------ | -------- | -------------------------------- |
| `id`               | `string` | Unique customer group ID         |
| `groupName`        | `string` | Customer group name              |
| `description`      | `string` | Description of the group         |
| `defaultPriceList` | `string` | Default price list ID            |
| `createdAt`        | `string` | Creation timestamp (ISO 8601)    |
| `updatedAt`        | `string` | Last update timestamp (ISO 8601) |

### Possible Errors

| Code | Message                                            |
| ---- | -------------------------------------------------- |
| 400  | Bad Request - Invalid input data                   |
| 401  | Unauthorized                                       |
| 403  | Forbidden - User does not have access to the store |
| 500  | Internal Server Error                              |

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://joptic.jethings.com/customer-group" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "VIP Customers",
      "defaultPriceListId": "price_list_123",
      "description": "Premium customers with special pricing"
    }'
  ```

  ```javascript JavaScript theme={null}
  const groupData = {
    name: "VIP Customers",
    defaultPriceListId: "price_list_123",
    description: "Premium customers with special pricing"
  }

  const response = await fetch("https://joptic.jethings.com/customer-group", {
    method: "POST",
    headers: {
      "x-store-id": "your-store-id",
      Authorization: "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify(groupData),
  })

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  url = "https://joptic.jethings.com/customer-group"

  group_data = {
      "name": "VIP Customers",
      "defaultPriceListId": "price_list_123",
      "description": "Premium customers with special pricing"
  }

  response = requests.post(
      url,
      headers={
          "x-store-id": "your-store-id",
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json"
      },
      json=group_data
  )

  print(response.json())
  ```
</CodeGroup>

<Note>
  The customer group is created without store association in the current implementation. The default price list ID should reference an existing price list in your system.
</Note>

***

## Get All Customer Groups

**GET** `/customer-group`

Retrieve a paginated list of customer groups with optional filters and search capabilities.

**Requires Authentication:** Bearer token in Authorization header\
**Requires Header:** `x-store-id`

**Rate Limited:** 60 requests per minute

### Required Headers

| Key          | Value    | Required | Description                                       |
| ------------ | -------- | -------- | ------------------------------------------------- |
| `x-store-id` | `string` | Yes      | Store identifier (used by `@StoreId()` decorator) |

### Query Parameters

| Parameter   | Type      | Required | Description                                         | Default     |
| ----------- | --------- | -------- | --------------------------------------------------- | ----------- |
| `search`    | `string`  | No       | Partial match for group name or description         | —           |
| `name`      | `string`  | No       | Partial match for group name                        | —           |
| `isActive`  | `boolean` | No       | Filter by active status (currently not implemented) | —           |
| `page`      | `number`  | No       | Page number (1-based)                               | `1`         |
| `limit`     | `number`  | No       | Items per page (1–100)                              | `10`        |
| `sortBy`    | `string`  | No       | Sort field (`name`, `createdAt`, `updatedAt`)       | `createdAt` |
| `sortOrder` | `string`  | No       | Sort direction (`asc` or `desc`)                    | `desc`      |

### Success Response

**Status Code:** `200 OK`

```json theme={null}
{
  "data": [
    {
      "id": "cgrp_abc123",
      "name": "VIP Customers",
      "description": "Premium customers with special pricing",
      "createdAt": "2025-10-01T09:00:00.000Z",
      "updatedAt": "2025-10-15T12:30:00.000Z"
    },
    {
      "id": "cgrp_def456",
      "name": "Regular Customers",
      "description": "Standard customer group",
      "createdAt": "2025-09-15T08:00:00.000Z",
      "updatedAt": "2025-09-20T10:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 4,
    "totalPages": 1,
    "hasNext": false,
    "hasPrev": false
  }
}
```

### Response Fields

#### CustomerGroup Object

| Field         | Type     | Description                      |
| ------------- | -------- | -------------------------------- |
| `id`          | `string` | Unique customer group ID         |
| `name`        | `string` | Group name                       |
| `description` | `string` | Description of the group         |
| `createdAt`   | `string` | Creation timestamp (ISO 8601)    |
| `updatedAt`   | `string` | Last update timestamp (ISO 8601) |

#### Pagination Object

| Field        | Type      | Description                    |
| ------------ | --------- | ------------------------------ |
| `page`       | `number`  | Current page number            |
| `limit`      | `number`  | Number of items per page       |
| `total`      | `number`  | Total number of records        |
| `totalPages` | `number`  | Total pages available          |
| `hasNext`    | `boolean` | Whether a next page exists     |
| `hasPrev`    | `boolean` | Whether a previous page exists |

### Possible Errors

| Code | Message                                            |
| ---- | -------------------------------------------------- |
| 401  | Unauthorized                                       |
| 403  | Forbidden - User does not have access to the store |
| 500  | Internal Server Error                              |

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://joptic.jethings.com/customer-group?page=1&limit=10" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>"
  ```

  ```javascript JavaScript theme={null}
  const params = new URLSearchParams({
    page: "1",
    limit: "10",
    sortBy: "name",
    sortOrder: "asc"
  })

  const response = await fetch(`https://joptic.jethings.com/customer-group?${params}`, {
    method: "GET",
    headers: {
      "x-store-id": "your-store-id",
      Authorization: "Bearer <token>",
    },
  })

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  url = "https://joptic.jethings.com/customer-group"

  params = {
      "page": 1,
      "limit": 10,
      "sortBy": "name",
      "sortOrder": "asc"
  }

  response = requests.get(
      url,
      headers={
          "x-store-id": "your-store-id",
          "Authorization": "Bearer <token>"
      },
      params=params
  )

  print(response.json())
  ```
</CodeGroup>

Search by name or description:

```bash theme={null}
curl -X GET "https://joptic.jethings.com/customer-group?search=VIP" \
  -H "x-store-id: your-store-id" \
  -H "Authorization: Bearer <token>"
```

<Note>
  The search parameter performs a case-insensitive search across both group name and description fields. Results are paginated for performance. Default sorting is by creation date (newest first).
</Note>

***

## Get Customer Group by ID

**GET** `/customer-group/:id`

Retrieve a single customer group by its ID.

**Requires Authentication:** Bearer token in Authorization header

**Rate Limited:** 60 requests per minute

### Path Parameters

| Parameter | Type     | Required | Description           |
| --------- | -------- | -------- | --------------------- |
| `id`      | `string` | ✅ Yes    | The customer group ID |

### Success Response

**Status Code:** `200 OK`

```json theme={null}
{
  "id": "cgrp_abc123",
  "name": "VIP Customers",
  "description": "Premium customers with special pricing",
  "createdAt": "2025-10-01T09:00:00.000Z",
  "updatedAt": "2025-10-15T12:30:00.000Z"
}
```

### Response Fields

| Field         | Type     | Description                      |
| ------------- | -------- | -------------------------------- |
| `id`          | `string` | Unique customer group ID         |
| `name`        | `string` | Group name                       |
| `description` | `string` | Description of the group         |
| `createdAt`   | `string` | Creation timestamp (ISO 8601)    |
| `updatedAt`   | `string` | Last update timestamp (ISO 8601) |

### Possible Errors

| Code | Message                              |
| ---- | ------------------------------------ |
| 401  | Unauthorized                         |
| 404  | Not Found - Customer group not found |
| 500  | Internal Server Error                |

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://joptic.jethings.com/customer-group/cgrp_abc123" \
    -H "Authorization: Bearer <token>"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://joptic.jethings.com/customer-group/cgrp_abc123", {
    method: "GET",
    headers: {
      Authorization: "Bearer <token>",
    },
  })

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  url = "https://joptic.jethings.com/customer-group/cgrp_abc123"

  response = requests.get(
      url,
      headers={
          "Authorization": "Bearer <token>"
      }
  )

  print(response.json())
  ```
</CodeGroup>

<Note>
  This endpoint does not require the `x-store-id` header. It retrieves the customer group by ID regardless of store association.
</Note>

***

## Delete Customer Groups (Bulk)

**DELETE** `/customer-group`

Delete one or more customer groups by their IDs. This is a bulk delete operation that allows removing multiple groups in a single request.

**Requires Authentication:** Bearer token in Authorization header

**Rate Limited:** 3 requests per minute

### Request Body

| Field | Type            | Required | Description                           |
| ----- | --------------- | -------- | ------------------------------------- |
| `ids` | `array<string>` | ✅ Yes    | Array of customer group IDs to delete |

### Request Body Example

```json theme={null}
{
  "ids": [
    "cgrp_abc123",
    "cgrp_def456",
    "cgrp_ghi789"
  ]
}
```

### Success Response

**Status Code:** `200 OK`

```json theme={null}
{
  "message": "Deleted 3 customer group(s)",
  "deletedCount": 3
}
```

### Response Fields

| Field          | Type     | Description                       |
| -------------- | -------- | --------------------------------- |
| `message`      | `string` | Success message with count        |
| `deletedCount` | `number` | Number of customer groups deleted |

### Possible Errors

| Code | Message                                       |
| ---- | --------------------------------------------- |
| 400  | Bad Request - No IDs provided or empty array  |
| 401  | Unauthorized                                  |
| 404  | Not Found - No matching customer groups found |
| 500  | Internal Server Error                         |

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE "https://joptic.jethings.com/customer-group" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "ids": ["cgrp_abc123", "cgrp_def456"]
    }'
  ```

  ```javascript JavaScript theme={null}
  const deleteData = {
    ids: ["cgrp_abc123", "cgrp_def456"]
  }

  const response = await fetch("https://joptic.jethings.com/customer-group", {
    method: "DELETE",
    headers: {
      Authorization: "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify(deleteData),
  })

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  url = "https://joptic.jethings.com/customer-group"

  delete_data = {
      "ids": ["cgrp_abc123", "cgrp_def456"]
  }

  response = requests.delete(
      url,
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json"
      },
      json=delete_data
  )

  print(response.json())
  ```
</CodeGroup>

<Warning>
  This is a bulk delete operation. Only valid customer group IDs are deleted (invalid IDs are ignored). Returns the count of successfully deleted groups. This operation is permanent and cannot be undone. Rate limited to 3 requests per minute for safety.
</Warning>

***

## Assign Customer to Group

**POST** `/customer-group/assign-group`

Assign a customer to a customer group. This creates a relationship between a customer and a customer group.

**Requires Authentication:** Bearer token in Authorization header

**Rate Limited:** 10 requests per minute

### Request Body

| Field             | Type     | Required | Description                  |
| ----------------- | -------- | -------- | ---------------------------- |
| `customerId`      | `string` | ✅ Yes    | ID of the customer to assign |
| `CustomerGroupId` | `string` | ✅ Yes    | ID of the customer group     |

### Request Body Example

```json theme={null}
{
  "customerId": "customer_123",
  "CustomerGroupId": "cgrp_abc123"
}
```

### Success Response

**Status Code:** `200 OK`

```json theme={null}
{
  "id": "relation_xyz789",
  "customerGroupId": "cgrp_abc123",
  "customerId": "customer_123",
  "createdAt": "2025-11-03T10:00:00.000Z"
}
```

### Response Fields

| Field             | Type     | Description                   |
| ----------------- | -------- | ----------------------------- |
| `id`              | `string` | Unique relation ID            |
| `customerGroupId` | `string` | Customer group ID             |
| `customerId`      | `string` | Customer ID                   |
| `createdAt`       | `string` | Creation timestamp (ISO 8601) |

### Possible Errors

| Code | Message                                                     |
| ---- | ----------------------------------------------------------- |
| 400  | Bad Request - Invalid input data or missing required fields |
| 401  | Unauthorized                                                |
| 404  | Not Found - Customer or customer group not found            |
| 500  | Internal Server Error                                       |

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://joptic.jethings.com/customer-group/assign-group" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "customerId": "customer_123",
      "CustomerGroupId": "cgrp_abc123"
    }'
  ```

  ```javascript JavaScript theme={null}
  const assignData = {
    customerId: "customer_123",
    CustomerGroupId: "cgrp_abc123"
  }

  const response = await fetch("https://joptic.jethings.com/customer-group/assign-group", {
    method: "POST",
    headers: {
      Authorization: "Bearer <token>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify(assignData),
  })

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  url = "https://joptic.jethings.com/customer-group/assign-group"

  assign_data = {
      "customerId": "customer_123",
      "CustomerGroupId": "cgrp_abc123"
  }

  response = requests.post(
      url,
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json"
      },
      json=assign_data
  )

  print(response.json())
  ```
</CodeGroup>

<Note>
  If a customer is already assigned to the group, the operation may fail or create a duplicate relation depending on your database constraints. Ensure the customer and customer group IDs exist before assignment.
</Note>

***

## Business Logic

### Customer Group Management

<AccordionGroup>
  <Accordion title="Default Price List Association" icon="tag">
    **Default Price List Association**

    Customer groups can have default price lists:

    1. When creating a group, you must specify a `defaultPriceListId`
    2. This price list can be used for automatic pricing when processing orders for customers in the group
    3. The price list ID must reference an existing price list in your system
    4. Default price lists help streamline pricing for groups of customers
  </Accordion>

  <Accordion title="Store Access Control" icon="shield">
    **Store Access Control**

    Customer group operations are protected:

    1. Users must have an active relation with the store (via `userStoreRelation`)
    2. The `x-store-id` header is required for store-scoped operations
    3. If a user doesn't have access to the store, a 403 Forbidden error is returned
    4. This ensures users can only manage customer groups for stores they have access to
  </Accordion>

  <Accordion title="Search Functionality" icon="search">
    **Search Functionality**

    The search parameter is flexible:

    1. Searches across both group name and description fields
    2. Uses case-insensitive partial matching (LIKE queries)
    3. The `name` parameter is an alias for searching by name specifically
    4. Search results are combined and paginated
  </Accordion>

  <Accordion title="Sorting Options" icon="sort">
    **Sorting Options**

    Customer groups can be sorted by:

    1. `name` - Sort alphabetically by group name
    2. `createdAt` - Sort by creation date (default)
    3. `updatedAt` - Sort by last update date
    4. Sort order can be `asc` (ascending) or `desc` (descending, default)
  </Accordion>

  <Accordion title="Customer Assignment" icon="user-plus">
    **Customer Assignment**

    Assigning customers to groups:

    1. Creates a relation between a customer and a customer group
    2. A customer can be assigned to multiple groups (if your schema allows)
    3. The assignment creates a record in the `customerGroupRelation` table
    4. This relation can be used for filtering, pricing, and reporting
  </Accordion>
</AccordionGroup>

### Customer Group States

<CardGroup cols={2}>
  <Card title="Active Group" icon="users">
    **Active**

    <br />

    Group is available for customer assignment
  </Card>

  <Card title="With Default Price List" icon="tag">
    **Price List Associated**

    <br />

    Group has a default price list for automatic pricing
  </Card>

  <Card title="Searchable" icon="search">
    **Searchable**

    <br />

    Groups can be found by name or description
  </Card>

  <Card title="Sortable" icon="sort">
    **Sortable**

    <br />

    Groups can be sorted by name, createdAt, or updatedAt
  </Card>
</CardGroup>

***

## Error Responses

All endpoints may return standard HTTP error codes:

* `400 Bad Request` - Invalid request parameters or body
* `401 Unauthorized` - Missing or invalid authentication token
* `403 Forbidden` - User does not have access to the store
* `404 Not Found` - Resource not found (customer, customer group, etc.)
* `429 Too Many Requests` - Rate limit exceeded
* `500 Internal Server Error` - Server error

### Error Response Format

```json theme={null}
{
  "statusCode": 403,
  "message": "You do not have access to this store",
  "error": "Forbidden"
}
```

### Common Error Scenarios

**403 Forbidden - Store Access**

```json theme={null}
{
  "statusCode": 403,
  "message": "You do not have access to this store"
}
```

Occurs when the user doesn't have an active relation with the store specified in the `x-store-id` header.

**400 Bad Request - Validation Error**

```json theme={null}
{
  "statusCode": 400,
  "message": ["name must be a string", "defaultPriceListId must be a string"],
  "error": "Bad Request"
}
```

Occurs when required fields are missing or data types are incorrect.

**404 Not Found - Customer or Group**

```json theme={null}
{
  "statusCode": 404,
  "message": "Customer not found"
}
```

Occurs when trying to assign a customer that doesn't exist or reference a non-existent customer group.

***

## Usage Examples

### Example 1: Create a customer group

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://joptic.jethings.com/customer-group" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Premium Members",
      "defaultPriceListId": "price_list_123",
      "description": "Customers with premium membership benefits"
    }'
  ```
</CodeGroup>

### Example 2: Get all customer groups with pagination

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://joptic.jethings.com/customer-group?page=1&limit=20&sortBy=name&sortOrder=asc" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>"
  ```
</CodeGroup>

### Example 3: Search customer groups

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://joptic.jethings.com/customer-group?search=VIP&page=1&limit=10" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>"
  ```
</CodeGroup>

### Example 4: Get customer group by ID

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://joptic.jethings.com/customer-group/cgrp_abc123" \
    -H "Authorization: Bearer <token>"
  ```
</CodeGroup>

### Example 5: Delete multiple customer groups

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE "https://joptic.jethings.com/customer-group" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "ids": ["cgrp_abc123", "cgrp_def456"]
    }'
  ```
</CodeGroup>

### Example 6: Assign customer to group

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://joptic.jethings.com/customer-group/assign-group" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "customerId": "customer_123",
      "CustomerGroupId": "cgrp_abc123"
    }'
  ```
</CodeGroup>

***

## Best Practices

<AccordionGroup>
  <Accordion title="Group Organization">
    * Use descriptive group names that indicate the customer category or tier
    * Organize customers by membership level, purchase behavior, or business relationship
    * Use descriptions to provide additional context about the group's purpose
    * Keep group names consistent and meaningful
  </Accordion>

  <Accordion title="Default Price Lists">
    * Associate appropriate price lists with customer groups for automatic pricing
    * Ensure the price list ID exists before creating a group
    * Update price list associations when business needs change
    * Use price lists to differentiate pricing for different customer segments
  </Accordion>

  <Accordion title="Customer Assignment">
    * Assign customers to groups during customer creation for better organization
    * Use groups to apply consistent pricing across customer segments
    * Monitor group membership for reporting and analytics
    * Reassign customers to groups when their status changes
  </Accordion>

  <Accordion title="Pagination">
    * Use pagination when fetching large lists of groups
    * Default limit of 10 is suitable for most use cases
    * Maximum limit of 100 should be used sparingly
    * Always check `hasNext` and `hasPrev` for navigation
  </Accordion>

  <Accordion title="Search and Filtering">
    * Use the search parameter for quick lookups by name or description
    * Combine search with pagination for efficient data retrieval
    * Use the `name` parameter for more specific name-based filtering
    * Leverage sorting options to organize results by relevance
  </Accordion>

  <Accordion title="Rate Limiting">
    * GET endpoints: 60 requests per minute
    * POST endpoints: 10 requests per minute
    * DELETE endpoints: 3 requests per minute
    * Implement retry logic with exponential backoff for rate limit errors
    * Batch operations when possible to reduce API calls
  </Accordion>

  <Accordion title="Error Handling">
    * Always check for 403 errors when accessing store-scoped endpoints
    * Validate customer and group IDs before assignment
    * Handle 400 validation errors by checking request body structure
    * Implement proper error handling for network and server errors
  </Accordion>
</AccordionGroup>

***

## Related Endpoints

Customer groups work in conjunction with other customer and pricing management endpoints:

* **Customer API** (`/customer`) - Manage customers that can be assigned to groups
* **Price List API** (`/price-lists`) - Manage price lists that can be associated with groups

<Info>
  Customer groups help organize customers by category, making it easier to manage pricing, apply discounts, and segment customers for marketing and reporting purposes. Groups can be associated with default price lists for automatic pricing.
</Info>

***

## Summary

| Endpoint                       | Method   | Description                                      |
| ------------------------------ | -------- | ------------------------------------------------ |
| `/customer-group`              | `POST`   | Create a new customer group (rate: 10/min)       |
| `/customer-group`              | `GET`    | Paginated list of customer groups (rate: 60/min) |
| `/customer-group/:id`          | `GET`    | Get a customer group by ID (rate: 60/min)        |
| `/customer-group`              | `DELETE` | Delete multiple customer groups (rate: 3/min)    |
| `/customer-group/assign-group` | `POST`   | Assign a customer to a group (rate: 10/min)      |

***

<CardGroup cols={2}>
  <Card title="Customer API" icon="users" href="/j-optic/customer-api">
    Create and manage optical customers
  </Card>

  <Card title="Price List API" icon="tag" href="/j-optic/price-list-api">
    Manage price lists for customer groups
  </Card>
</CardGroup>
