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

# API

> API reference for Follow Up Boss: every `followupboss.api.*` operation with input and output types.

Every `followupboss.api.*` operation is listed below with parameter shapes and return types from the plugin 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).

## Account

### identity

`account.identity`

Get the account identity information behind the authenticated API key

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.account.identity({});
```

**Input:** *empty object*

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |

***

### me

`account.me`

Get the authenticated user's profile and role

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.account.me({});
```

**Input:** *empty object*

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `role` | `string \| null` | No | — |
| `email` | `string \| null` | No | — |
| `created` | `string \| null` | No | — |

***

## Action Plans

### list

`actionPlans.list`

List the account's action plans

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.actionPlans.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `sort` | `string` | No | — |
| `status` | `string` | No | `Active`, `Deleted`, or `Active,Deleted` for both. |
| `names` | `string[]` | No | Action plan names to match; sent as the repeated `names[]` array filter. |
| `ids` | `string` | No | Comma separated action plan IDs, e.g. `287564,67484`. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `actionPlans` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] actionPlans full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   updated?: string | null,
>   name?: string | null,
>   status?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

## Action Plans People

### create

`actionPlansPeople.create`

Enroll a person into an action plan

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.actionPlansPeople.create({ personId: 123, actionPlanId: 3 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | The person to apply the action plan to. |
| `actionPlanId` | `number` | Yes | The action plan to apply. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `actionPlanId` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |

***

### list

`actionPlansPeople.list`

List the people enrolled in action plans, filtered by person

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.actionPlansPeople.list({ personId: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `personId` | `number` | No | List action plans applied to this person. |
| `actionPlanId` | `number` | No | List the people on this action plan. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `actionPlansPeople` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] actionPlansPeople full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   updated?: string | null,
>   personId?: number | null,
>   actionPlanId?: number | null,
>   status?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`actionPlansPeople.update`

Update an action plan enrollment, such as finishing it

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.actionPlansPeople.update({ id: 41, status: 'Running' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The action-plan-person pairing ID. |
| `status` | `Running \| Paused` | Yes | The desired state of the applied action plan. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `actionPlanId` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |

***

## Appointment Outcomes

### create

`appointmentOutcomes.create`

Create an appointment outcome with an optional sort order

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.appointmentOutcomes.create({ name: 'Met at property', orderWeight: 1 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | No | Name of the appointment outcome. |
| `orderWeight` | `number` | No | Set this value to enforce a specific sort order. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |

***

### delete

`appointmentOutcomes.delete`

Delete an appointment outcome after reassigning its appointments to another outcome

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.appointmentOutcomes.delete({ id: 4, assignOutcomeId: 5 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | ID of the appointment outcome to delete. |
| `assignOutcomeId` | `number` | Yes | The outcome id that existing appointments are reassigned to. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`appointmentOutcomes.get`

Get one appointment outcome by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.appointmentOutcomes.get({ id: 4 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The appointment outcome ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |

***

### list

`appointmentOutcomes.list`

List the outcomes that appointments can be closed with

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.appointmentOutcomes.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `sort` | `string` | No | Sorts by `id`, `name` or `orderWeight`; prefix with `-` for descending. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `appointmentoutcomes` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] appointmentoutcomes full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   orderWeight?: number | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`appointmentOutcomes.update`

Update an appointment outcome's name or sort order

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.appointmentOutcomes.update({ id: 4, name: 'Met at property (completed)' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The appointment outcome ID. |
| `name` | `string` | No | — |
| `orderWeight` | `number` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |

***

## Appointments

### create

`appointments.create`

Create an appointment with invitees, optionally sending them invitations

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.appointments.create({ title: 'Property tour', start: '2026-05-21T17:00:00+00:00', end: '2026-05-21T17:30:00+00:00', invitees: [{ id: 123, type: 'person' }] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `title` | `string` | Yes | Title of the appointment. |
| `start` | `string` | Yes | Beginning date and time, ISO 8601 UTC (e.g. 2026-05-21T17:00:00+00:00). |
| `end` | `string` | Yes | Ending date and time, ISO 8601 UTC. |
| `description` | `string` | No | — |
| `invitees` | `object[]` | No | — |
| `allDay` | `boolean` | No | — |
| `location` | `string` | No | — |
| `typeId` | `number` | No | — |
| `createdById` | `number` | No | — |
| `sendInvitation` | `boolean` | No | Send an invitation email to the invitees. |
| `outcomeId` | `number` | No | Outcome ID from appointmentOutcomes.list. |

> [accordion] invitees full type
>
> ```ts theme={null}
> {
>   id: number,
>   type?: string
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `title` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `startDateTime` | `string \| null` | No | — |
| `endDateTime` | `string \| null` | No | — |
| `allDay` | `boolean \| number \| null` | No | — |
| `location` | `string \| null` | No | — |
| `typeId` | `number \| null` | No | — |
| `persons` | `Record<string, any>[] \| null` | No | — |
| `users` | `Record<string, any>[] \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### delete

`appointments.delete`

Permanently delete an appointment

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.appointments.delete({ id: 8 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The appointment ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `success` | `true` | Yes | — |
| `id` | `number` | Yes | — |

***

### get

`appointments.get`

Get one appointment by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.appointments.get({ id: 8 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The appointment ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `title` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `startDateTime` | `string \| null` | No | — |
| `endDateTime` | `string \| null` | No | — |
| `allDay` | `boolean \| number \| null` | No | — |
| `location` | `string \| null` | No | — |
| `typeId` | `number \| null` | No | — |
| `persons` | `Record<string, any>[] \| null` | No | — |
| `users` | `Record<string, any>[] \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### list

`appointments.list`

List appointments, filtered by person, user or date range, paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.appointments.list({ personId: 123, start: '2026-05-21T00:00:00+00:00', end: '2026-05-28T00:00:00+00:00' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `personId` | `number` | No | — |
| `userId` | `number` | No | — |
| `start` | `string` | No | — |
| `end` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `appointments` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] appointments full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   title?: string | null,
>   description?: string | null,
>   startDateTime?: string | null,
>   endDateTime?: string | null,
>   allDay?: boolean | number | null,
>   location?: string | null,
>   typeId?: number | null,
>   persons?: Record<string, any>[] | null,
>   users?: Record<string, any>[] | null,
>   createdById?: number | null,
>   created?: string | null,
>   updated?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`appointments.update`

Update an appointment's time, place, type or invitees

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.appointments.update({ id: 8, start: '2026-05-22T17:00:00+00:00', end: '2026-05-22T17:30:00+00:00' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The appointment ID. |
| `title` | `string` | No | — |
| `start` | `string` | No | — |
| `end` | `string` | No | — |
| `description` | `string` | No | — |
| `invitees` | `object[]` | No | — |
| `allDay` | `boolean` | No | — |
| `location` | `string` | No | — |
| `typeId` | `number` | No | — |
| `sendInvitation` | `boolean` | No | — |
| `outcomeId` | `number` | No | Outcome ID from appointmentOutcomes.list. |

> [accordion] invitees full type
>
> ```ts theme={null}
> {
>   id: number,
>   type?: string
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `title` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `startDateTime` | `string \| null` | No | — |
| `endDateTime` | `string \| null` | No | — |
| `allDay` | `boolean \| number \| null` | No | — |
| `location` | `string \| null` | No | — |
| `typeId` | `number \| null` | No | — |
| `persons` | `Record<string, any>[] \| null` | No | — |
| `users` | `Record<string, any>[] \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

## Appointment Types

### create

`appointmentTypes.create`

Create an appointment type with an optional sort order

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.appointmentTypes.create({ name: 'Buyer consultation', orderWeight: 1 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | No | — |
| `orderWeight` | `number` | No | Set this value to enforce a specific sort order. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |

***

### delete

`appointmentTypes.delete`

Delete an appointment type after reassigning its appointments to another type

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.appointmentTypes.delete({ id: 3, assignTypeId: 4 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The appointment type ID to delete. |
| `assignTypeId` | `number` | Yes | The appointment type that existing appointments are reassigned to. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`appointmentTypes.get`

Get one appointment type by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.appointmentTypes.get({ id: 3 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The appointment type ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |

***

### list

`appointmentTypes.list`

List the appointment types, sorted and paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.appointmentTypes.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `sort` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `appointmentTypes` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] appointmentTypes full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   orderWeight?: number | null,
>   created?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`appointmentTypes.update`

Update an appointment type's name or sort order

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.appointmentTypes.update({ id: 3, name: 'Buyer consult' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The appointment type ID. |
| `name` | `string` | No | — |
| `orderWeight` | `number` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |

***

## Automations

### get

`automations.get`

Get one automation by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.automations.get({ id: 10 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The automation ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |

***

### list

`automations.list`

List the account's automations

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.automations.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `status` | `string` | No | `Active`, `Disabled` or `Deleted`. |
| `enabledOnly` | `boolean` | No | — |
| `manualOnly` | `boolean` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `automations` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] automations full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   updated?: string | null,
>   name?: string | null,
>   status?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

## Automations People

### create

`automationsPeople.create`

Enroll a person into an automation

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.automationsPeople.create({ automationId: 10, personId: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `automationId` | `number` | No | ID of an existing Automation to trigger. |
| `personId` | `number` | No | ID of an existing Person to run the Automation for. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `createdBy` | `string \| null` | No | — |
| `updatedBy` | `string \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `automationId` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |
| `automationName` | `string \| null` | No | — |

***

### get

`automationsPeople.get`

Get one automation enrollment by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.automationsPeople.get({ id: 77 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The automation-person pairing ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `createdBy` | `string \| null` | No | — |
| `updatedBy` | `string \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `automationId` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |
| `automationName` | `string \| null` | No | — |

***

### list

`automationsPeople.list`

List the people enrolled in automations, filtered by automation

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.automationsPeople.list({ automationId: 10 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `personId` | `number` | No | — |
| `automationId` | `number` | No | — |
| `status` | `Initial \| Running \| Paused \| Completed` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `automationsPeople` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] automationsPeople full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   updated?: string | null,
>   createdById?: number | null,
>   updatedById?: number | null,
>   createdBy?: string | null,
>   updatedBy?: string | null,
>   personId?: number | null,
>   automationId?: number | null,
>   status?: string | null,
>   automationName?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`automationsPeople.update`

Update an automation enrollment, such as finishing it

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.automationsPeople.update({ id: 77, isFinished: true });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The automation-person pairing ID. |
| `status` | `Running \| Paused` | No | `Paused` to pause the automation or `Running` to unpause it. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `createdBy` | `string \| null` | No | — |
| `updatedBy` | `string \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `automationId` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |
| `automationName` | `string \| null` | No | — |

***

## Calls

### create

`calls.create`

Log a call on a person with its direction, duration, outcome and note

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.calls.create({ personId: 123, phone: '888-555-0123', isIncoming: false, outcome: 'Interested', duration: 320 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | The person associated with this call. |
| `phone` | `string` | Yes | The phone number this call was made to or from. |
| `isIncoming` | `boolean` | Yes | Whether the call was incoming. |
| `note` | `string` | No | — |
| `outcome` | `string` | No | Call outcome, e.g. `Interested`, `Not Interested`, `Neighborhood` or `Wrong Number`. |
| `duration` | `number` | No | Length of the call in seconds. |
| `toNumber` | `string` | No | — |
| `fromNumber` | `string` | No | — |
| `userId` | `number` | No | User who made or took the call; only admins can set it. |
| `recordingUrl` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `phone` | `string \| null` | No | — |
| `isIncoming` | `boolean \| number \| null` | No | — |
| `duration` | `number \| null` | No | — |
| `note` | `string \| null` | No | — |
| `outcome` | `string \| null` | No | — |
| `toNumber` | `string \| null` | No | — |
| `fromNumber` | `string \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### get

`calls.get`

Get one logged call by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.calls.get({ id: 89 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The call ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `phone` | `string \| null` | No | — |
| `isIncoming` | `boolean \| number \| null` | No | — |
| `duration` | `number \| null` | No | — |
| `note` | `string \| null` | No | — |
| `outcome` | `string \| null` | No | — |
| `toNumber` | `string \| null` | No | — |
| `fromNumber` | `string \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### list

`calls.list`

List logged calls, filtered by person or phone number, paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.calls.list({ personId: 123, limit: 50 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `personId` | `number` | No | — |
| `phone` | `string` | No | — |
| `toNumber` | `string` | No | — |
| `fromNumber` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `calls` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] calls full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   personId?: number | null,
>   phone?: string | null,
>   isIncoming?: boolean | number | null,
>   duration?: number | null,
>   note?: string | null,
>   outcome?: string | null,
>   toNumber?: string | null,
>   fromNumber?: string | null,
>   created?: string | null,
>   updated?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`calls.update`

Update a logged call's note, outcome or duration

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.calls.update({ id: 89, note: 'Left a voicemail' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The call ID. |
| `phone` | `string` | No | — |
| `isIncoming` | `boolean` | No | — |
| `note` | `string` | No | — |
| `outcome` | `string` | No | — |
| `duration` | `number` | No | — |
| `toNumber` | `string` | No | — |
| `fromNumber` | `string` | No | — |
| `userId` | `number` | No | User who made or took the call; only admins can set it. |
| `recordingUrl` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `phone` | `string \| null` | No | — |
| `isIncoming` | `boolean \| number \| null` | No | — |
| `duration` | `number \| null` | No | — |
| `note` | `string \| null` | No | — |
| `outcome` | `string \| null` | No | — |
| `toNumber` | `string \| null` | No | — |
| `fromNumber` | `string \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

## Custom Fields

### create

`customFields.create`

Create a custom field definition for people, with choices for dropdown types

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.customFields.create({ label: 'Preferred contact', type: 'text' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `label` | `string` | Yes | The user-friendly name of the custom field (e.g. `Anniversary`). |
| `type` | `text \| date \| number \| dropdown` | Yes | The type of custom field. |
| `choices` | `string[]` | No | Options for a custom field of type `dropdown`. |
| `isRecurring` | `boolean` | No | Whether a `date` field occurs every year, e.g. birthdays or anniversaries; only set and returned for `date` fields. |
| `hideIfEmpty` | `boolean` | No | Hide the field on a person while it is empty. |
| `orderWeight` | `number` | No | Weight used for custom sorting of the fields. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `label` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `isRecurring` | `boolean \| number \| null` | No | — |
| `hideIfEmpty` | `boolean \| number \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `choices` | `string[] \| null` | No | — |

***

### delete

`customFields.delete`

Permanently delete a person custom field definition

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.customFields.delete({ id: 12 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The custom field ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`customFields.get`

Get one person custom field definition by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.customFields.get({ id: 12 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The custom field ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `label` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `isRecurring` | `boolean \| number \| null` | No | — |
| `hideIfEmpty` | `boolean \| number \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `choices` | `string[] \| null` | No | — |

***

### list

`customFields.list`

List the custom fields available on people

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.customFields.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `label` | `string` | No | Find custom fields by their label. |
| `sort` | `string` | No | Sort by `id`, `name` or `orderWeight`, optionally prefixed with `-` for descending. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `customfields` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] customfields full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   label?: string | null,
>   name?: string | null,
>   type?: string | null,
>   isRecurring?: boolean | number | null,
>   hideIfEmpty?: boolean | number | null,
>   orderWeight?: number | null,
>   choices?: string[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`customFields.update`

Update a person custom field's label, choices or visibility

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.customFields.update({ id: 12, label: 'Preferred contact method' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The custom field ID. |
| `label` | `string` | No | — |
| `choices` | `string[]` | No | — |
| `isRecurring` | `boolean` | No | — |
| `hideIfEmpty` | `boolean` | No | — |
| `orderWeight` | `number` | No | — |
| `dropdownChoiceMap` | `number[]` | No | Maps previous dropdown choice positions to their new positions; choices missing from the keys are removed. When omitted, FUB tries to detect moves and renames on its own. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `label` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `isRecurring` | `boolean \| number \| null` | No | — |
| `hideIfEmpty` | `boolean \| number \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `choices` | `string[] \| null` | No | — |

***

## Deal Attachments

### create

`dealAttachments.create`

Attach an externally hosted file to a deal

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.dealAttachments.create({ dealId: 55, uri: 'https://files.example.com/offer.pdf', fileName: 'offer.pdf' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `dealId` | `number` | Yes | The id of the deal to attach the file to. |
| `uri` | `string` | Yes | URI of the externally hosted file. |
| `fileName` | `string` | Yes | Name of the file. |
| `fileSize` | `number` | No | Size of the file in bytes. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `dealId` | `number \| null` | No | — |
| `uri` | `string \| null` | No | — |
| `fileName` | `string \| null` | No | — |
| `fileSize` | `number \| null` | No | — |
| `mimeType` | `string \| null` | No | — |
| `thumbnailUri` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `createdAt` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `createdByName` | `string \| null` | No | — |

***

### delete

`dealAttachments.delete`

Permanently delete a file attachment from a deal

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.dealAttachments.delete({ id: 61 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | ID of the attachment to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`dealAttachments.get`

Get one file attachment of a deal by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.dealAttachments.get({ id: 61 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | ID of the attachment. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `dealId` | `number \| null` | No | — |
| `uri` | `string \| null` | No | — |
| `fileName` | `string \| null` | No | — |
| `fileSize` | `number \| null` | No | — |
| `mimeType` | `string \| null` | No | — |
| `thumbnailUri` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `createdAt` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `createdByName` | `string \| null` | No | — |

***

### update

`dealAttachments.update`

Update the file URI, name or size of a deal attachment

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.dealAttachments.update({ id: 61, dealId: 55, uri: 'https://files.example.com/offer-v2.pdf', fileName: 'offer-v2.pdf' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `dealId` | `number` | Yes | The id of the deal to attach the file to. |
| `uri` | `string` | Yes | URI of the externally hosted file. |
| `fileName` | `string` | Yes | Name of the file. |
| `fileSize` | `number` | No | Size of the file in bytes. |
| `id` | `number` | Yes | ID of the attachment. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `dealId` | `number \| null` | No | — |
| `uri` | `string \| null` | No | — |
| `fileName` | `string \| null` | No | — |
| `fileSize` | `number \| null` | No | — |
| `mimeType` | `string \| null` | No | — |
| `thumbnailUri` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `createdAt` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `createdByName` | `string \| null` | No | — |

***

## Deal Custom Fields

### create

`dealCustomFields.create`

Create a custom field definition for deals, with choices for dropdown types

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.dealCustomFields.create({ label: 'Closing date', type: 'date' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `label` | `string` | Yes | The user-friendly name of the custom field (e.g. "Anniversary"). |
| `type` | `text \| date \| number \| dropdown` | Yes | The type of deals custom field. |
| `choices` | `string[]` | No | Options for a deals custom field of type `dropdown`. |
| `isRecurring` | `boolean` | No | Whether a date field occurs every year (e.g. birthdays). |
| `hideIfEmpty` | `boolean` | No | Sets whether the field is hidden if it is empty. |
| `orderWeight` | `number` | No | A weighted integer for custom sorting. |
| `readOnly` | `boolean` | No | Determines whether the deals custom field is read only. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `label` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `choices` | `string[] \| null` | No | — |
| `isRecurring` | `boolean \| number \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `hideIfEmpty` | `boolean \| number \| null` | No | — |
| `readOnly` | `boolean \| number \| null` | No | — |

***

### delete

`dealCustomFields.delete`

Permanently delete a deal custom field definition

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.dealCustomFields.delete({ id: 9 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The deals custom field ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`dealCustomFields.get`

Get one deal custom field definition by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.dealCustomFields.get({ id: 9 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The deals custom field ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `label` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `choices` | `string[] \| null` | No | — |
| `isRecurring` | `boolean \| number \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `hideIfEmpty` | `boolean \| number \| null` | No | — |
| `readOnly` | `boolean \| number \| null` | No | — |

***

### list

`dealCustomFields.list`

List the custom fields available on deals

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.dealCustomFields.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `label` | `string` | No | Find a custom field by label. |
| `sort` | `string` | No | Sorts by `id`, `name` or `orderWeight`; prefix with `-` for descending. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `dealCustomfields` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] dealCustomfields full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   label?: string | null,
>   name?: string | null,
>   type?: string | null,
>   choices?: string[] | null,
>   isRecurring?: boolean | number | null,
>   orderWeight?: number | null,
>   hideIfEmpty?: boolean | number | null,
>   readOnly?: boolean | number | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`dealCustomFields.update`

Update a deal custom field's label, choices or visibility

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.dealCustomFields.update({ id: 9, label: 'Expected closing date', type: 'date' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The deals custom field ID. |
| `label` | `string` | Yes | The user-friendly name of the custom field (e.g. "Anniversary"). |
| `type` | `text \| date \| number \| dropdown` | Yes | The type of deals custom field. |
| `choices` | `string[]` | No | — |
| `isRecurring` | `boolean` | No | — |
| `hideIfEmpty` | `boolean` | No | — |
| `orderWeight` | `number` | No | — |
| `dropdownChoiceMap` | `number[]` | No | — |
| `readOnly` | `boolean` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `label` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `choices` | `string[] \| null` | No | — |
| `isRecurring` | `boolean \| number \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `hideIfEmpty` | `boolean \| number \| null` | No | — |
| `readOnly` | `boolean \| number \| null` | No | — |

***

## Deals

### create

`deals.create`

Create a deal on a pipeline stage with a value and description

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.deals.create({ name: '812 Oak Street', stageId: 7, price: 520000, description: 'Buyer tour scheduled' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | Name of the deal. |
| `stageId` | `number` | Yes | The stage that this deal should be assigned to. |
| `description` | `string` | No | — |
| `customFields` | `Record<string, any>` | No | Deal custom field values keyed by their `custom…` name (e.g. `{ customClosingDate: "2026-12-01" }`); sent as top-level fields. |
| `peopleIds` | `number[]` | No | Person ids that should be part of this deal. |
| `userIds` | `number[]` | No | User ids that should be part of this deal. |
| `price` | `number` | No | — |
| `projectedCloseDate` | `string` | No | — |
| `orderWeight` | `number` | No | Set this value to enforce a specific sort order. |
| `commissionValue` | `number` | No | Commission value to assign to this deal. |
| `agentCommission` | `number` | No | Commission split for the agent split. |
| `teamCommission` | `number` | No | Commission split for the team split. |
| `earnestMoneyDueDate` | `string` | No | — |
| `mutualAcceptanceDate` | `string` | No | — |
| `dueDiligenceDate` | `string` | No | — |
| `finalWalkThroughDate` | `string` | No | — |
| `possessionDate` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `pipelineId` | `number \| null` | No | — |
| `stageId` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `type` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |
| `price` | `number \| null` | No | — |
| `createdAt` | `string \| null` | No | — |
| `enteredStageAt` | `string \| null` | No | — |
| `projectedCloseDate` | `string \| null` | No | — |
| `earnestMoneyDueDate` | `string \| null` | No | — |
| `mutualAcceptanceDate` | `string \| null` | No | — |
| `dueDiligenceDate` | `string \| null` | No | — |
| `finalWalkThroughDate` | `string \| null` | No | — |
| `possessionDate` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `commissionValue` | `number \| null` | No | — |
| `agentCommission` | `number \| null` | No | — |
| `teamCommission` | `number \| null` | No | — |
| `peopleIds` | `number[] \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |
| `people` | `object[] \| null` | No | — |
| `users` | `object[] \| null` | No | — |

> [accordion] people full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   avatar?: string | null
> }[] | null
> ```

> [accordion] users full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null
> }[] | null
> ```

***

### delete

`deals.delete`

Permanently delete a deal

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.deals.delete({ id: 55 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The deal ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`deals.get`

Get one deal by ID with its stage, value and associated people

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.deals.get({ id: 55 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The deal ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `pipelineId` | `number \| null` | No | — |
| `stageId` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `type` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |
| `price` | `number \| null` | No | — |
| `createdAt` | `string \| null` | No | — |
| `enteredStageAt` | `string \| null` | No | — |
| `projectedCloseDate` | `string \| null` | No | — |
| `earnestMoneyDueDate` | `string \| null` | No | — |
| `mutualAcceptanceDate` | `string \| null` | No | — |
| `dueDiligenceDate` | `string \| null` | No | — |
| `finalWalkThroughDate` | `string \| null` | No | — |
| `possessionDate` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `commissionValue` | `number \| null` | No | — |
| `agentCommission` | `number \| null` | No | — |
| `teamCommission` | `number \| null` | No | — |
| `peopleIds` | `number[] \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |
| `people` | `object[] \| null` | No | — |
| `users` | `object[] \| null` | No | — |

> [accordion] people full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   avatar?: string | null
> }[] | null
> ```

> [accordion] users full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null
> }[] | null
> ```

***

### list

`deals.list`

List deals with their stage, price and people, sorted and paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.deals.list({ limit: 50 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `pipelineId` | `number` | No | — |
| `userId` | `number` | No | — |
| `personId` | `number` | No | — |
| `includeDeleted` | `number` | No | Set to `1` to include deals with a status of `Deleted`. |
| `includeArchived` | `number` | No | Set to `1` to include deals with a status of `Archived`. |
| `status` | `Active \| Archived \| Deleted` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `deals` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] deals full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   pipelineId?: number | null,
>   stageId?: number | null,
>   name?: string | null,
>   description?: string | null,
>   type?: number | null,
>   status?: string | null,
>   price?: number | null,
>   createdAt?: string | null,
>   enteredStageAt?: string | null,
>   projectedCloseDate?: string | null,
>   earnestMoneyDueDate?: string | null,
>   mutualAcceptanceDate?: string | null,
>   dueDiligenceDate?: string | null,
>   finalWalkThroughDate?: string | null,
>   possessionDate?: string | null,
>   orderWeight?: number | null,
>   commissionValue?: number | null,
>   agentCommission?: number | null,
>   teamCommission?: number | null,
>   peopleIds?: number[] | null,
>   userIds?: number[] | null,
>   people?: {
>     id?: number | null,
>     name?: string | null,
>     avatar?: string | null
>   }[] | null,
>   users?: {
>     id?: number | null,
>     name?: string | null
>   }[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`deals.update`

Update a deal's stage, value, commission or associated people

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.deals.update({ id: 55, price: 535000 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The deal ID. |
| `name` | `string` | No | — |
| `stageId` | `number` | No | — |
| `description` | `string` | No | — |
| `customFields` | `Record<string, any>` | No | Deal custom field values keyed by their `custom…` name (e.g. `{ customClosingDate: "2026-12-01" }`); sent as top-level fields. |
| `peopleIds` | `number[]` | No | — |
| `userIds` | `number[]` | No | — |
| `price` | `number` | No | — |
| `projectedCloseDate` | `string` | No | — |
| `commissionValue` | `number` | No | — |
| `agentCommision` | `number` | No | Commission value for an agent split; spelled `agentCommision` in the PUT contract. |
| `teamComission` | `number` | No | Commission value for a team split; spelled `teamComission` in the PUT contract. |
| `earnestMoneyDueDate` | `string` | No | — |
| `mutualAcceptanceDate` | `string` | No | — |
| `dueDiligenceDate` | `string` | No | — |
| `finalWalkThroughDate` | `string` | No | — |
| `possessionDate` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `pipelineId` | `number \| null` | No | — |
| `stageId` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `type` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |
| `price` | `number \| null` | No | — |
| `createdAt` | `string \| null` | No | — |
| `enteredStageAt` | `string \| null` | No | — |
| `projectedCloseDate` | `string \| null` | No | — |
| `earnestMoneyDueDate` | `string \| null` | No | — |
| `mutualAcceptanceDate` | `string \| null` | No | — |
| `dueDiligenceDate` | `string \| null` | No | — |
| `finalWalkThroughDate` | `string \| null` | No | — |
| `possessionDate` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `commissionValue` | `number \| null` | No | — |
| `agentCommission` | `number \| null` | No | — |
| `teamCommission` | `number \| null` | No | — |
| `peopleIds` | `number[] \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |
| `people` | `object[] \| null` | No | — |
| `users` | `object[] \| null` | No | — |

> [accordion] people full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   avatar?: string | null
> }[] | null
> ```

> [accordion] users full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null
> }[] | null
> ```

***

## Em Campaigns

### create

`emCampaigns.create`

Create an email marketing campaign with subject and HTML body

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.emCampaigns.create({ name: 'Spring newsletter', subject: 'New listings this spring', bodyHtml: '<p>Hi {{first_name}}</p>', origin: 'custom' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `origin` | `string` | No | Name of the email marketing system where this campaign originated from. |
| `originId` | `string` | No | Internal ID of the new campaign or email in the origin system. |
| `name` | `string` | No | Name of the email campaign or template. |
| `subject` | `string` | No | Email subject line. |
| `bodyHtml` | `string` | No | Email body in HTML. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `origin` | `string \| null` | No | — |
| `originId` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `bodyHtml` | `string \| null` | No | — |

***

### list

`emCampaigns.list`

List the email marketing campaigns, filtered by origin

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.emCampaigns.list({ limit: 25 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `origin` | `string` | No | Search for campaigns from a specific origin. |
| `originId` | `string` | No | Search for campaigns with a specific ID from the originating system. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `emCampaigns` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] emCampaigns full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   origin?: string | null,
>   originId?: string | null,
>   name?: string | null,
>   subject?: string | null,
>   bodyHtml?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`emCampaigns.update`

Update an email marketing campaign's name, subject or body

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.emCampaigns.update({ id: 8, subject: 'New listings this April' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The Follow Up Boss ID of the email campaign. |
| `name` | `string` | No | Name of the email campaign or template. |
| `subject` | `string` | No | Email subject line. |
| `bodyHtml` | `string` | No | Email body in HTML. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `origin` | `string \| null` | No | — |
| `originId` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `bodyHtml` | `string \| null` | No | — |

***

## Em Events

### create

`emEvents.create`

Record email marketing events against subscriber email addresses

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.emEvents.create({ emEvents: [{ type: 'open', email: 'jordan@acme-logistics.com' }] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `emEvents` | `object[]` | No | The email marketing events to notify FUB about. |

> [accordion] emEvents full type
>
> ```ts theme={null}
> {
>   type?: string,
>   occurred?: string,
>   recipient?: string,
>   personId?: number,
>   campaignId?: string | number,
>   userId?: number,
>   url?: string
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `emEventIds` | `number[] \| null` | No | — |
| `recipientsNotFound` | `string[] \| null` | No | — |

***

### list

`emEvents.list`

List email marketing events such as sends, opens and clicks

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.emEvents.list({ limit: 50 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `type` | `string` | No | Event type: `delivered`, `open`, `click`, `bounced`, `soft-bounce`, `hard-bounce`, `unsubscribe`, `spamreport` or `dropped`. |
| `personId` | `number` | No | — |
| `updatedAfter` | `string` | No | Only events created or updated after this time, e.g. 2017-01-01T00:00:00Z. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `emEvents` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] emEvents full type
>
> ```ts theme={null}
> {
>   count?: number | null,
>   type?: string | null,
>   personId?: number | null,
>   campaignId?: number | null,
>   campaignName?: string | null,
>   created?: string | null,
>   updated?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

## Events

### create

`events.create`

Push a lead event into Follow Up Boss's routing, which creates or matches the person and runs their action plans

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.events.create({ source: 'Zillow', type: 'Registration', person: { firstName: 'Jordan', lastName: 'Rivera', emails: [{ value: 'jordan@acme-logistics.com' }] } });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `system` | `string` | No | The name of the system providing the lead. |
| `source` | `string` | No | The name of the lead source. |
| `type` | `string` | No | Event type, e.g. `Registration`, `Inquiry`, `Sellers Inquiry`, `Property Inquiry`, `Viewed Page` or `General`. |
| `message` | `string` | No | — |
| `description` | `string` | No | — |
| `person` | `object` | No | — |
| `property` | `object` | No | — |
| `propertySearch` | `object` | No | — |
| `campaign` | `object` | No | — |
| `occurredAt` | `string` | No | When the event happened. Events more than a day old count as historical and do not trigger automations. |
| `pageTitle` | `string` | No | Viewed Page events: title of the page. |
| `pageUrl` | `string` | No | Viewed Page events: URL of the page. |
| `pageReferrer` | `string` | No | Viewed Page events: referring URL; send pageUrl with it. |
| `pageDuration` | `number` | No | Viewed Page events: seconds spent on the page. |

> [accordion] person full type
>
> ```ts theme={null}
> {
>   id?: number,
>   firstName?: string,
>   lastName?: string,
>   stage?: string,
>   source?: string,
>   emails?: {
>     value?: string | null,
>     type?: string | null
>   }[],
>   phones?: {
>     value?: string | null,
>     type?: string | null
>   }[],
>   tags?: string[]
> }
> ```

> [accordion] property full type
>
> ```ts theme={null}
> {
>   street?: string,
>   city?: string,
>   state?: string,
>   code?: string,
>   mlsNumber?: string,
>   price?: number,
>   forRent?: boolean,
>   url?: string,
>   type?: string,
>   bedrooms?: string,
>   bathrooms?: string,
>   area?: string,
>   lot?: string
> }
> ```

> [accordion] propertySearch full type
>
> ```ts theme={null}
> {
>   type?: string,
>   neighborhood?: string,
>   city?: string,
>   state?: string,
>   code?: string | string[],
>   minPrice?: number,
>   maxPrice?: number,
>   minBedrooms?: number,
>   maxBedrooms?: number,
>   minBathrooms?: number,
>   maxBathrooms?: number
> }
> ```

> [accordion] campaign full type
>
> ```ts theme={null}
> {
>   source: string,
>   medium?: string,
>   term?: string,
>   content?: string,
>   campaign?: string
> }
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `event` | `object \| null` | No | — |

> [accordion] event full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   type?: string | null,
>   created?: string | null,
>   system?: string | null,
>   source?: string | null,
>   sourceType?: string | null,
>   sourceUrl?: string | null,
>   description?: string | null,
>   message?: string | null,
>   personId?: number | null,
>   person?: Record<string, any> | null,
>   property?: Record<string, any> | null
> } | null
> ```

***

### get

`events.get`

Get one lead event by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.events.get({ id: 1001 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The event ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `type` | `string \| null` | No | — |
| `created` | `string \| null` | No | — |
| `system` | `string \| null` | No | — |
| `source` | `string \| null` | No | — |
| `sourceType` | `string \| null` | No | — |
| `sourceUrl` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `message` | `string \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `person` | `Record<string, any> \| null` | No | — |
| `property` | `Record<string, any> \| null` | No | — |

***

### list

`events.list`

List lead events, filtered by person, type or property, paged with the keyset cursor FUB enforces on deep pages

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.events.list({ personId: 123, limit: 50 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `personId` | `number` | No | — |
| `type` | `string[]` | No | Event types to include, e.g. `Registration`, `Inquiry`, `Viewed Page`; sent comma separated. |
| `hasProperty` | `boolean` | No | — |
| `propertyAddress` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `events` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] events full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   type?: string | null,
>   created?: string | null,
>   system?: string | null,
>   source?: string | null,
>   sourceType?: string | null,
>   sourceUrl?: string | null,
>   description?: string | null,
>   message?: string | null,
>   personId?: number | null,
>   person?: Record<string, any> | null,
>   property?: Record<string, any> | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

## Groups

### create

`groups.create`

Create a routing group of users with a distribution strategy

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.groups.create({ name: 'Round robin intake', users: [1, 4, 6], distribution: 'round-robin' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | The name of the group. |
| `distribution` | `first-to-claim \| round-robin` | No | Distribution model; Lender groups cannot be set to `first-to-claim`. |
| `users` | `number[]` | Yes | User IDs that will be members of this group. |
| `type` | `Agent \| Lender` | No | — |
| `claimWindow` | `number` | No | Seconds a first-to-claim lead waits before reassignment; default 1800, minimum 60, maximum 1800. |
| `defaultGroupId` | `number` | No | Group that receives unclaimed first-to-claim leads. |
| `defaultPondId` | `number` | No | Pond that receives unclaimed first-to-claim leads. |
| `defaultUserId` | `number` | No | User who receives unclaimed first-to-claim leads. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `distribution` | `string \| null` | No | — |
| `claimWindow` | `number \| null` | No | — |
| `nextRoundRobinUser` | `number \| null` | No | — |
| `isPrimary` | `boolean \| number \| null` | No | — |
| `defaultUserId` | `number \| null` | No | — |
| `defaultPondId` | `number \| null` | No | — |
| `defaultGroupId` | `number \| null` | No | — |
| `users` | `object[] \| null` | No | — |

> [accordion] users full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   firstName?: string | null,
>   lastName?: string | null,
>   role?: string | null,
>   pauseLeadDistribution?: boolean | number | null
> }[] | null
> ```

***

### delete

`groups.delete`

Permanently delete a routing group

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.groups.delete({ id: 2 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The group ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`groups.get`

Get one routing group by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.groups.get({ id: 2 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The group ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `distribution` | `string \| null` | No | — |
| `claimWindow` | `number \| null` | No | — |
| `nextRoundRobinUser` | `number \| null` | No | — |
| `isPrimary` | `boolean \| number \| null` | No | — |
| `defaultUserId` | `number \| null` | No | — |
| `defaultPondId` | `number \| null` | No | — |
| `defaultGroupId` | `number \| null` | No | — |
| `users` | `object[] \| null` | No | — |

> [accordion] users full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   firstName?: string | null,
>   lastName?: string | null,
>   role?: string | null,
>   pauseLeadDistribution?: boolean | number | null
> }[] | null
> ```

***

### list

`groups.list`

List the routing groups with their distribution strategy

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.groups.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `type` | `Agent \| Lender` | No | `Agent` groups allow admins and agents and `Lender` groups allow lender role users. |
| `sort` | `string` | No | Sort by `id` or `name`, optionally prefixed with `-` for descending. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `groups` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] groups full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   type?: string | null,
>   distribution?: string | null,
>   claimWindow?: number | null,
>   nextRoundRobinUser?: number | null,
>   isPrimary?: boolean | number | null,
>   defaultUserId?: number | null,
>   defaultPondId?: number | null,
>   defaultGroupId?: number | null,
>   users?: {
>     id?: number | null,
>     name?: string | null,
>     firstName?: string | null,
>     lastName?: string | null,
>     role?: string | null,
>     pauseLeadDistribution?: boolean | number | null
>   }[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### roundRobin

`groups.roundRobin`

Read the round-robin rotation state of the routing groups

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.groups.roundRobin({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `type` | `Agent \| Lender` | No | `Agent` groups allow admins and agents and `Lender` groups allow lender role users. |
| `sort` | `string` | No | Sort by `id` or `name`, optionally prefixed with `-` for descending. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `groups` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] groups full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   type?: string | null,
>   distribution?: string | null,
>   claimWindow?: number | null,
>   nextRoundRobinUser?: number | null,
>   isPrimary?: boolean | number | null,
>   defaultUserId?: number | null,
>   defaultPondId?: number | null,
>   defaultGroupId?: number | null,
>   users?: {
>     id?: number | null,
>     name?: string | null,
>     firstName?: string | null,
>     lastName?: string | null,
>     role?: string | null,
>     pauseLeadDistribution?: boolean | number | null
>   }[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`groups.update`

Update a routing group's name, members or distribution

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.groups.update({ id: 2, name: 'Intake group', users: [1, 4, 6] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The group ID. |
| `name` | `string` | Yes | The name of the group. |
| `distribution` | `first-to-claim \| round-robin` | No | Distribution model; Lender groups cannot be set to `first-to-claim`. |
| `users` | `number[]` | Yes | User IDs that will be members of this group. |
| `type` | `Agent \| Lender` | No | — |
| `claimWindow` | `number` | No | Seconds a first-to-claim lead waits before reassignment; default 1800, minimum 60, maximum 1800. |
| `defaultGroupId` | `number` | No | Group that receives unclaimed first-to-claim leads. |
| `defaultPondId` | `number` | No | Pond that receives unclaimed first-to-claim leads. |
| `defaultUserId` | `number` | No | User who receives unclaimed first-to-claim leads. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `distribution` | `string \| null` | No | — |
| `claimWindow` | `number \| null` | No | — |
| `nextRoundRobinUser` | `number \| null` | No | — |
| `isPrimary` | `boolean \| number \| null` | No | — |
| `defaultUserId` | `number \| null` | No | — |
| `defaultPondId` | `number \| null` | No | — |
| `defaultGroupId` | `number \| null` | No | — |
| `users` | `object[] \| null` | No | — |

> [accordion] users full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   firstName?: string | null,
>   lastName?: string | null,
>   role?: string | null,
>   pauseLeadDistribution?: boolean | number | null
> }[] | null
> ```

***

## Inbox Apps

### addMessage

`inboxApps.addMessage`

Deliver a message from your system into an inbox app conversation

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.inboxApps.addMessage({ inboxAppId: 'app_123', externalConversationId: 'conv_88', externalMessageId: 'msg_910', message: 'Offer accepted!', isIncoming: false, sender: { name: 'Jordan Rivera' } });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID adding the message. |
| `externalConversationId` | `string` | Yes | A unique identifier that references this conversation. |
| `externalMessageId` | `string` | Yes | A unique identifier that references this message. |
| `replyToExternalMessageId` | `string` | No | External message ID of the message this message replies to. |
| `sentAt` | `string` | No | Delivery timestamp in ISO 8601 UTC; defaults to the current time. |
| `subject` | `string` | No | Sets or updates the subject of the conversation. |
| `message` | `string` | Yes | A plaintext message body. |
| `isIncoming` | `boolean` | Yes | Whether the message was incoming to your system. |
| `sender` | `object` | Yes | Who sent the message: a FUB User, a FUB Person or an unrelated entity. |
| `isAutomation` | `boolean` | No | Whether the sender is an automated system. |
| `person` | `object` | No | The person associated with the conversation; required on the first message. |
| `owner` | `object` | No | The owner of the conversation; required on the first message. |
| `deliveryStatus` | `Sent \| Delivered \| Read \| Not Delivered` | No | — |
| `deliveryStatusErrorMessage` | `string` | No | User-facing error message for Not Delivered statuses. |
| `attachments` | `object[]` | No | File attachments with a URL FUB can download for 20 minutes. |
| `richObjects` | `string[]` | No | List of Rich Object URLs. |

> [accordion] sender full type
>
> ```ts theme={null}
> {
>   userId?: number,
>   personId?: number,
>   relationshipId?: number,
>   participantId?: number,
>   name?: string,
>   email?: string,
>   phone?: string
> }
> ```

> [accordion] person full type
>
> ```ts theme={null}
> {
>   id?: number,
>   name?: string,
>   email?: string,
>   phone?: string
> }
> ```

> [accordion] owner full type
>
> ```ts theme={null}
> {
>   userId?: number,
>   inboxId?: string
> }
> ```

> [accordion] attachments full type
>
> ```ts theme={null}
> {
>   filename?: string | null,
>   url?: string | null
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `sentAt` | `string \| null` | No | — |
| `deliveryStatus` | `string \| null` | No | — |
| `deliveryStatusErrorMessage` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `isIncoming` | `boolean \| number \| null` | No | — |
| `isSystem` | `boolean \| number \| null` | No | — |
| `systemType` | `string \| null` | No | — |
| `message` | `string \| null` | No | — |
| `userId` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `sender` | `object \| null` | No | — |
| `attachments` | `object[] \| null` | No | — |
| `conversationDeepLinkUrl` | `string \| null` | No | — |

> [accordion] sender full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   personId?: number | null,
>   relationshipId?: number | null,
>   participantId?: number | null,
>   name?: string | null,
>   email?: string | null,
>   phone?: string | null,
>   avatar?: string | null
> } | null
> ```

> [accordion] attachments full type
>
> ```ts theme={null}
> {
>   filename?: string | null,
>   url?: string | null
> }[] | null
> ```

***

### addNote

`inboxApps.addNote`

Add an internal note to an inbox app conversation

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.inboxApps.addNote({ inboxAppId: 'app_123', externalConversationId: 'conv_88', body: 'Client prefers evening calls', user: { name: 'Alex' } });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID adding the note. |
| `externalConversationId` | `string` | Yes | The unique identifier that references the conversation. |
| `body` | `string` | Yes | The plaintext body of the note. |
| `user` | `object` | Yes | The user adding the note. |

> [accordion] user full type
>
> ```ts theme={null}
> {
>   id?: string,
>   name?: string,
>   email?: string
> }
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `createdBy` | `string \| null` | No | — |
| `updatedBy` | `string \| null` | No | — |
| `conversationId` | `number \| null` | No | — |
| `body` | `string \| null` | No | — |
| `isHtml` | `boolean \| number \| null` | No | — |
| `type` | `string \| null` | No | — |
| `conversationDeepLinkUrl` | `string \| null` | No | — |

***

### addSystemConfirmationMessage

`inboxApps.addSystemConfirmationMessage`

Add a system confirmation message to an inbox app conversation

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.inboxApps.addSystemConfirmationMessage({ inboxAppId: 'app_123', externalConversationId: 'conv_88', externalMessageId: 'sys_1', type: 'success', message: 'Conversation synced' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID adding the message. |
| `externalConversationId` | `string` | Yes | A unique identifier that references this conversation. |
| `externalMessageId` | `string` | Yes | A unique identifier that references this message. |
| `message` | `string` | Yes | A plaintext message body. |
| `type` | `success \| info \| error` | No | The system confirmation message type. |
| `person` | `object` | No | The person associated with the conversation; required on the first message. |
| `owner` | `object` | No | The owner of the conversation; required on the first message. |

> [accordion] person full type
>
> ```ts theme={null}
> {
>   id?: number,
>   name?: string,
>   email?: string,
>   phone?: string
> }
> ```

> [accordion] owner full type
>
> ```ts theme={null}
> {
>   userId?: number,
>   inboxId?: string
> }
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `sentAt` | `string \| null` | No | — |
| `deliveryStatus` | `string \| null` | No | — |
| `deliveryStatusErrorMessage` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `isIncoming` | `boolean \| number \| null` | No | — |
| `isSystem` | `boolean \| number \| null` | No | — |
| `systemType` | `string \| null` | No | — |
| `message` | `string \| null` | No | — |
| `userId` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `sender` | `object \| null` | No | — |
| `attachments` | `object[] \| null` | No | — |
| `conversationDeepLinkUrl` | `string \| null` | No | — |

> [accordion] sender full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   personId?: number | null,
>   relationshipId?: number | null,
>   participantId?: number | null,
>   name?: string | null,
>   email?: string | null,
>   phone?: string | null,
>   avatar?: string | null
> } | null
> ```

> [accordion] attachments full type
>
> ```ts theme={null}
> {
>   filename?: string | null,
>   url?: string | null
> }[] | null
> ```

***

### createParticipant

`inboxApps.createParticipant`

Add a participant to an inbox app conversation

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.inboxApps.createParticipant({ inboxAppId: 'app_123', extConversationId: 'conv_88', body: { name: 'Sam Rivera' } });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID sending the message. |
| `extConversationId` | `string` | Yes | The unique identifier that references the conversation being updated. |
| `body` | `object` | Yes | — |

> [accordion] body full type
>
> ```ts theme={null}
> {
>   personId?: number,
>   userId?: number,
>   relationshipId?: number,
>   name?: string,
>   email?: string,
>   phone?: string,
>   isAutomation?: boolean
> }
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `status` | `string \| null` | No | — |
| `userId` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `email` | `string \| null` | No | — |
| `phone` | `string \| null` | No | — |
| `isAutomation` | `boolean \| number \| null` | No | — |

***

### deactivate

`inboxApps.deactivate`

Deactivate an inbox app so it stops receiving conversations

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.inboxApps.deactivate({ inboxAppId: 'app_123' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID to deactivate. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `success` | `true` | Yes | — |
| `inboxAppId` | `string` | Yes | — |

***

### deleteParticipant

`inboxApps.deleteParticipant`

Remove a participant from an inbox app conversation

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.inboxApps.deleteParticipant({ inboxAppId: 'app_123', extConversationId: 'conv_88', participantId: 'part_5' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID sending the message. |
| `extConversationId` | `string` | Yes | The unique identifier that references the conversation being updated. |
| `participantId` | `string` | Yes | The participant's ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `success` | `true` | Yes | — |
| `participantId` | `string` | Yes | — |

***

### getParticipants

`inboxApps.getParticipants`

List the participants of an inbox app conversation

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.inboxApps.getParticipants({ inboxAppId: 'app_123', extConversationId: 'conv_88' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID sending the message. |
| `extConversationId` | `string` | Yes | The unique identifier that references the conversation being updated. |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   status?: string | null,
>   userId?: number | null,
>   personId?: number | null,
>   name?: string | null,
>   email?: string | null,
>   phone?: string | null,
>   isAutomation?: boolean | number | null
> }[]
> ```

***

### install

`inboxApps.install`

Install a published inbox app for a user with a subscription URL

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.inboxApps.install({ publishedInboxAppId: 1, userId: 1, subscriptionUrl: 'https://hooks.example.com/inbox' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `publishedInboxAppId` | `number` | Yes | Your Published Inbox App ID. |
| `userId` | `number` | Yes | The User ID to scope the install to, or 0 for account-wide scope. |
| `subscriptionUrl` | `string` | Yes | The webhook URL you will receive Inbox App replies at. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `status` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `publishedInboxAppId` | `number \| null` | No | — |
| `userId` | `number \| null` | No | — |
| `canReply` | `boolean \| number \| null` | No | — |

***

### installedApp

`inboxApps.installedApp`

Read the installation details of a published inbox app

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.inboxApps.installedApp({ publishedInboxAppId: 'pub_app_1' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `publishedInboxAppId` | `string` | Yes | Your Published Inbox App ID, to display installations of. |

**Output**

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

> [accordion] inboxApps full type
>
> ```ts theme={null}
> {
>   inboxAppId?: number | null,
>   userId?: number | null,
>   created?: string | null
> }[]
> ```

***

### updateConversation

`inboxApps.updateConversation`

Update an inbox app conversation's subject or state

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.inboxApps.updateConversation({ inboxAppId: 'app_123', extConversationId: 'conv_88', name: 'Offer negotiation' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID sending the message. |
| `extConversationId` | `string` | Yes | The unique identifier that references the conversation being updated. |
| `subject` | `string` | No | Sets or updates the subject. |
| `archived` | `boolean` | No | Archives or unarchives. |
| `permanentlyArchived` | `boolean` | No | Disables replies and notes; cannot be undone. |
| `person` | `object` | No | Updates the person; only changeable before a Person ID is set. |
| `assignedUserId` | `number` | No | The User ID to reassign to; 0 reverts to the owner. |
| `assignedInboxId` | `number` | No | The Team Inbox ID to reassign to; 0 reverts to the owner. |

> [accordion] person full type
>
> ```ts theme={null}
> {
>   id?: number,
>   name?: string,
>   email?: string,
>   phone?: string
> }
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `externalConversationId` | `string \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `string \| null` | No | — |
| `updatedById` | `string \| null` | No | — |
| `ownerUserId` | `number \| null` | No | — |
| `ownerSharedInboxId` | `number \| null` | No | — |
| `assignedUserId` | `number \| null` | No | — |
| `assignedSharedInboxId` | `number \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `archived` | `boolean \| number \| null` | No | — |
| `person` | `object \| null` | No | — |
| `conversationDeepLinkUrl` | `string \| null` | No | — |

> [accordion] person full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   email?: string | null,
>   phone?: string | null
> } | null
> ```

***

### updateMessage

`inboxApps.updateMessage`

Update a message previously delivered to an inbox app conversation

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.inboxApps.updateMessage({ inboxAppId: 'app_123', externalMessageId: 'msg_910', deliveryStatus: 'Read' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `inboxAppId` | `string` | Yes | The Inbox App ID updating the message. |
| `id` | `number` | No | FUB ID of the Inbox App message to update. |
| `externalMessageId` | `string` | No | Identifies the message when sent alone; updates its value alongside `id`. |
| `deliveryStatus` | `Sent \| Delivered \| Read \| Not Delivered` | No | — |
| `deliveryStatusErrorMessage` | `string` | No | User-facing error message for Not Delivered statuses. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `sentAt` | `string \| null` | No | — |
| `deliveryStatus` | `string \| null` | No | — |
| `deliveryStatusErrorMessage` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `isIncoming` | `boolean \| number \| null` | No | — |
| `isSystem` | `boolean \| number \| null` | No | — |
| `systemType` | `string \| null` | No | — |
| `message` | `string \| null` | No | — |
| `userId` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `sender` | `object \| null` | No | — |
| `attachments` | `object[] \| null` | No | — |
| `conversationDeepLinkUrl` | `string \| null` | No | — |

> [accordion] sender full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   personId?: number | null,
>   relationshipId?: number | null,
>   participantId?: number | null,
>   name?: string | null,
>   email?: string | null,
>   phone?: string | null,
>   avatar?: string | null
> } | null
> ```

> [accordion] attachments full type
>
> ```ts theme={null}
> {
>   filename?: string | null,
>   url?: string | null
> }[] | null
> ```

***

## Notes

### create

`notes.create`

Add a note to a person

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.notes.create({ personId: 123, subject: 'Tour follow-up', body: 'Sent the listing packet.' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | The person the note is attached to. |
| `subject` | `string` | No | — |
| `body` | `string` | No | — |
| `isHtml` | `boolean` | No | When true, HTML tags in the body are rendered. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `body` | `string \| null` | No | — |
| `isHtml` | `boolean \| number \| null` | No | — |
| `user` | `Record<string, any> \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### delete

`notes.delete`

Permanently delete a note

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.notes.delete({ id: 21 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The note ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`notes.get`

Get one note by ID, optionally with its threaded replies and reactions

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.notes.get({ id: 21, includeThreadedReplies: true });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The note ID. |
| `includeThreadedReplies` | `boolean` | No | Include the threaded replies attached to the note. |
| `includeReactions` | `boolean` | No | Include the reactions attached to the note. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `body` | `string \| null` | No | — |
| `isHtml` | `boolean \| number \| null` | No | — |
| `user` | `Record<string, any> \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### update

`notes.update`

Update a note's subject, body or person

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.notes.update({ id: 21, body: 'Sent the listing packet and comps.' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The note ID. |
| `personId` | `number` | No | — |
| `subject` | `string` | No | — |
| `body` | `string` | No | — |
| `isHtml` | `boolean` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `body` | `string \| null` | No | — |
| `isHtml` | `boolean \| number \| null` | No | — |
| `user` | `Record<string, any> \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

## People

### checkDuplicate

`people.checkDuplicate`

Check whether a person with this email address or phone number already exists, and who they are assigned to, before creating a new lead

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.people.checkDuplicate({ email: 'jordan@acme-logistics.com' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `email` | `string` | No | — |
| `phone` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `found` | `boolean` | Yes | — |
| `matchedBy` | `string \| null` | No | — |
| `assignedTo` | `string \| null` | No | — |

***

### claim

`people.claim`

Claim an unclaimed lead so it becomes the user's contact

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.people.claim({ personId: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | The unclaimed person to claim. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `stage` | `string \| null` | No | — |
| `stageUpdated` | `string \| null` | No | — |
| `source` | `string \| null` | No | — |
| `sourceUrl` | `string \| null` | No | — |
| `lastActivity` | `string \| null` | No | — |
| `lastCommunication` | `string \| null` | No | — |
| `contacted` | `boolean \| number \| null` | No | — |
| `price` | `number \| null` | No | — |
| `emails` | `object[] \| null` | No | — |
| `phones` | `object[] \| null` | No | — |
| `addresses` | `object[] \| null` | No | — |
| `tags` | `string[] \| null` | No | — |
| `timeframeId` | `number \| null` | No | — |
| `background` | `string \| null` | No | — |
| `picture` | `string \| object \| null` | No | — |
| `assignedUserId` | `number \| null` | No | — |
| `assignedPondId` | `number \| null` | No | — |
| `assignedLenderId` | `number \| null` | No | — |
| `assignedPartnerId` | `number \| null` | No | — |
| `assignedToList` | `string[] \| null` | No | — |
| `customFields` | `Record<string, any> \| null` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[] | null
> ```

> [accordion] picture full type
>
> ```ts theme={null}
> string | {
>   small?: string | null
> } | null
> ```

***

### create

`people.create`

Create a person, optionally merging into an existing duplicate instead of creating a new lead

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.people.create({ firstName: 'Jordan', lastName: 'Rivera', emails: [{ value: 'jordan@acme-logistics.com', type: 'home' }], tags: ['Zillow'] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `firstName` | `string` | No | — |
| `lastName` | `string` | No | — |
| `stage` | `string` | No | — |
| `source` | `string` | No | — |
| `sourceUrl` | `string` | No | — |
| `contacted` | `boolean` | No | — |
| `price` | `number` | No | — |
| `assignedTo` | `string` | No | — |
| `assignedUserId` | `number` | No | — |
| `assignedPondId` | `number` | No | — |
| `assignedLenderName` | `string` | No | — |
| `assignedLenderId` | `number` | No | — |
| `background` | `string` | No | — |
| `tags` | `string[]` | No | — |
| `timeframeId` | `number` | No | Buying timeframe ID from timeframes.list. |
| `collaborators` | `number[]` | No | User IDs to set as collaborators on the person. |
| `createdAt` | `string` | No | Backdates the creation time, for importing historical leads. |
| `customFields` | `Record<string, any>` | No | — |
| `emails` | `object[]` | No | — |
| `phones` | `object[]` | No | — |
| `addresses` | `object[]` | No | — |
| `deduplicate` | `boolean` | No | When true, the lead is merged into an existing duplicate instead of creating a new person. |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `stage` | `string \| null` | No | — |
| `stageUpdated` | `string \| null` | No | — |
| `source` | `string \| null` | No | — |
| `sourceUrl` | `string \| null` | No | — |
| `lastActivity` | `string \| null` | No | — |
| `lastCommunication` | `string \| null` | No | — |
| `contacted` | `boolean \| number \| null` | No | — |
| `price` | `number \| null` | No | — |
| `emails` | `object[] \| null` | No | — |
| `phones` | `object[] \| null` | No | — |
| `addresses` | `object[] \| null` | No | — |
| `tags` | `string[] \| null` | No | — |
| `timeframeId` | `number \| null` | No | — |
| `background` | `string \| null` | No | — |
| `picture` | `string \| object \| null` | No | — |
| `assignedUserId` | `number \| null` | No | — |
| `assignedPondId` | `number \| null` | No | — |
| `assignedLenderId` | `number \| null` | No | — |
| `assignedPartnerId` | `number \| null` | No | — |
| `assignedToList` | `string[] \| null` | No | — |
| `customFields` | `Record<string, any> \| null` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[] | null
> ```

> [accordion] picture full type
>
> ```ts theme={null}
> string | {
>   small?: string | null
> } | null
> ```

***

### delete

`people.delete`

Permanently delete a person from the account

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.people.delete({ id: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The person ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`people.get`

Get one person by ID with their contact details, stage, source, tags and timeframes

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.people.get({ id: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The person ID. |
| `fields` | `string` | No | Comma-separated fields to return, or `allFields`; custom fields are only returned when requested here. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `stage` | `string \| null` | No | — |
| `stageUpdated` | `string \| null` | No | — |
| `source` | `string \| null` | No | — |
| `sourceUrl` | `string \| null` | No | — |
| `lastActivity` | `string \| null` | No | — |
| `lastCommunication` | `string \| null` | No | — |
| `contacted` | `boolean \| number \| null` | No | — |
| `price` | `number \| null` | No | — |
| `emails` | `object[] \| null` | No | — |
| `phones` | `object[] \| null` | No | — |
| `addresses` | `object[] \| null` | No | — |
| `tags` | `string[] \| null` | No | — |
| `timeframeId` | `number \| null` | No | — |
| `background` | `string \| null` | No | — |
| `picture` | `string \| object \| null` | No | — |
| `assignedUserId` | `number \| null` | No | — |
| `assignedPondId` | `number \| null` | No | — |
| `assignedLenderId` | `number \| null` | No | — |
| `assignedPartnerId` | `number \| null` | No | — |
| `assignedToList` | `string[] \| null` | No | — |
| `customFields` | `Record<string, any> \| null` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[] | null
> ```

> [accordion] picture full type
>
> ```ts theme={null}
> string | {
>   small?: string | null
> } | null
> ```

***

### ignoreUnclaimed

`people.ignoreUnclaimed`

Ignore an unclaimed lead so it is no longer offered to the user; the lead answers 204 and is not deleted

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.people.ignoreUnclaimed({ personId: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | The unclaimed person to ignore. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `success` | `true` | Yes | — |
| `personId` | `number` | Yes | — |

***

### list

`people.list`

List people with filters such as name, email, phone, stage, source, tags or assignment, sorted and paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.people.list({ limit: 10, stage: 'Lead' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `id` | `number[]` | No | Only these people; sent as the comma-separated `id` filter. |
| `sort` | `string` | No | Sort order, e.g. `id`, `created`, `updated`, `name`, `stage` or `lastActivity`, optionally prefixed with `-` for descending. |
| `fields` | `string` | No | Comma separated list of fields to return, or `allFields`. |
| `lastActivityAfter` | `string \| null` | No | — |
| `lastActivityBefore` | `string \| null` | No | — |
| `name` | `string` | No | — |
| `firstName` | `string` | No | — |
| `lastName` | `string` | No | — |
| `email` | `string` | No | — |
| `phone` | `string` | No | — |
| `stage` | `string` | No | Stage name to filter by, e.g. `Lead` or `Trash`. |
| `source` | `string` | No | — |
| `assignedTo` | `string` | No | — |
| `assignedUserId` | `number` | No | — |
| `assignedPondId` | `number` | No | — |
| `assignedLenderName` | `string` | No | — |
| `assignedLenderId` | `number` | No | — |
| `contacted` | `boolean` | No | — |
| `priceAbove` | `number` | No | — |
| `priceBelow` | `number` | No | — |
| `smartListId` | `number` | No | — |
| `includeTrash` | `boolean` | No | — |
| `includeUnclaimed` | `boolean` | No | — |
| `tags` | `string[]` | No | Tags to match; sent as the comma-separated `tags` filter. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `people` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] people full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   updated?: string | null,
>   name?: string | null,
>   firstName?: string | null,
>   lastName?: string | null,
>   stage?: string | null,
>   stageUpdated?: string | null,
>   source?: string | null,
>   sourceUrl?: string | null,
>   lastActivity?: string | null,
>   lastCommunication?: string | null,
>   contacted?: boolean | number | null,
>   price?: number | null,
>   emails?: {
>     value?: string | null,
>     type?: string | null
>   }[] | null,
>   phones?: {
>     value?: string | null,
>     type?: string | null
>   }[] | null,
>   addresses?: {
>     type?: string | null,
>     street?: string | null,
>     city?: string | null,
>     state?: string | null,
>     postalCode?: string | null,
>     country?: string | null
>   }[] | null,
>   tags?: string[] | null,
>   timeframeId?: number | null,
>   background?: string | null,
>   picture?: string | {
>     small?: string | null
>   } | null,
>   assignedUserId?: number | null,
>   assignedPondId?: number | null,
>   assignedLenderId?: number | null,
>   assignedPartnerId?: number | null,
>   assignedToList?: string[] | null,
>   customFields?: Record<string, any> | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### unclaimed

`people.unclaimed`

List the unclaimed leads currently offered to the user

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.people.unclaimed({ limit: 25 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `people` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] people full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   updated?: string | null,
>   name?: string | null,
>   firstName?: string | null,
>   lastName?: string | null,
>   stage?: string | null,
>   stageUpdated?: string | null,
>   source?: string | null,
>   sourceUrl?: string | null,
>   lastActivity?: string | null,
>   lastCommunication?: string | null,
>   contacted?: boolean | number | null,
>   price?: number | null,
>   emails?: {
>     value?: string | null,
>     type?: string | null
>   }[] | null,
>   phones?: {
>     value?: string | null,
>     type?: string | null
>   }[] | null,
>   addresses?: {
>     type?: string | null,
>     street?: string | null,
>     city?: string | null,
>     state?: string | null,
>     postalCode?: string | null,
>     country?: string | null
>   }[] | null,
>   tags?: string[] | null,
>   timeframeId?: number | null,
>   background?: string | null,
>   picture?: string | {
>     small?: string | null
>   } | null,
>   assignedUserId?: number | null,
>   assignedPondId?: number | null,
>   assignedLenderId?: number | null,
>   assignedPartnerId?: number | null,
>   assignedToList?: string[] | null,
>   customFields?: Record<string, any> | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`people.update`

Update one person's contact details, stage, price, assignment, tags, timeframes or custom fields

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.people.update({ id: 123, stage: 'Working', mergeTags: true, tags: ['Hot'] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The person ID. |
| `firstName` | `string` | No | — |
| `lastName` | `string` | No | — |
| `stage` | `string` | No | — |
| `source` | `string` | No | — |
| `contacted` | `boolean` | No | — |
| `price` | `number` | No | — |
| `assignedTo` | `string` | No | — |
| `assignedUserId` | `number` | No | — |
| `assignedPondId` | `number` | No | — |
| `assignedLenderName` | `string` | No | — |
| `assignedLenderId` | `number` | No | — |
| `background` | `string` | No | — |
| `emails` | `object[]` | No | — |
| `phones` | `object[]` | No | Replaces all existing phone numbers, including relationship numbers. Include every number to keep. |
| `addresses` | `object[]` | No | — |
| `tags` | `string[]` | No | Replaces the existing tags unless mergeTags is true. |
| `timeframeId` | `number` | No | Buying timeframe ID from timeframes.list. |
| `customFields` | `Record<string, any>` | No | — |
| `mergeTags` | `boolean` | No | When true, sent tags are merged into the existing tags instead of replacing them. |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `stage` | `string \| null` | No | — |
| `stageUpdated` | `string \| null` | No | — |
| `source` | `string \| null` | No | — |
| `sourceUrl` | `string \| null` | No | — |
| `lastActivity` | `string \| null` | No | — |
| `lastCommunication` | `string \| null` | No | — |
| `contacted` | `boolean \| number \| null` | No | — |
| `price` | `number \| null` | No | — |
| `emails` | `object[] \| null` | No | — |
| `phones` | `object[] \| null` | No | — |
| `addresses` | `object[] \| null` | No | — |
| `tags` | `string[] \| null` | No | — |
| `timeframeId` | `number \| null` | No | — |
| `background` | `string \| null` | No | — |
| `picture` | `string \| object \| null` | No | — |
| `assignedUserId` | `number \| null` | No | — |
| `assignedPondId` | `number \| null` | No | — |
| `assignedLenderId` | `number \| null` | No | — |
| `assignedPartnerId` | `number \| null` | No | — |
| `assignedToList` | `string[] \| null` | No | — |
| `customFields` | `Record<string, any> \| null` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[] | null
> ```

> [accordion] picture full type
>
> ```ts theme={null}
> string | {
>   small?: string | null
> } | null
> ```

***

## People Relationships

### create

`peopleRelationships.create`

Create a partner relationship attached to a person

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.peopleRelationships.create({ personId: 123, firstName: 'Sam', lastName: 'Rivera', type: 'Spouse', emails: [{ value: 'sam@acme-logistics.com' }] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | ID of the person the relationship is associated with. |
| `firstName` | `string` | No | — |
| `lastName` | `string` | No | — |
| `type` | `string` | No | Relationship type, e.g. `Spouse`, `Brother` or `Partner`. |
| `emails` | `object[]` | No | — |
| `phones` | `object[]` | No | — |
| `addresses` | `object[]` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `emails` | `object[] \| null` | No | — |
| `phones` | `object[] \| null` | No | — |
| `addresses` | `object[] \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[] | null
> ```

***

### delete

`peopleRelationships.delete`

Permanently delete a partner relationship

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.peopleRelationships.delete({ id: 67 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | ID of the relationship to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`peopleRelationships.get`

Get one partner relationship by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.peopleRelationships.get({ id: 67 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | ID of the relationship. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `emails` | `object[] \| null` | No | — |
| `phones` | `object[] \| null` | No | — |
| `addresses` | `object[] \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[] | null
> ```

***

### list

`peopleRelationships.list`

List the partner relationships of people, filtered by person or name

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.peopleRelationships.list({ personId: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `sort` | `string` | No | — |
| `personId` | `number` | No | — |
| `name` | `string` | No | — |
| `firstName` | `string` | No | — |
| `lastName` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `peopleRelationships` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] peopleRelationships full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   personId?: number | null,
>   firstName?: string | null,
>   lastName?: string | null,
>   type?: string | null,
>   emails?: {
>     value?: string | null,
>     type?: string | null
>   }[] | null,
>   phones?: {
>     value?: string | null,
>     type?: string | null
>   }[] | null,
>   addresses?: {
>     type?: string | null,
>     street?: string | null,
>     city?: string | null,
>     state?: string | null,
>     postalCode?: string | null,
>     country?: string | null
>   }[] | null,
>   created?: string | null,
>   updated?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`peopleRelationships.update`

Update the name, type or contact details of a relationship

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.peopleRelationships.update({ id: 67, type: 'Partner' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | ID of the relationship. |
| `firstName` | `string` | No | — |
| `lastName` | `string` | No | — |
| `type` | `string` | No | — |
| `emails` | `object[]` | No | — |
| `phones` | `object[]` | No | — |
| `addresses` | `object[]` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `emails` | `object[] \| null` | No | — |
| `phones` | `object[] \| null` | No | — |
| `addresses` | `object[] \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

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

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

> [accordion] addresses full type
>
> ```ts theme={null}
> {
>   type?: string | null,
>   street?: string | null,
>   city?: string | null,
>   state?: string | null,
>   postalCode?: string | null,
>   country?: string | null
> }[] | null
> ```

***

## Person Attachments

### create

`personAttachments.create`

Attach an externally hosted file to a person

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.personAttachments.create({ personId: 123, uri: 'https://files.example.com/contract.pdf', fileName: 'contract.pdf' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | ID of the person. |
| `uri` | `string` | Yes | URI of the externally hosted file. |
| `fileName` | `string` | Yes | Name of the file. |
| `fileSize` | `number` | No | Size of the file in bytes. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `uri` | `string \| null` | No | — |
| `fileName` | `string \| null` | No | — |
| `fileSize` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |

***

### delete

`personAttachments.delete`

Permanently delete a file attachment from a person

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.personAttachments.delete({ id: 45 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | ID of the attachment. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`personAttachments.get`

Get one file attachment of a person by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.personAttachments.get({ id: 45 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | ID of the attachment. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `uri` | `string \| null` | No | — |
| `fileName` | `string \| null` | No | — |
| `fileSize` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |

***

### update

`personAttachments.update`

Update the file URI, name or size of a person attachment

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.personAttachments.update({ id: 45, personId: 123, uri: 'https://files.example.com/contract-v2.pdf', fileName: 'contract-v2.pdf' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | ID of the person. |
| `uri` | `string` | Yes | URI of the externally hosted file. |
| `fileName` | `string` | Yes | Name of the file. |
| `fileSize` | `number` | No | Size of the file in bytes. |
| `id` | `number` | Yes | ID of the attachment. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `uri` | `string \| null` | No | — |
| `fileName` | `string \| null` | No | — |
| `fileSize` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |

***

## Pipelines

### create

`pipelines.create`

Create a deal pipeline with an optional stage list

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.pipelines.create({ name: 'Buyer pipeline', stages: [{ name: 'New', closedStage: false }, { name: 'Touring', closedStage: false }, { name: 'Offer', closedStage: true }] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | Name of the pipeline. |
| `description` | `string` | No | — |
| `stages` | `object[]` | No | Stage objects to associate with the pipeline. |
| `orderWeight` | `number` | No | — |

> [accordion] stages full type
>
> ```ts theme={null}
> {
>   name: string,
>   closedStage: boolean,
>   description?: string,
>   orderWeight?: number,
>   color?: string
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `stages` | `object[] \| null` | No | — |

> [accordion] stages full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   description?: string | null,
>   orderWeight?: number | null,
>   color?: string | null,
>   closedStage?: boolean | number | null,
>   isProtected?: boolean | number | null,
>   peopleCount?: number | null
> }[] | null
> ```

***

### delete

`pipelines.delete`

Permanently delete a deal pipeline

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.pipelines.delete({ id: 2 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The pipeline ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`pipelines.get`

Get one deal pipeline by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.pipelines.get({ id: 2 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The pipeline ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `stages` | `object[] \| null` | No | — |

> [accordion] stages full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   description?: string | null,
>   orderWeight?: number | null,
>   color?: string | null,
>   closedStage?: boolean | number | null,
>   isProtected?: boolean | number | null,
>   peopleCount?: number | null
> }[] | null
> ```

***

### list

`pipelines.list`

List the deal pipelines with their stages and order

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.pipelines.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `name` | `string` | No | The pipeline name to look up (must be an exact match). |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `pipelines` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] pipelines full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   description?: string | null,
>   orderWeight?: number | null,
>   stages?: {
>     id?: number | null,
>     name?: string | null,
>     description?: string | null,
>     orderWeight?: number | null,
>     color?: string | null,
>     closedStage?: boolean | number | null,
>     isProtected?: boolean | number | null,
>     peopleCount?: number | null
>   }[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`pipelines.update`

Update a pipeline's name, description or stage order

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.pipelines.update({ id: 2, name: 'Buyer pipeline 2026' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The pipeline ID. |
| `name` | `string` | No | — |
| `description` | `string` | No | — |
| `stages` | `object[]` | No | — |
| `orderWeight` | `number` | No | — |

> [accordion] stages full type
>
> ```ts theme={null}
> {
>   name: string,
>   closedStage: boolean,
>   description?: string,
>   orderWeight?: number,
>   color?: string,
>   id?: number
> }[]
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `stages` | `object[] \| null` | No | — |

> [accordion] stages full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   description?: string | null,
>   orderWeight?: number | null,
>   color?: string | null,
>   closedStage?: boolean | number | null,
>   isProtected?: boolean | number | null,
>   peopleCount?: number | null
> }[] | null
> ```

***

## Ponds

### create

`ponds.create`

Create a pond with the users whose leads land in it

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.ponds.create({ name: 'Buyer pond', userId: 1, userIds: [1, 4] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | The name of the pond to create. |
| `userId` | `number` | Yes | The Pond Lead Agent. |
| `userIds` | `number[]` | Yes | IDs of all users to add as members of the pond. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `userId` | `number \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |

***

### delete

`ponds.delete`

Permanently delete a pond

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.ponds.delete({ id: 6, assignTo: 1 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The pond ID to delete. |
| `assignTo` | `number` | Yes | Agent who receives the contacts currently in this pond after it is deleted. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`ponds.get`

Get one pond by ID with its assigned users

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.ponds.get({ id: 6 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The pond ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `userId` | `number \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |

***

### list

`ponds.list`

List the ponds, the lead pools that distribute new contacts to agents

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.ponds.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `ponds` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] ponds full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   userId?: number | null,
>   userIds?: number[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`ponds.update`

Update a pond's name or assigned users

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.ponds.update({ id: 6, name: 'Buyer pond 2026' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The pond ID. |
| `name` | `string` | No | — |
| `userId` | `number \| string` | No | — |
| `userIds` | `(number \| string)[]` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `userId` | `number \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |

***

## Rate Limit

### limits

`rateLimit.limits`

Read the rate-limit levels currently configured for this system

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.rateLimit.limits({});
```

**Input:** *empty object*

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `system` | `string \| null` | No | — |
| `current_limits` | `object \| null` | No | — |

> [accordion] current\_limits full type
>
> ```ts theme={null}
> {
>   across_all_accounts?: Record<string, any> | null,
>   per_account?: Record<string, any> | null
> } | null
> ```

***

### usage

`rateLimit.usage`

Read this system's 24-hour API usage totals and rate-limit statistics

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.rateLimit.usage({});
```

**Input:** *empty object*

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `system` | `string \| null` | No | — |
| `period` | `string \| null` | No | — |
| `usage` | `object \| null` | No | — |
| `current_limits` | `object \| null` | No | — |

> [accordion] usage full type
>
> ```ts theme={null}
> {
>   total_requests?: number | null,
>   rate_limited_requests?: number | null,
>   rate_limit_percentage?: number | null,
>   peak_hour?: string | null,
>   current_limits?: {
>     across_all_accounts?: Record<string, any> | null,
>     per_account?: Record<string, any> | null
>   } | null
> } | null
> ```

> [accordion] current\_limits full type
>
> ```ts theme={null}
> {
>   across_all_accounts?: Record<string, any> | null,
>   per_account?: Record<string, any> | null
> } | null
> ```

***

## Reactions

### create

`reactions.create`

Add a reaction to a note or other reference

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.reactions.create({ refType: 'Note', refId: '21', body: '👍' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `refType` | `Note \| Call \| ThreadedReply` | Yes | The type of entity being reacted to. |
| `refId` | `number \| string` | Yes | The ID of the entity being reacted to. |
| `body` | `string` | No | The single-character emoji reaction. |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   createdBy?: string | null,
>   createdById?: number | null,
>   refType?: string | null,
>   refId?: number | null,
>   body?: string | null
> }[]
> ```

***

### delete

`reactions.delete`

Remove a reaction, sending the documented delete body

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.reactions.delete({ refType: 'Note', refId: '21' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `refType` | `Note \| Call \| ThreadedReply` | Yes | The type of entity the reaction is removed from. |
| `refId` | `number \| string` | Yes | The ID of the entity. |
| `emoji` | `string` | No | Single character emoji reaction to delete, as a query filter. |
| `body` | `string` | No | The single-character emoji reaction, carried as the DELETE request body. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `success` | `true` | Yes | — |
| `refType` | `string` | Yes | — |
| `refId` | `number \| string` | Yes | — |

***

### get

`reactions.get`

Get the reactions attached to a note

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.reactions.get({ id: 31 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The reaction ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `createdBy` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `refType` | `string \| null` | No | — |
| `refId` | `number \| null` | No | — |
| `body` | `string \| null` | No | — |

***

## Smart Lists

### get

`smartLists.get`

Get one smart list by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.smartLists.get({ id: 2 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The smart list ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `total` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### list

`smartLists.list`

List the account smart lists, paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.smartLists.list({ limit: 50 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `fub2` | `boolean` | No | Include smart lists created in FUB 2.0. |
| `all` | `boolean` | No | Show all smart lists. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `smartLists` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] smartLists full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   description?: string | null,
>   total?: number | null,
>   created?: string | null,
>   updated?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

## Stages

### create

`stages.create`

Create a deal stage with an optional sort order

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.stages.create({ name: 'Touring', orderWeight: 3 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | Name of the stage. |
| `orderWeight` | `number` | No | Set this value to enforce a specific sort order. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `color` | `string \| null` | No | — |
| `closedStage` | `boolean \| number \| null` | No | — |
| `isProtected` | `boolean \| number \| null` | No | — |
| `peopleCount` | `number \| null` | No | — |

***

### delete

`stages.delete`

Delete a deal stage after reassigning its action plans to another stage

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.stages.delete({ id: 7, assignStageId: 8 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The stage ID to delete. |
| `assignStageId` | `number` | Yes | The stage id assigned to action plans referencing the deleted stage. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`stages.get`

Get one deal stage by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.stages.get({ id: 7 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The stage ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `color` | `string \| null` | No | — |
| `closedStage` | `boolean \| number \| null` | No | — |
| `isProtected` | `boolean \| number \| null` | No | — |
| `peopleCount` | `number \| null` | No | — |

***

### list

`stages.list`

List the deal stages across pipelines with their order weight

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.stages.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `sort` | `string` | No | Sorts the stages by `orderWeight`, `id` or `name`. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `stages` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] stages full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   description?: string | null,
>   orderWeight?: number | null,
>   color?: string | null,
>   closedStage?: boolean | number | null,
>   isProtected?: boolean | number | null,
>   peopleCount?: number | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`stages.update`

Update a deal stage's name or sort order

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.stages.update({ id: 7, name: 'Active touring' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The stage ID. |
| `name` | `string` | No | — |
| `orderWeight` | `number` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `description` | `string \| null` | No | — |
| `orderWeight` | `number \| null` | No | — |
| `color` | `string \| null` | No | — |
| `closedStage` | `boolean \| number \| null` | No | — |
| `isProtected` | `boolean \| number \| null` | No | — |
| `peopleCount` | `number \| null` | No | — |

***

## Tasks

### create

`tasks.create`

Create a task such as a follow-up on a person

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.tasks.create({ personId: 123, name: 'Send listing packet', type: 'Email', dueDate: '2026-05-22' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | The person this task is related to. |
| `assignedTo` | `string` | No | — |
| `assignedUserId` | `number` | No | — |
| `name` | `string` | No | — |
| `type` | `Follow Up \| Call \| Email \| Text Message \| Drop-off Mail \| Drop-off Package \| Meeting` | No | — |
| `isCompleted` | `boolean` | No | — |
| `dueDate` | `string` | No | Due date in YYYY-MM-DD format. |
| `dueDateTime` | `string` | No | — |
| `remindSecondsBefore` | `number` | No | Seconds before the due time to send a reminder; needs dueDateTime. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `isCompleted` | `boolean \| number \| null` | No | — |
| `dueDate` | `string \| null` | No | — |
| `dueDateTime` | `string \| null` | No | — |
| `completed` | `string \| null` | No | — |
| `assignedUserId` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### delete

`tasks.delete`

Permanently delete a task

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.tasks.delete({ id: 14 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The task ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`tasks.get`

Get one task by ID with its type, due date and completion status

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.tasks.get({ id: 14 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The task ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `isCompleted` | `boolean \| number \| null` | No | — |
| `dueDate` | `string \| null` | No | — |
| `dueDateTime` | `string \| null` | No | — |
| `completed` | `string \| null` | No | — |
| `assignedUserId` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### list

`tasks.list`

List tasks, filtered by person, assignee, type or due range, paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.tasks.list({ due: 'today' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `personId` | `number` | No | — |
| `assignedTo` | `string` | No | — |
| `assignedUserId` | `number` | No | — |
| `name` | `string` | No | — |
| `type` | `string` | No | — |
| `isCompleted` | `boolean` | No | — |
| `due` | `string` | No | Due range filter: `today`, `overdue`, `tomorrow`, `thisweek`, `nextweek` or `later`. |
| `dueStart` | `string` | No | — |
| `dueEnd` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `tasks` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] tasks full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   personId?: number | null,
>   name?: string | null,
>   type?: string | null,
>   isCompleted?: boolean | number | null,
>   dueDate?: string | null,
>   dueDateTime?: string | null,
>   completed?: string | null,
>   assignedUserId?: number | null,
>   created?: string | null,
>   updated?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`tasks.update`

Update a task's name, type, due date or completion

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.tasks.update({ id: 14, isCompleted: true });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The task ID. |
| `name` | `string` | No | — |
| `type` | `Follow Up \| Call \| Email \| Text Message \| Drop-off Mail \| Drop-off Package \| Meeting` | No | — |
| `isCompleted` | `boolean` | No | — |
| `dueDate` | `string` | No | — |
| `dueDateTime` | `string` | No | — |
| `personId` | `number` | No | — |
| `assignedTo` | `string` | No | Full name of the agent to assign the task to. |
| `assignedUserId` | `number` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `type` | `string \| null` | No | — |
| `isCompleted` | `boolean \| number \| null` | No | — |
| `dueDate` | `string \| null` | No | — |
| `dueDateTime` | `string \| null` | No | — |
| `completed` | `string \| null` | No | — |
| `assignedUserId` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

## Team Inboxes

### list

`teamInboxes.list`

List the team inboxes available in the account

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.teamInboxes.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `teamInboxes` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] teamInboxes full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   users?: {
>     id?: number | null,
>     name?: string | null,
>     firstName?: string | null,
>     lastName?: string | null
>   }[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

## Teams

### create

`teams.create`

Create a team with members and leaders

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.teams.create({ name: 'Downtown crew', userIds: [1, 4], leaderIds: [1] });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | The name of the team. |
| `userIds` | `number[]` | Yes | User IDs that will be members of this team. |
| `leaderIds` | `number[]` | No | The complete list of team leaders. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |
| `leaderIds` | `number[] \| null` | No | — |

***

### delete

`teams.delete`

Permanently delete a team

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.teams.delete({ id: 3 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The team ID to delete. |
| `moveToTeamId` | `number` | No | Merge before deleting: all members of this team join the target team first. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`teams.get`

Get one team by ID with its members and leaders

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.teams.get({ id: 3 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The team ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |
| `leaderIds` | `number[] \| null` | No | — |

***

### list

`teams.list`

List the teams in the account with their members

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.teams.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `teams` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] teams full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   userIds?: number[] | null,
>   leaderIds?: number[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`teams.update`

Update a team's name, members or leaders

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.teams.update({ id: 3, name: 'Downtown team' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The team ID. |
| `name` | `string` | No | — |
| `userIds` | `number[]` | No | The complete list of members of this team. |
| `leaderIds` | `number[]` | No | The complete list of team leaders. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `userIds` | `number[] \| null` | No | — |
| `leaderIds` | `number[] \| null` | No | — |

***

## Templates

### create

`templates.create`

Create an email template with subject and body, optionally shared

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.templates.create({ name: 'Tour follow-up', subject: 'Great meeting you', body: 'Hi {{first_name}}, ...', isShared: true });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | The name of the new email template. |
| `subject` | `string` | Yes | The email subject used when this template is selected. |
| `body` | `string` | Yes | The HTML body of the email template. |
| `isShared` | `boolean` | No | Share the template with other users in the account. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `isMobile` | `number \| null` | No | — |
| `imported` | `number \| null` | No | — |
| `isShared` | `boolean \| number \| null` | No | — |
| `body` | `string \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `isEditable` | `boolean \| number \| null` | No | — |
| `isDeletable` | `boolean \| number \| null` | No | — |
| `isShareable` | `boolean \| number \| null` | No | — |
| `actionPlans` | `object[] \| null` | No | — |
| `categories` | `Record<string, any>[] \| null` | No | — |

> [accordion] actionPlans full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null
> }[] | null
> ```

***

### delete

`templates.delete`

Permanently delete an email template

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.templates.delete({ id: 3 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The template ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`templates.get`

Get one email template by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.templates.get({ id: 3 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The template ID. |
| `mergePersonId` | `number` | No | Fill the merge fields with this person and the current user before returning the template. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `isMobile` | `number \| null` | No | — |
| `imported` | `number \| null` | No | — |
| `isShared` | `boolean \| number \| null` | No | — |
| `body` | `string \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `isEditable` | `boolean \| number \| null` | No | — |
| `isDeletable` | `boolean \| number \| null` | No | — |
| `isShareable` | `boolean \| number \| null` | No | — |
| `actionPlans` | `object[] \| null` | No | — |
| `categories` | `Record<string, any>[] \| null` | No | — |

> [accordion] actionPlans full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null
> }[] | null
> ```

***

### list

`templates.list`

List the email message templates, paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.templates.list({ limit: 50 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `templates` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] templates full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   updated?: string | null,
>   createdById?: number | null,
>   updatedById?: number | null,
>   name?: string | null,
>   isMobile?: number | null,
>   imported?: number | null,
>   isShared?: boolean | number | null,
>   body?: string | null,
>   subject?: string | null,
>   isEditable?: boolean | number | null,
>   isDeletable?: boolean | number | null,
>   isShareable?: boolean | number | null,
>   actionPlans?: {
>     id?: number | null,
>     name?: string | null
>   }[] | null,
>   categories?: Record<string, any>[] | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### merge

`templates.merge`

Render an email template for a person, merging their fields into the body

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.templates.merge({ templateId: 3, mergePersonId: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `templateId` | `number` | Yes | The ID of the email template to merge. |
| `mergePersonId` | `number` | No | Person ID to use for merge fields like %contact\_name%. |
| `recipients` | `object` | No | Recipients in the To: field of this email. |

> [accordion] recipients full type
>
> ```ts theme={null}
> {
>   to?: {
>     name?: string | null,
>     email?: string | null
>   }[] | null
> }
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `isMobile` | `number \| null` | No | — |
| `imported` | `number \| null` | No | — |
| `isShared` | `boolean \| number \| null` | No | — |
| `body` | `string \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `isEditable` | `boolean \| number \| null` | No | — |
| `isDeletable` | `boolean \| number \| null` | No | — |
| `isShareable` | `boolean \| number \| null` | No | — |
| `actionPlans` | `object[] \| null` | No | — |
| `categories` | `Record<string, any>[] \| null` | No | — |

> [accordion] actionPlans full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null
> }[] | null
> ```

***

### update

`templates.update`

Replace an email template's name, subject and body

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.templates.update({ id: 3, name: 'Tour follow-up', subject: 'Great meeting you today', body: 'Hi there' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The template ID. |
| `name` | `string` | Yes | The new name for the email template. |
| `subject` | `string` | Yes | The new subject for the email template. |
| `body` | `string` | Yes | The new body for the email template. |
| `isShared` | `boolean` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `updatedById` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `isMobile` | `number \| null` | No | — |
| `imported` | `number \| null` | No | — |
| `isShared` | `boolean \| number \| null` | No | — |
| `body` | `string \| null` | No | — |
| `subject` | `string \| null` | No | — |
| `isEditable` | `boolean \| number \| null` | No | — |
| `isDeletable` | `boolean \| number \| null` | No | — |
| `isShareable` | `boolean \| number \| null` | No | — |
| `actionPlans` | `object[] \| null` | No | — |
| `categories` | `Record<string, any>[] \| null` | No | — |

> [accordion] actionPlans full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null
> }[] | null
> ```

***

## Text Messages

### create

`textMessages.create`

Log a text message on a person with its direction and byline details

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.textMessages.create({ personId: 123, message: 'Tour confirmed for Friday', toNumber: '888-555-0123', fromNumber: '888-555-0199' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `personId` | `number` | Yes | The person associated with the text message. |
| `message` | `string` | Yes | The body of the text message. |
| `toNumber` | `string` | Yes | The phone number the text was sent to. |
| `fromNumber` | `string` | Yes | The phone number the text was sent from. |
| `isIncoming` | `boolean` | No | Whether the text was incoming rather than outgoing. |
| `externalLabel` | `string` | No | Descriptive text shown in the byline of the message. |
| `externalUrl` | `string` | No | Link shown in the byline of the message. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `message` | `string \| null` | No | — |
| `isIncoming` | `boolean \| number \| null` | No | — |
| `toNumber` | `string \| null` | No | — |
| `fromNumber` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `externalId` | `string \| null` | No | — |
| `externalLabel` | `string \| null` | No | — |
| `externalUrl` | `string \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### get

`textMessages.get`

Get one text message by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.textMessages.get({ id: 32 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The text message record ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `personId` | `number \| null` | No | — |
| `message` | `string \| null` | No | — |
| `isIncoming` | `boolean \| number \| null` | No | — |
| `toNumber` | `string \| null` | No | — |
| `fromNumber` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `externalId` | `string \| null` | No | — |
| `externalLabel` | `string \| null` | No | — |
| `externalUrl` | `string \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |

***

### list

`textMessages.list`

List text messages, filtered by person or phone number, paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.textMessages.list({ personId: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `personId` | `number` | No | — |
| `toNumber` | `string` | No | — |
| `fromNumber` | `string` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `textMessages` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] textMessages full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   personId?: number | null,
>   message?: string | null,
>   isIncoming?: boolean | number | null,
>   toNumber?: string | null,
>   fromNumber?: string | null,
>   status?: string | null,
>   externalId?: string | null,
>   externalLabel?: string | null,
>   externalUrl?: string | null,
>   created?: string | null,
>   updated?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

## Text Message Templates

### create

`textMessageTemplates.create`

Create a text message template, optionally shared

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.textMessageTemplates.create({ name: 'Tour reminder', message: 'See you at the tour tomorrow!', isShared: true });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `name` | `string` | Yes | The name of the text message template. |
| `message` | `string` | Yes | The body of the text message template. |
| `isShared` | `boolean` | No | Share the template with other users in the account. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `message` | `string \| null` | No | — |
| `totalSent` | `number \| null` | No | — |
| `totalReplies` | `number \| null` | No | — |
| `isShared` | `boolean \| number \| null` | No | — |
| `createdBy` | `number \| null` | No | — |
| `isEditable` | `boolean \| number \| null` | No | — |
| `isDeletable` | `boolean \| number \| null` | No | — |
| `isShareable` | `boolean \| number \| null` | No | — |
| `sentPeopleIds` | `number[] \| null` | No | — |
| `sentPeopleCount` | `number \| null` | No | — |
| `categories` | `Record<string, any>[] \| null` | No | — |
| `actionPlans` | `Record<string, any>[] \| null` | No | — |
| `effectivenessScore` | `number \| null` | No | — |
| `windowedSent` | `number \| null` | No | — |
| `windowedReplies` | `number \| null` | No | — |
| `windowedOptOutRate` | `number \| null` | No | — |
| `totalOptOutRate` | `number \| null` | No | — |

***

### delete

`textMessageTemplates.delete`

Permanently delete a text message template

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.textMessageTemplates.delete({ id: 5 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The template ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`textMessageTemplates.get`

Get one text message template by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.textMessageTemplates.get({ id: 5 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The template ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `message` | `string \| null` | No | — |
| `totalSent` | `number \| null` | No | — |
| `totalReplies` | `number \| null` | No | — |
| `isShared` | `boolean \| number \| null` | No | — |
| `createdBy` | `number \| null` | No | — |
| `isEditable` | `boolean \| number \| null` | No | — |
| `isDeletable` | `boolean \| number \| null` | No | — |
| `isShareable` | `boolean \| number \| null` | No | — |
| `sentPeopleIds` | `number[] \| null` | No | — |
| `sentPeopleCount` | `number \| null` | No | — |
| `categories` | `Record<string, any>[] \| null` | No | — |
| `actionPlans` | `Record<string, any>[] \| null` | No | — |
| `effectivenessScore` | `number \| null` | No | — |
| `windowedSent` | `number \| null` | No | — |
| `windowedReplies` | `number \| null` | No | — |
| `windowedOptOutRate` | `number \| null` | No | — |
| `totalOptOutRate` | `number \| null` | No | — |

***

### list

`textMessageTemplates.list`

List the text message templates, paged

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.textMessageTemplates.list({ limit: 50 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `textmessagetemplates` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] textmessagetemplates full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null,
>   message?: string | null,
>   totalSent?: number | null,
>   totalReplies?: number | null,
>   isShared?: boolean | number | null,
>   createdBy?: number | null,
>   isEditable?: boolean | number | null,
>   isDeletable?: boolean | number | null,
>   isShareable?: boolean | number | null,
>   sentPeopleIds?: number[] | null,
>   sentPeopleCount?: number | null,
>   categories?: Record<string, any>[] | null,
>   actionPlans?: Record<string, any>[] | null,
>   effectivenessScore?: number | null,
>   windowedSent?: number | null,
>   windowedReplies?: number | null,
>   windowedOptOutRate?: number | null,
>   totalOptOutRate?: number | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### merge

`textMessageTemplates.merge`

Render a text message template for a person, merging their fields into the message

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.textMessageTemplates.merge({ templateId: 5, personId: 123 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `templateId` | `number` | Yes | The ID of the text message template to merge. |
| `personId` | `number` | No | Person ID to use for merge fields like %contact\_name%. |
| `recipients` | `object` | No | Recipients of this text message. |

> [accordion] recipients full type
>
> ```ts theme={null}
> {
>   to?: {
>     name?: string | null,
>     phone?: string | null
>   }[] | null
> }
> ```

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `mergedTemplate` | `string \| null` | No | — |

***

### update

`textMessageTemplates.update`

Update a text message template's name or message

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.textMessageTemplates.update({ id: 5, name: 'Tour reminder', message: 'Reminder: tour tomorrow at 5pm.' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The template ID. |
| `name` | `string` | Yes | The name of the text message template. |
| `message` | `string` | Yes | The body of the text message template. |
| `isShared` | `boolean` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `name` | `string \| null` | No | — |
| `message` | `string \| null` | No | — |
| `totalSent` | `number \| null` | No | — |
| `totalReplies` | `number \| null` | No | — |
| `isShared` | `boolean \| number \| null` | No | — |
| `createdBy` | `number \| null` | No | — |
| `isEditable` | `boolean \| number \| null` | No | — |
| `isDeletable` | `boolean \| number \| null` | No | — |
| `isShareable` | `boolean \| number \| null` | No | — |
| `sentPeopleIds` | `number[] \| null` | No | — |
| `sentPeopleCount` | `number \| null` | No | — |
| `categories` | `Record<string, any>[] \| null` | No | — |
| `actionPlans` | `Record<string, any>[] \| null` | No | — |
| `effectivenessScore` | `number \| null` | No | — |
| `windowedSent` | `number \| null` | No | — |
| `windowedReplies` | `number \| null` | No | — |
| `windowedOptOutRate` | `number \| null` | No | — |
| `totalOptOutRate` | `number \| null` | No | — |

***

## Threaded Replies

### get

`threadedReplies.get`

Get the threaded replies of a note

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.threadedReplies.get({ id: 44 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The ID of the threaded reply to return. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `createdById` | `number \| null` | No | — |
| `refType` | `string \| null` | No | — |
| `refId` | `number \| null` | No | — |
| `body` | `string \| null` | No | — |
| `reactions` | `object \| object[] \| null` | No | — |

> [accordion] reactions full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   createdBy?: string | null,
>   createdById?: number | null,
>   refType?: string | null,
>   refId?: number | null,
>   body?: string | null
> } | {
>   id?: number | null,
>   created?: string | null,
>   createdBy?: string | null,
>   createdById?: number | null,
>   refType?: string | null,
>   refId?: number | null,
>   body?: string | null
> }[] | null
> ```

***

## Timeframes

### list

`timeframes.list`

List the named timeframes available for people

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.timeframes.list({});
```

**Input:** *empty object*

**Output**

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

> [accordion] timeframes full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   timeframe?: string | null
> }[]
> ```

***

## Users

### delete

`users.delete`

Permanently remove a user from the account

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.users.delete({ id: 14, assignTo: 1 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The user ID to delete. |
| `assignTo` | `number` | Yes | ID of another user to reassign the deleted user’s leads to. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`users.get`

Get one user by ID with their role and contact details

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.users.get({ id: 1 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The user ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `created` | `string \| null` | No | — |
| `updated` | `string \| null` | No | — |
| `name` | `string \| null` | No | — |
| `firstName` | `string \| null` | No | — |
| `lastName` | `string \| null` | No | — |
| `email` | `string \| null` | No | — |
| `phone` | `string \| null` | No | — |
| `role` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `timezone` | `string \| null` | No | — |
| `beta` | `boolean \| number \| null` | No | — |
| `picture` | `any \| null` | No | — |
| `pauseLeadDistribution` | `boolean \| number \| null` | No | — |
| `lastSeenIos` | `string \| null` | No | — |
| `lastSeenAndroid` | `string \| null` | No | — |
| `lastSeenFub2` | `string \| null` | No | — |
| `canExport` | `boolean \| number \| null` | No | — |
| `canCreateApiKeys` | `boolean \| number \| null` | No | — |
| `isOwner` | `boolean \| number \| null` | No | — |
| `groups` | `object[] \| null` | No | — |
| `teamIds` | `number[] \| null` | No | — |
| `teamLeaderOf` | `number[] \| null` | No | — |
| `leadEmailAddress` | `string \| null` | No | — |

> [accordion] groups full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   name?: string | null
> }[] | null
> ```

***

### list

`users.list`

List the users of the account with their roles

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.users.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `sort` | `string` | No | Sort by `id`, `name` or `created`, optionally prefixed with `-` for descending. |
| `role` | `string` | No | Find users by role, e.g. `Broker`, `Agent` or `Lender`. |
| `name` | `string` | No | Exact full-name match; no partial matching. |
| `email` | `string` | No | — |
| `fields` | `string` | No | Comma separated fields to return (e.g. `id,name`), or `allFields`. |
| `includeDeleted` | `boolean` | No | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `users` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] users full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   created?: string | null,
>   updated?: string | null,
>   name?: string | null,
>   firstName?: string | null,
>   lastName?: string | null,
>   email?: string | null,
>   phone?: string | null,
>   role?: string | null,
>   status?: string | null,
>   timezone?: string | null,
>   beta?: boolean | number | null,
>   picture?: any | null,
>   pauseLeadDistribution?: boolean | number | null,
>   lastSeenIos?: string | null,
>   lastSeenAndroid?: string | null,
>   lastSeenFub2?: string | null,
>   canExport?: boolean | number | null,
>   canCreateApiKeys?: boolean | number | null,
>   isOwner?: boolean | number | null,
>   groups?: {
>     id?: number | null,
>     name?: string | null
>   }[] | null,
>   teamIds?: number[] | null,
>   teamLeaderOf?: number[] | null,
>   leadEmailAddress?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

## Webhook Events

### get

`webhookEvents.get`

List the delivery events recorded for one webhook subscription

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.webhookEvents.get({ id: 9001 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| string` | Yes | The ID of the webhook whose delivery events are listed. |

**Output:** `object[]`

> [accordion] Output full type
>
> ```ts theme={null}
> {
>   id?: string | null,
>   eventCreated?: string | null,
>   event?: string | null,
>   resourceIds?: number[] | null,
>   uri?: string | null
> }[]
> ```

***

## Webhooks

### create

`webhooks.create`

Subscribe a URL to one Follow Up Boss event

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.webhooks.create({ event: 'peopleCreated', url: 'https://hooks.example.com/fub' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `event` | `peopleCreated \| peopleUpdated \| peopleDeleted \| peopleTagsCreated \| peopleStageUpdated \| peopleRelationshipCreated \| peopleRelationshipUpdated \| peopleRelationshipDeleted \| notesCreated \| notesUpdated \| notesDeleted \| emEventsOpened \| emEventsClicked \| emEventsUnsubscribed \| tasksCreated \| tasksUpdated \| tasksDeleted \| appointmentsCreated \| appointmentsUpdated \| appointmentsDeleted \| textMessagesCreated \| textMessagesUpdated \| textMessagesDeleted \| callsCreated \| callsUpdated \| callsDeleted \| dealsCreated \| dealsUpdated \| dealsDeleted \| emailsCreated \| emailsUpdated \| emailsDeleted \| eventsCreated \| stageCreated \| stageUpdated \| stageDeleted` | Yes | The event the webhook responds to. |
| `url` | `string` | Yes | — |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `event` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `url` | `string \| null` | No | — |

***

### delete

`webhooks.delete`

Permanently delete a webhook subscription

**Risk:** `destructive`

```ts theme={null}
await corsair.followupboss.api.webhooks.delete({ id: 18 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The webhook ID to delete. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | — |
| `resource` | `Record<string, any> \| null` | No | — |

***

### get

`webhooks.get`

Get one webhook subscription by ID

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.webhooks.get({ id: 18 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The webhook ID. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `event` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `url` | `string \| null` | No | — |

***

### list

`webhooks.list`

List the webhook subscriptions of the account

**Risk:** `read`

```ts theme={null}
await corsair.followupboss.api.webhooks.list({});
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `next` | `string` | No | Keyset cursor from the \_metadata.next field; FUB enforces it for deep pagination. |
| `limit` | `number` | No | Number of results to return, 1-100; FUB defaults to 10. |
| `offset` | `number` | No | Number of rows to skip before returning results. |
| `sort` | `string` | No | Sort order: `id`, `created`, `updated`, `status` or `event`; defaults to `created`. |
| `event` | `string` | No | Search for webhooks by event, e.g. `peopleCreated`. |
| `status` | `Active \| Disabled` | No | Search for webhooks by status, `Active` or `Disabled`. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `webhooks` | `object[]` | Yes | — |
| `_metadata` | `object \| null` | No | — |

> [accordion] webhooks full type
>
> ```ts theme={null}
> {
>   id?: number | null,
>   event?: string | null,
>   status?: string | null,
>   url?: string | null
> }[]
> ```

> [accordion] \_metadata full type
>
> ```ts theme={null}
> {
>   collection?: string | null,
>   offset?: number | string | null,
>   limit?: number | string | null,
>   total?: number | string | null,
>   next?: string | null,
>   nextLink?: string | null
> } | null
> ```

***

### update

`webhooks.update`

Update a webhook subscription's URL or event type

**Risk:** `write`

```ts theme={null}
await corsair.followupboss.api.webhooks.update({ id: 18, url: 'https://hooks.example.com/fub-v2' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | The webhook ID. |
| `event` | `peopleCreated \| peopleUpdated \| peopleDeleted \| peopleTagsCreated \| peopleStageUpdated \| peopleRelationshipCreated \| peopleRelationshipUpdated \| peopleRelationshipDeleted \| notesCreated \| notesUpdated \| notesDeleted \| emEventsOpened \| emEventsClicked \| emEventsUnsubscribed \| tasksCreated \| tasksUpdated \| tasksDeleted \| appointmentsCreated \| appointmentsUpdated \| appointmentsDeleted \| textMessagesCreated \| textMessagesUpdated \| textMessagesDeleted \| callsCreated \| callsUpdated \| callsDeleted \| dealsCreated \| dealsUpdated \| dealsDeleted \| emailsCreated \| emailsUpdated \| emailsDeleted \| eventsCreated` | No | The event the webhook responds to. |
| `url` | `string` | No | — |
| `status` | `Active \| Disabled` | No | `Active` or `Disabled`. |

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number \| null` | No | — |
| `event` | `string \| null` | No | — |
| `status` | `string \| null` | No | — |
| `url` | `string \| null` | No | — |

***


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