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

# Hub Planner API reference

> API reference for the Hub Planner plugin in Corsair: every `hubplanner.api.*` operation with its input and output types, taken from the plugin's Zod schemas.

> [!NOTE]
>
> **New to Corsair?** See [API access](https://docs.corsair.dev/concepts/api.md), [authentication](https://docs.corsair.dev/concepts/auth.md), and [error handling](https://docs.corsair.dev/concepts/error-handling).

## Bookings

### create

`bookings.create`

Create a new resource schedule booking

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.bookings.create({
	resource: '5ba09b645ff58f149a2c2222',
	project: '5ba09b645ff58f149a2cf521',
	start: '2026-12-01',
	end: '2026-12-05',
	title: 'Sprint Planning',
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `start` | `string` | Yes | — |
| `end` | `string` | Yes | — |
| `state` | `string` | No | — |
| `stateValue` | `number` | No | — |
| `title` | `string` | No | — |
| `note` | `string` | No | — |
| `allDay` | `boolean` | No | — |
| `allowOverschedule` | `boolean` | No | — |
| `repeat` | `boolean` | No | — |
| `interval` | `string` | No | — |
| `repeatEndsAfterTimes` | `number` | No | — |
| `repeatEndsOnDate` | `string` | No | — |
| `type` | `string` | No | — |

Requires `resource`, `project`, `start`, and `end` dates (YYYY-MM-DD). Use `allowOverschedule: true` to bypass schedule warning thresholds. `type: 'WAITING_FOR_APPROVAL'` creates a booking request (requesting & approval extension).

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `title` | `string \| null` | No | — |
| `state` | `string \| null` | No | — |
| `allDay` | `boolean \| null` | No | — |
| `start` | `string` | Yes | — |
| `end` | `string` | Yes | — |
| `stateValue` | `number \| null` | No | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `categoryTemplateId` | `string \| null` | No | — |
| `categoryName` | `string \| null` | No | — |
| `bookingCreatorId` | `string \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

***

### delete

`bookings.delete`

Delete a specific booking by ID

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.bookings.delete({ bookingId: '5b1977ade02d407011112222' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `bookingId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |

***

### deleteBulk

`bookings.deleteBulk`

Bulk delete bookings by IDs, or every booking of one resource or one project

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.bookings.deleteBulk({
	ids: ['5b1977ade02d407011112222'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `ids` | `string[]` | No | — |
| `resourceId` | `string` | No | — |
| `projectId` | `string` | No | — |

Pass exactly one of `ids`, `resourceId` or `projectId`. `resourceId` and `projectId` delete every booking of that resource or project.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `message` | `string \| null` | No | — |
| `deletedCount` | `number` | Yes | — |

***

### get

`bookings.get`

Get booking details by booking ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.bookings.get({ bookingId: '5b1977ade02d407011112222' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `bookingId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `title` | `string \| null` | No | — |
| `state` | `string \| null` | No | — |
| `allDay` | `boolean \| null` | No | — |
| `start` | `string` | Yes | — |
| `end` | `string` | Yes | — |
| `stateValue` | `number \| null` | No | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `categoryTemplateId` | `string \| null` | No | — |
| `categoryName` | `string \| null` | No | — |
| `bookingCreatorId` | `string \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

***

### list

`bookings.list`

List scheduled bookings with pagination and filters

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.bookings.list({ limit: 20 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `skip` | `number` | No | — |
| `cursor` | `string` | No | — |
| `sort` | `string` | No | — |
| `deleted` | `boolean` | No | — |
| `dependencies` | `boolean` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   title?: string | null,
>   state?: string | null,
>   allDay?: boolean | null,
>   start: string,
>   end: string,
>   stateValue?: number | null,
>   resource: string,
>   project: string,
>   note?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   metadata?: string | null,
>   type?: string | null,
>   categoryTemplateId?: string | null,
>   categoryName?: string | null,
>   bookingCreatorId?: string | null,
>   customFields?: any[] | null
> }[]
> ```

***

### patch

`bookings.patch`

Patch specific properties of a booking or approve/reject booking requests

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.bookings.patch({ bookingId: '5b1977ade02d407011112222', type: 'APPROVED' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `bookingId` | `string` | Yes | — |
| `type` | `string` | No | — |
| `approvalInfo` | `Record<string, any>` | No | — |
| `allowOverschedule` | `boolean` | No | — |
| `state` | `string` | No | — |
| `stateValue` | `number` | No | — |
| `start` | `string` | No | — |
| `end` | `string` | No | — |
| `title` | `string` | No | — |
| `note` | `string` | No | — |

Used for partial updates or for approving/rejecting booking requests with `type: 'APPROVED'` or `'REJECTED'`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `title` | `string \| null` | No | — |
| `state` | `string \| null` | No | — |
| `allDay` | `boolean \| null` | No | — |
| `start` | `string` | Yes | — |
| `end` | `string` | Yes | — |
| `stateValue` | `number \| null` | No | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `categoryTemplateId` | `string \| null` | No | — |
| `categoryName` | `string \| null` | No | — |
| `bookingCreatorId` | `string \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

***

### search

`bookings.search`

Search bookings matching criteria such as date range or project

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.bookings.search({
	query: { project: '5ba09b645ff58f149a2cf521' },
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `query` | `Record<string, any>` | No | — |
| `dependencies` | `boolean` | No | — |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   title?: string | null,
>   state?: string | null,
>   allDay?: boolean | null,
>   start: string,
>   end: string,
>   stateValue?: number | null,
>   resource: string,
>   project: string,
>   note?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   metadata?: string | null,
>   type?: string | null,
>   categoryTemplateId?: string | null,
>   categoryName?: string | null,
>   bookingCreatorId?: string | null,
>   customFields?: any[] | null
> }[]
> ```

***

### update

`bookings.update`

Update all properties of an existing booking

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.bookings.update({
	bookingId: '5b1977ade02d407011112222',
	resource: '5ba09b645ff58f149a2c2222',
	project: '5ba09b645ff58f149a2cf521',
	start: '2026-12-01',
	end: '2026-12-06',
	title: 'Sprint Planning',
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `bookingId` | `string` | Yes | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `start` | `string` | Yes | — |
| `end` | `string` | Yes | — |
| `state` | `string` | No | — |
| `stateValue` | `number` | No | — |
| `title` | `string` | No | — |
| `note` | `string` | No | — |
| `allDay` | `boolean` | No | — |
| `allowOverschedule` | `boolean` | No | — |
| `type` | `string` | No | — |
| `metadata` | `string` | No | — |
| `categoryTemplateId` | `string` | No | — |
| `customFields` | `Record<string, any>[]` | No | — |

PUT replaces the booking: send every stored field you want to keep (title, note, type, metadata, categoryTemplateId, customFields), or use bookings.patch for a partial change.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `title` | `string \| null` | No | — |
| `state` | `string \| null` | No | — |
| `allDay` | `boolean \| null` | No | — |
| `start` | `string` | Yes | — |
| `end` | `string` | Yes | — |
| `stateValue` | `number \| null` | No | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `categoryTemplateId` | `string \| null` | No | — |
| `categoryName` | `string \| null` | No | — |
| `bookingCreatorId` | `string \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

***

## Categories

### create

`categories.create`

Create a new booking category in a group

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.categories.create({ groupId: '66e81d231d512707a7266d32', name: 'Design Review' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `groupId` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `gridColor` | `string` | No | — |
| `type` | `NON_OPTIONAL \| CUSTOM` | Yes | — |

Requires `groupId`, `name` and `type`. `type: 'NON_OPTIONAL'` sets the category as the group's default; use `'CUSTOM'` otherwise.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `gridColor` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `categoryGroupId` | `string \| null` | No | — |
| `categoryGroupName` | `string \| null` | No | — |

***

### createCostCategory

`categories.createCostCategory`

Create a new project cost category

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.categories.createCostCategory({ name: 'Travel Expenses' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |

***

### deleteCostCategory

`categories.deleteCostCategory`

Delete a project cost category by ID

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.categories.deleteCostCategory({ costCategoryId: '5f057949f338cd432a794a13' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `costCategoryId` | `string` | Yes | — |

**Output:** `undefined`

***

### get

`categories.get`

Get booking category details by category ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.categories.get({ categoryId: '5f057949f338cd432a794a12' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `categoryId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `gridColor` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `categoryGroupId` | `string \| null` | No | — |
| `categoryGroupName` | `string \| null` | No | — |

***

### getCostCategory

`categories.getCostCategory`

Get project cost category by ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.categories.getCostCategory({ costCategoryId: '5f057949f338cd432a794a13' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `costCategoryId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |

***

### list

`categories.list`

List all booking categories

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.categories.list({});
```

**Input:** *empty object*

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   gridColor?: string | null,
>   type?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   categoryGroupId?: string | null,
>   categoryGroupName?: string | null
> }[]
> ```

***

### listCostCategories

`categories.listCostCategories`

List all project cost categories

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.categories.listCostCategories({});
```

**Input:** *empty object*

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   createdDate?: string | null,
>   updatedDate?: string | null
> }[]
> ```

***

### listGroups

`categories.listGroups`

List booking category groups

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.categories.listGroups({});
```

**Input:** *empty object*

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   type?: string | null
> }[]
> ```

***

### search

`categories.search`

Search booking categories by name or group

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.categories.search({
	query: { name: 'Design' },
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `query` | `Record<string, any>` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   gridColor?: string | null,
>   type?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   categoryGroupId?: string | null,
>   categoryGroupName?: string | null
> }[]
> ```

***

### searchCostCategories

`categories.searchCostCategories`

Search project cost categories by name

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.categories.searchCostCategories({
	query: { name: 'Travel' },
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `query` | `Record<string, any>` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   createdDate?: string | null,
>   updatedDate?: string | null
> }[]
> ```

***

### update

`categories.update`

Update an existing booking category

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.categories.update({ categoryId: '5f057949f338cd432a794a12', name: 'Design Sprint', gridColor: '#4A90E2' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `categoryId` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `gridColor` | `string` | No | — |
| `type` | `NON_OPTIONAL \| CUSTOM` | Yes | — |

PUT replaces the category: send `name`, `gridColor` and `type` together.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `gridColor` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `categoryGroupId` | `string \| null` | No | — |
| `categoryGroupName` | `string \| null` | No | — |

***

### updateCostCategory

`categories.updateCostCategory`

Update an existing project cost category

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.categories.updateCostCategory({ costCategoryId: '5f057949f338cd432a794a13', name: 'Domestic Travel' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `costCategoryId` | `string` | Yes | — |
| `name` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |

***

## Custom Fields

### addChoices

`customFields.addChoices`

Add options to dropdown or selection custom field templates

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.customFields.addChoices({
	entityType: 'project',
	id: '669554d27dc15b5590a1b831',
	choices: [{ value: 'Tier 1' }, { value: 'Tier 2' }],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `entityType` | `string` | Yes | — |
| `id` | `string` | Yes | — |
| `choices` | `object[]` | Yes | — |

> [accordion] choices full type
>
> ```ts theme={null}
> {
>   value: string
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `type` | `string` | Yes | — |
| `label` | `string` | Yes | — |
| `instructions` | `string \| null` | No | — |
| `placeholderText` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `allowMultipleValues` | `boolean \| string \| null` | No | — |
| `isRequired` | `boolean \| string \| null` | No | — |
| `canResourceEdit` | `boolean \| string \| null` | No | — |
| `characterLimit` | `number \| string \| null` | No | — |
| `isChoicesSortedAlphabetically` | `boolean \| string \| null` | No | — |
| `choices` | `object[] \| null` | No | — |
| `defaultValue` | `string \| null` | No | — |

> [accordion] choices full type
>
> ```ts theme={null}
> {
>   _id?: string | null,
>   value: string
> }[] | null
> ```

***

### create

`customFields.create`

Create a new custom field template for projects or resources

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.customFields.create({ entityType: 'project', type: 'TEXT', label: 'Purchase Order' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `entityType` | `string` | Yes | — |
| `type` | `string` | Yes | — |
| `label` | `string` | Yes | — |
| `instructions` | `string` | No | — |
| `placeholderText` | `string` | No | — |
| `status` | `string` | No | — |
| `allowMultipleValues` | `boolean` | No | — |
| `isRequired` | `boolean` | No | — |
| `canResourceEdit` | `boolean` | No | — |
| `characterLimit` | `string` | No | — |
| `isChoicesSortedAlphabetically` | `boolean` | No | — |
| `choices` | `object[]` | No | — |
| `defaultValue` | `string` | No | — |

`entityType` must be either `'project'` or `'resource'`. Requires `type` (e.g., `'TEXT'`, `'select'`) and `label`.

> [accordion] choices full type
>
> ```ts theme={null}
> {
>   value: string
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `type` | `string` | Yes | — |
| `label` | `string` | Yes | — |
| `instructions` | `string \| null` | No | — |
| `placeholderText` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `allowMultipleValues` | `boolean \| string \| null` | No | — |
| `isRequired` | `boolean \| string \| null` | No | — |
| `canResourceEdit` | `boolean \| string \| null` | No | — |
| `characterLimit` | `number \| string \| null` | No | — |
| `isChoicesSortedAlphabetically` | `boolean \| string \| null` | No | — |
| `choices` | `object[] \| null` | No | — |
| `defaultValue` | `string \| null` | No | — |

> [accordion] choices full type
>
> ```ts theme={null}
> {
>   _id?: string | null,
>   value: string
> }[] | null
> ```

***

### delete

`customFields.delete`

Delete a custom field template by ID

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.customFields.delete({ entityType: 'project', id: '669554d27dc15b5590a1b831' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `entityType` | `string` | Yes | — |
| `id` | `string` | Yes | — |

**Output:** `undefined`

***

### get

`customFields.get`

Get custom field template details by ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.customFields.get({ entityType: 'project', id: '669554d27dc15b5590a1b831' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `entityType` | `string` | Yes | — |
| `id` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `type` | `string` | Yes | — |
| `label` | `string` | Yes | — |
| `instructions` | `string \| null` | No | — |
| `placeholderText` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `allowMultipleValues` | `boolean \| string \| null` | No | — |
| `isRequired` | `boolean \| string \| null` | No | — |
| `canResourceEdit` | `boolean \| string \| null` | No | — |
| `characterLimit` | `number \| string \| null` | No | — |
| `isChoicesSortedAlphabetically` | `boolean \| string \| null` | No | — |
| `choices` | `object[] \| null` | No | — |
| `defaultValue` | `string \| null` | No | — |

> [accordion] choices full type
>
> ```ts theme={null}
> {
>   _id?: string | null,
>   value: string
> }[] | null
> ```

***

### list

`customFields.list`

List custom field templates for projects or resources

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.customFields.list({ entityType: 'project' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `entityType` | `string` | Yes | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   type: string,
>   label: string,
>   instructions?: string | null,
>   placeholderText?: string | null,
>   status?: string | null,
>   allowMultipleValues?: boolean | string | null,
>   isRequired?: boolean | string | null,
>   canResourceEdit?: boolean | string | null,
>   characterLimit?: number | string | null,
>   isChoicesSortedAlphabetically?: boolean | string | null,
>   choices?: {
>     _id?: string | null,
>     value: string
>   }[] | null,
>   defaultValue?: string | null
> }[]
> ```

***

### search

`customFields.search`

Search custom field templates matching filter parameters

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.customFields.search({
	entityType: 'resource',
	query: {},
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `entityType` | `string` | Yes | — |
| `query` | `Record<string, any>` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   type: string,
>   label: string,
>   instructions?: string | null,
>   placeholderText?: string | null,
>   status?: string | null,
>   allowMultipleValues?: boolean | string | null,
>   isRequired?: boolean | string | null,
>   canResourceEdit?: boolean | string | null,
>   characterLimit?: number | string | null,
>   isChoicesSortedAlphabetically?: boolean | string | null,
>   choices?: {
>     _id?: string | null,
>     value: string
>   }[] | null,
>   defaultValue?: string | null
> }[]
> ```

***

### update

`customFields.update`

Replace a custom field template; choices left out of the array are removed from records

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.customFields.update({
	entityType: 'project',
	id: '669554d27dc15b5590a1b831',
	type: 'TEXT',
	label: 'Purchase Order Number',
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `entityType` | `string` | Yes | — |
| `id` | `string` | Yes | — |
| `type` | `string` | Yes | — |
| `label` | `string` | Yes | — |
| `instructions` | `string` | No | — |
| `placeholderText` | `string` | No | — |
| `status` | `string` | No | — |
| `allowMultipleValues` | `boolean` | No | — |
| `isRequired` | `boolean` | No | — |
| `canResourceEdit` | `boolean` | No | — |
| `characterLimit` | `string` | No | — |
| `isChoicesSortedAlphabetically` | `boolean` | No | — |
| `choices` | `object[]` | No | — |
| `defaultValue` | `string` | No | — |

PUT replaces the template. For SELECT, RADIO and CHECKBOX types send the complete `choices` array (existing choices with their `_id`), or the API answers 400.

> [accordion] choices full type
>
> ```ts theme={null}
> {
>   _id?: string,
>   value: string
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `type` | `string` | Yes | — |
| `label` | `string` | Yes | — |
| `instructions` | `string \| null` | No | — |
| `placeholderText` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `allowMultipleValues` | `boolean \| string \| null` | No | — |
| `isRequired` | `boolean \| string \| null` | No | — |
| `canResourceEdit` | `boolean \| string \| null` | No | — |
| `characterLimit` | `number \| string \| null` | No | — |
| `isChoicesSortedAlphabetically` | `boolean \| string \| null` | No | — |
| `choices` | `object[] \| null` | No | — |
| `defaultValue` | `string \| null` | No | — |

> [accordion] choices full type
>
> ```ts theme={null}
> {
>   _id?: string | null,
>   value: string
> }[] | null
> ```

***

## Events

### create

`events.create`

Create a new company event

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.events.create({ name: 'Quarterly Planning', eventCode: 'QPLAN' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | — |
| `eventCode` | `string` | No | — |
| `backgroundColor` | `string` | No | — |
| `metadata` | `string` | No | — |

Requires event `name`. Color and metadata custom fields are optional.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `eventCode` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |

***

### delete

`events.delete`

Delete a company event by ID

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.events.delete({ eventId: '53a168304cc0f1bb16a898ca' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `eventId` | `string` | Yes | — |

**Output:** `boolean`

***

### get

`events.get`

Get company event details by event ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.events.get({ eventId: '53a168304cc0f1bb16a898ca' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `eventId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `eventCode` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |

***

### list

`events.list`

List company events with pagination and sorting

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.events.list({ limit: 10 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   eventCode?: string | null,
>   backgroundColor?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   metadata?: string | null
> }[]
> ```

***

### search

`events.search`

Search events by name or event code

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.events.search({
	query: { name: 'Planning' },
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `query` | `Record<string, any>` | No | — |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   eventCode?: string | null,
>   backgroundColor?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   metadata?: string | null
> }[]
> ```

***

### update

`events.update`

Update an existing company event

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.events.update({ eventId: '53a168304cc0f1bb16a898ca', name: 'Q1 Planning' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `eventId` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `eventCode` | `string` | No | — |
| `backgroundColor` | `string` | No | — |
| `metadata` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `eventCode` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |

***

## Milestones

### create

`milestones.create`

Create a new project milestone date

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.milestones.create({ name: 'Alpha Release', date: '2026-12-15', project: '5ba09b645ff58f149a2cf521' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | — |
| `date` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `metadata` | `string` | No | — |

Requires `name`, `date` (YYYY-MM-DD), and `project`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `date` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `metadata` | `string \| null` | No | — |

***

### delete

`milestones.delete`

Delete a project milestone by ID

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.milestones.delete({ milestoneId: '54785431e91e5ead13e8d841' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `milestoneId` | `string` | Yes | — |

**Output:** `boolean`

***

### get

`milestones.get`

Get milestone details by milestone ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.milestones.get({ milestoneId: '54785431e91e5ead13e8d841' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `milestoneId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `date` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `metadata` | `string \| null` | No | — |

***

### list

`milestones.list`

List milestones with pagination and sorting

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.milestones.list({ limit: 10 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

Hub Planner has no GET /milestone, so this runs an empty milestone search.

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   date: string,
>   project: string,
>   metadata?: string | null
> }[]
> ```

***

### search

`milestones.search`

Search milestones by project or date range

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.milestones.search({
	query: { project: '5ba09b645ff58f149a2cf521' },
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `query` | `Record<string, any>` | No | — |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   date: string,
>   project: string,
>   metadata?: string | null
> }[]
> ```

***

### update

`milestones.update`

Update an existing project milestone

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.milestones.update({
	milestoneId: '54785431e91e5ead13e8d841',
	name: 'Alpha Release v1.0',
	date: '2026-12-18',
	project: '5ba09b645ff58f149a2cf521',
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `milestoneId` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `date` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `metadata` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `date` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `metadata` | `string \| null` | No | — |

***

## Projects

### addClients

`projects.addClients`

Associate client organizations with a project

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.projects.addClients({
	projectId: '5ba09b645ff58f149a2cf521',
	clientIds: ['65ca012029601f211c2864b0'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `string` | Yes | — |
| `clientIds` | `string[]` | Yes | — |

**Output:** `boolean`

***

### addResources

`projects.addResources`

Assign resources to a project

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.projects.addResources({
	projectId: '5ba09b645ff58f149a2cf521',
	resourceIds: ['5ba09b645ff58f149a2c2222'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `string` | Yes | — |
| `resourceIds` | `string[]` | Yes | — |

**Output:** `boolean`

***

### addTags

`projects.addTags`

Add tags to a project

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.projects.addTags({
	projectId: '5ba09b645ff58f149a2cf521',
	tags: ['5bb1e49065e0555544443333'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `string` | Yes | — |
| `tags` | `string[]` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `links` | `Record<string, string> \| null` | No | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `timeEntryEnabled` | `boolean \| null` | No | — |
| `timeEntryLocked` | `boolean \| null` | No | — |
| `timeEntryApproval` | `boolean \| null` | No | — |
| `projectCode` | `string \| null` | No | — |
| `timeEntryNoteRequired` | `boolean \| null` | No | — |
| `budgetHours` | `number \| null` | No | — |
| `budgetCashAmount` | `number \| null` | No | — |
| `budgetCurrency` | `string \| null` | No | — |
| `useStatusColor` | `boolean \| null` | No | — |
| `status` | `string \| null` | No | — |
| `useProjectDuration` | `boolean \| null` | No | — |
| `start` | `string \| null` | No | — |
| `end` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `projectManagers` | `string[] \| null` | No | — |
| `resources` | `string[] \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customers` | `Record<string, any>[] \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

> [accordion] tags full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[] | null
> ```

***

### create

`projects.create`

Create a new project

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.projects.create({ name: 'Website Redesign', budgetHours: 120 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | — |
| `note` | `string` | No | — |
| `projectCode` | `string` | No | — |
| `timeEntryEnabled` | `boolean` | No | — |
| `timeEntryLocked` | `boolean` | No | — |
| `timeEntryApproval` | `boolean` | No | — |
| `timeEntryNoteRequired` | `boolean` | No | — |
| `budgetHours` | `number` | No | — |
| `budgetCashAmount` | `number` | No | — |
| `budgetCurrency` | `string` | No | — |
| `useStatusColor` | `boolean` | No | — |
| `status` | `string` | No | — |
| `useProjectDuration` | `boolean` | No | — |
| `start` | `string` | No | — |
| `end` | `string` | No | — |
| `backgroundColor` | `string` | No | — |
| `metadata` | `string` | No | — |
| `projectManagers` | `string[]` | No | — |
| `resources` | `string[]` | No | — |
| `customFields` | `Record<string, any>[]` | No | — |

Project `name` is required. Optional properties like `budgetHours` and `budgetCashAmount` configure budget limits.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `links` | `Record<string, string> \| null` | No | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `timeEntryEnabled` | `boolean \| null` | No | — |
| `timeEntryLocked` | `boolean \| null` | No | — |
| `timeEntryApproval` | `boolean \| null` | No | — |
| `projectCode` | `string \| null` | No | — |
| `timeEntryNoteRequired` | `boolean \| null` | No | — |
| `budgetHours` | `number \| null` | No | — |
| `budgetCashAmount` | `number \| null` | No | — |
| `budgetCurrency` | `string \| null` | No | — |
| `useStatusColor` | `boolean \| null` | No | — |
| `status` | `string \| null` | No | — |
| `useProjectDuration` | `boolean \| null` | No | — |
| `start` | `string \| null` | No | — |
| `end` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `projectManagers` | `string[] \| null` | No | — |
| `resources` | `string[] \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customers` | `Record<string, any>[] \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

> [accordion] tags full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[] | null
> ```

***

### delete

`projects.delete`

Delete a specific project by ID

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.projects.delete({ projectId: '5ba09b645ff58f149a2cf521' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `string` | Yes | — |

**Output:** `boolean`

***

### deleteBulk

`projects.deleteBulk`

Delete multiple projects by their IDs

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.projects.deleteBulk({
	projectIds: ['5ba09b645ff58f149a2cf521'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectIds` | `string[]` | Yes | — |

**Output:** `string[]`

***

### get

`projects.get`

Get project details by project ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.projects.get({ projectId: '5ba09b645ff58f149a2cf521' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `links` | `Record<string, string> \| null` | No | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `timeEntryEnabled` | `boolean \| null` | No | — |
| `timeEntryLocked` | `boolean \| null` | No | — |
| `timeEntryApproval` | `boolean \| null` | No | — |
| `projectCode` | `string \| null` | No | — |
| `timeEntryNoteRequired` | `boolean \| null` | No | — |
| `budgetHours` | `number \| null` | No | — |
| `budgetCashAmount` | `number \| null` | No | — |
| `budgetCurrency` | `string \| null` | No | — |
| `useStatusColor` | `boolean \| null` | No | — |
| `status` | `string \| null` | No | — |
| `useProjectDuration` | `boolean \| null` | No | — |
| `start` | `string \| null` | No | — |
| `end` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `projectManagers` | `string[] \| null` | No | — |
| `resources` | `string[] \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customers` | `Record<string, any>[] \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

> [accordion] tags full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[] | null
> ```

***

### getTags

`projects.getTags`

List tags associated with a project

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.projects.getTags({ projectId: '5ba09b645ff58f149a2cf521' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `string` | Yes | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[]
> ```

***

### list

`projects.list`

List all projects with pagination and sorting

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.projects.list({ limit: 20 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   links?: Record<string, string> | null,
>   note?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   timeEntryEnabled?: boolean | null,
>   timeEntryLocked?: boolean | null,
>   timeEntryApproval?: boolean | null,
>   projectCode?: string | null,
>   timeEntryNoteRequired?: boolean | null,
>   budgetHours?: number | null,
>   budgetCashAmount?: number | null,
>   budgetCurrency?: string | null,
>   useStatusColor?: boolean | null,
>   status?: string | null,
>   useProjectDuration?: boolean | null,
>   start?: string | null,
>   end?: string | null,
>   backgroundColor?: string | null,
>   metadata?: string | null,
>   projectManagers?: string[] | null,
>   resources?: string[] | null,
>   tags?: {
>     tagId: string,
>     value: string,
>     _id?: string | null
>   }[] | null,
>   customers?: Record<string, any>[] | null,
>   customFields?: any[] | null
> }[]
> ```

***

### removeClient

`projects.removeClient`

Dissociate a client organization from projects

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.projects.removeClient({
	clientId: '65ca012029601f211c2864b0',
	projectIds: ['5ba09b645ff58f149a2cf521'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `clientId` | `string` | Yes | — |
| `projectIds` | `string[]` | Yes | — |

**Output:** `boolean`

***

### removeResource

`projects.removeResource`

Remove a resource from multiple projects

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.projects.removeResource({
	resourceId: '5ba09b645ff58f149a2c2222',
	projectIds: ['5ba09b645ff58f149a2cf521'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resourceId` | `string` | Yes | — |
| `projectIds` | `string[]` | Yes | — |

**Output:** `boolean`

***

### removeTag

`projects.removeTag`

Remove a tag from a project

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.projects.removeTag({ projectId: '5ba09b645ff58f149a2cf521', tagId: '5bbcaa1ae9fcfa1a87cd5f0e' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `string` | Yes | — |
| `tagId` | `string` | Yes | — |

**Output:** `undefined`

***

### search

`projects.search`

Search projects matching custom criteria

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.projects.search({
	query: { status: 'STATUS_ACTIVE' },
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `query` | `Record<string, any>` | No | — |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name: string,
>   links?: Record<string, string> | null,
>   note?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   timeEntryEnabled?: boolean | null,
>   timeEntryLocked?: boolean | null,
>   timeEntryApproval?: boolean | null,
>   projectCode?: string | null,
>   timeEntryNoteRequired?: boolean | null,
>   budgetHours?: number | null,
>   budgetCashAmount?: number | null,
>   budgetCurrency?: string | null,
>   useStatusColor?: boolean | null,
>   status?: string | null,
>   useProjectDuration?: boolean | null,
>   start?: string | null,
>   end?: string | null,
>   backgroundColor?: string | null,
>   metadata?: string | null,
>   projectManagers?: string[] | null,
>   resources?: string[] | null,
>   tags?: {
>     tagId: string,
>     value: string,
>     _id?: string | null
>   }[] | null,
>   customers?: Record<string, any>[] | null,
>   customFields?: any[] | null
> }[]
> ```

***

### setProjectManagers

`projects.setProjectManagers`

Replace the project manager list of a project (managers not listed are removed)

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.projects.setProjectManagers({
	projectId: '5ba09b645ff58f149a2cf521',
	managerIds: ['5ba09fc85ff58f149a2c2222'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `string` | Yes | — |
| `managerIds` | `string[]` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `name` | `string` | Yes | — |
| `links` | `Record<string, string> \| null` | No | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `timeEntryEnabled` | `boolean \| null` | No | — |
| `timeEntryLocked` | `boolean \| null` | No | — |
| `timeEntryApproval` | `boolean \| null` | No | — |
| `projectCode` | `string \| null` | No | — |
| `timeEntryNoteRequired` | `boolean \| null` | No | — |
| `budgetHours` | `number \| null` | No | — |
| `budgetCashAmount` | `number \| null` | No | — |
| `budgetCurrency` | `string \| null` | No | — |
| `useStatusColor` | `boolean \| null` | No | — |
| `status` | `string \| null` | No | — |
| `useProjectDuration` | `boolean \| null` | No | — |
| `start` | `string \| null` | No | — |
| `end` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `projectManagers` | `string[] \| null` | No | — |
| `resources` | `string[] \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customers` | `Record<string, any>[] \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

> [accordion] tags full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[] | null
> ```

***

### update

`projects.update`

Bulk update projects with modified attributes

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.projects.update({
	projects: [{ _id: '5ba09b645ff58f149a2cf521', name: 'Website Redesign v2' }],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projects` | `object[]` | Yes | — |

Bulk update accepts an array of project objects, each requiring `_id` and the attributes to be modified.

> [accordion] projects full type
>
> ```ts theme={null}
> {
>   _id: string,
>   name?: string,
>   note?: string,
>   projectCode?: string,
>   budgetCashAmount?: number,
>   budgetHours?: number,
>   budgetCurrency?: string,
>   status?: string,
>   backgroundColor?: string,
>   metadata?: string,
>   timeEntryEnabled?: boolean,
>   timeEntryLocked?: boolean,
>   timeEntryApproval?: boolean,
>   timeEntryNoteRequired?: boolean,
>   useStatusColor?: boolean,
>   useProjectDuration?: boolean,
>   start?: string,
>   end?: string,
>   customFields?: Record<string, any>[]
> }[]
> ```

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   status?: string | null
> }[]
> ```

***

## Resources

### addTags

`resources.addTags`

Add tags to a resource

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.resources.addTags({
	resourceId: '5ba09b645ff58f149a2c2222',
	tags: ['5bb1e49065e0555544443333'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resourceId` | `string` | Yes | — |
| `tags` | `string[]` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `email` | `string \| null` | No | — |
| `role` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

> [accordion] tags full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[] | null
> ```

***

### create

`resources.create`

Create a new resource member

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.resources.create({ firstName: 'Jane', lastName: 'Doe', email: 'jane.doe@example.com' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `firstName` | `string` | Yes | — |
| `lastName` | `string` | Yes | — |
| `email` | `string` | No | — |
| `role` | `string` | No | — |
| `status` | `string` | No | — |
| `backgroundColor` | `string` | No | — |
| `metadata` | `string` | No | — |
| `customFields` | `Record<string, any>[]` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `email` | `string \| null` | No | — |
| `role` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

> [accordion] tags full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[] | null
> ```

***

### delete

`resources.delete`

Delete a specific resource by ID

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.resources.delete({ resourceId: '5ba09b645ff58f149a2c2222' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resourceId` | `string` | Yes | — |

**Output:** `string[]`

***

### deleteBulk

`resources.deleteBulk`

Delete multiple resources by their IDs

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.resources.deleteBulk({
	resourceIds: ['5ba09b645ff58f149a2c2222'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resourceIds` | `string[]` | Yes | — |

**Output:** `string[]`

***

### get

`resources.get`

Get resource details by resource ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.resources.get({ resourceId: '5ba09b645ff58f149a2c2222' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resourceId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `email` | `string \| null` | No | — |
| `role` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `backgroundColor` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customFields` | `any[] \| null` | No | — |

> [accordion] tags full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[] | null
> ```

***

### getTags

`resources.getTags`

List tags associated with a resource

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.resources.getTags({ resourceId: '5ba09b645ff58f149a2c2222' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resourceId` | `string` | Yes | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   tagId: string,
>   value: string,
>   _id?: string | null
> }[]
> ```

***

### list

`resources.list`

List all resources with pagination and sorting

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.resources.list({ limit: 20 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   firstName?: string | null,
>   lastName?: string | null,
>   email?: string | null,
>   role?: string | null,
>   status?: string | null,
>   backgroundColor?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   metadata?: string | null,
>   tags?: {
>     tagId: string,
>     value: string,
>     _id?: string | null
>   }[] | null,
>   customFields?: any[] | null
> }[]
> ```

***

### removeTag

`resources.removeTag`

Remove a tag from a resource

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.resources.removeTag({ resourceId: '5ba09b645ff58f149a2c2222', tagId: '5bbcaa1ae9fcfa1a87cd5f0e' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resourceId` | `string` | Yes | — |
| `tagId` | `string` | Yes | — |

**Output:** `undefined`

***

### search

`resources.search`

Search resources matching custom criteria

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.resources.search({
	query: { status: 'ACTIVE' },
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `query` | `Record<string, any>` | No | — |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   firstName?: string | null,
>   lastName?: string | null,
>   email?: string | null,
>   role?: string | null,
>   status?: string | null,
>   backgroundColor?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   metadata?: string | null,
>   tags?: {
>     tagId: string,
>     value: string,
>     _id?: string | null
>   }[] | null,
>   customFields?: any[] | null
> }[]
> ```

***

### update

`resources.update`

Bulk update resources with modified attributes

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.resources.update({
	resources: [{ _id: '5ba09b645ff58f149a2c2222', firstName: 'Janet' }],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resources` | `object[]` | Yes | — |

> [accordion] resources full type
>
> ```ts theme={null}
> {
>   _id: string,
>   firstName?: string,
>   lastName?: string,
>   email?: string,
>   role?: string,
>   status?: string,
>   backgroundColor?: string,
>   metadata?: string,
>   customFields?: Record<string, any>[]
> }[]
> ```

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   status?: string | null
> }[]
> ```

***

## Time Entries

### create

`timeEntries.create`

Log new time entry on a project for a resource

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.timeEntries.create({
	resource: '5ba09b645ff58f149a2c2222',
	project: '5ba09b645ff58f149a2cf521',
	date: '2026-11-20',
	minutes: 480,
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `date` | `string` | Yes | — |
| `minutes` | `number` | Yes | — |
| `note` | `string` | No | — |

Requires `resource`, `project`, `date` (YYYY-MM-DD), and `minutes`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `projectName` | `string \| null` | No | — |
| `projectType` | `string \| null` | No | — |
| `projectStatus` | `string \| null` | No | — |
| `date` | `string` | Yes | — |
| `minutes` | `number` | Yes | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `locked` | `boolean \| null` | No | — |
| `creator` | `string \| null` | No | — |
| `categoryTemplateId` | `string \| null` | No | — |
| `categoryName` | `string \| null` | No | — |

***

### delete

`timeEntries.delete`

Delete a timesheet entry by ID

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.timeEntries.delete({ timeEntryId: '5ae1d7a2d61e560c4916aaaa' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `timeEntryId` | `string` | Yes | — |

**Output:** `boolean`

***

### deleteBulk

`timeEntries.deleteBulk`

Delete multiple timesheet entries by their IDs

**Risk:** `destructive`

```ts theme={null}
await corsair.hubplanner.api.timeEntries.deleteBulk({
	ids: ['5ae1d7a2d61e560c4916aaaa'],
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `ids` | `string[]` | Yes | — |

**Output:** `undefined`

***

### get

`timeEntries.get`

Get timesheet entry details by ID

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.timeEntries.get({ timeEntryId: '5ae1d7a2d61e560c4916aaaa' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `timeEntryId` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `projectName` | `string \| null` | No | — |
| `projectType` | `string \| null` | No | — |
| `projectStatus` | `string \| null` | No | — |
| `date` | `string` | Yes | — |
| `minutes` | `number` | Yes | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `locked` | `boolean \| null` | No | — |
| `creator` | `string \| null` | No | — |
| `categoryTemplateId` | `string \| null` | No | — |
| `categoryName` | `string \| null` | No | — |

***

### list

`timeEntries.list`

List recorded timesheet entries with pagination and filters

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.timeEntries.list({ limit: 20 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |
| `project` | `string` | No | — |
| `start` | `string` | No | — |
| `end` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   resource: string,
>   project: string,
>   projectName?: string | null,
>   projectType?: string | null,
>   projectStatus?: string | null,
>   date: string,
>   minutes: number,
>   note?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   metadata?: string | null,
>   status?: string | null,
>   locked?: boolean | null,
>   creator?: string | null,
>   categoryTemplateId?: string | null,
>   categoryName?: string | null
> }[]
> ```

***

### search

`timeEntries.search`

Search time entries matching date ranges and resource/project filters

**Risk:** `read`

```ts theme={null}
await corsair.hubplanner.api.timeEntries.search({
	query: { resource: '5ba09b645ff58f149a2c2222' },
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `query` | `Record<string, any>` | No | — |
| `page` | `number` | No | — |
| `limit` | `number` | No | — |
| `sort` | `string` | No | — |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   _id: string,
>   resource: string,
>   project: string,
>   projectName?: string | null,
>   projectType?: string | null,
>   projectStatus?: string | null,
>   date: string,
>   minutes: number,
>   note?: string | null,
>   createdDate?: string | null,
>   updatedDate?: string | null,
>   metadata?: string | null,
>   status?: string | null,
>   locked?: boolean | null,
>   creator?: string | null,
>   categoryTemplateId?: string | null,
>   categoryName?: string | null
> }[]
> ```

***

### update

`timeEntries.update`

Update an existing timesheet entry

**Risk:** `write`

```ts theme={null}
await corsair.hubplanner.api.timeEntries.update({
	timeEntryId: '5ae1d7a2d61e560c4916aaaa',
	resource: '5ba09b645ff58f149a2c2222',
	project: '5ba09b645ff58f149a2cf521',
	date: '2026-11-20',
	minutes: 360,
});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `timeEntryId` | `string` | Yes | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `date` | `string` | Yes | — |
| `minutes` | `number` | Yes | — |
| `note` | `string` | No | — |
| `status` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `_id` | `string` | Yes | — |
| `resource` | `string` | Yes | — |
| `project` | `string` | Yes | — |
| `projectName` | `string \| null` | No | — |
| `projectType` | `string \| null` | No | — |
| `projectStatus` | `string \| null` | No | — |
| `date` | `string` | Yes | — |
| `minutes` | `number` | Yes | — |
| `note` | `string \| null` | No | — |
| `createdDate` | `string \| null` | No | — |
| `updatedDate` | `string \| null` | No | — |
| `metadata` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `locked` | `boolean \| null` | No | — |
| `creator` | `string \| null` | No | — |
| `categoryTemplateId` | `string \| null` | No | — |
| `categoryName` | `string \| null` | No | — |

***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.