> ## 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 Leiga: every `leiga.api.*` operation with input and output types.

Every `leiga.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).

## Issues

### fields

`issues.fields`

List the fields one issue type exposes, including custom ones

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.issues.fields({ projectId: 123456, issueTypeId: 1 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Leiga numeric id |
| `issueTypeId` | `number` | Yes | Leiga numeric id |

Lists the fields one issue type exposes, including the custom fields that appear in an issue's `customFieldData`.

**Output**

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

> [accordion] fields full type
>
> ```ts theme={null}
> {
>   fieldName: string,
>   fieldCode: string
> }[]
> ```

***

### get

`issues.get`

Get one issue by id, with its fields and tags

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.issues.get({ issueId: 987654 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `issueId` | `number` | Yes | Issue id |

Takes `issueId` as the `id` query parameter and answers one issue. Custom field values live in `customFieldData`, keyed by codes such as `customfield_1`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | Leiga numeric id |
| `issueNumber` | `string \| null` | No | Human-readable, e.g. SAMPL-23 |
| `summary` | `string \| null` | No | — |
| `projectId` | `number \| null` | No | Leiga numeric id |
| `issueTypeId` | `number \| null` | No | Leiga numeric id |
| `issueTypeName` | `string \| null` | No | — |
| `statusId` | `number \| null` | No | Leiga numeric id |
| `statusName` | `string \| null` | No | — |
| `statusType` | `number \| null` | No | — |
| `priorityId` | `number \| null` | No | Leiga numeric id |
| `priorityName` | `string \| null` | No | — |
| `assigneeId` | `number \| null` | No | Leiga numeric id |
| `assigneeName` | `string \| null` | No | — |
| `assigneeVO` | `object \| null` | No | — |
| `createBy` | `number \| null` | No | Leiga numeric id |
| `createByVO` | `object \| null` | No | — |
| `createTime` | `number \| null` | No | Unix epoch milliseconds |
| `updateBy` | `number \| null` | No | Leiga numeric id |
| `updateByVO` | `object \| null` | No | — |
| `updateTime` | `number \| null` | No | Unix epoch milliseconds |
| `dueDate` | `number \| null` | No | Unix epoch milliseconds |
| `startDate` | `number \| null` | No | Unix epoch milliseconds |
| `description` | `string \| null` | No | HTML |
| `sprint` | `string \| number \| null` | No | Sprint id, absent when the issue is not in one |
| `estimateLabour` | `number \| null` | No | — |
| `totalRemainingLabour` | `number \| null` | No | — |
| `isArchived` | `number \| null` | No | — |
| `issueNumberOrAlias` | `string \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customFieldData` | `Record<string, any> \| null` | No | Custom field values keyed by field code, e.g. customfield\_213979997 |

> [accordion] assigneeVO full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   userName?: string | null,
>   profilePicture?: string | null,
>   accountEnabled?: number | null
> } | null
> ```

> [accordion] createByVO full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   userName?: string | null,
>   profilePicture?: string | null,
>   accountEnabled?: number | null
> } | null
> ```

> [accordion] updateByVO full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   userName?: string | null,
>   profilePicture?: string | null,
>   accountEnabled?: number | null
> } | null
> ```

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

***

### getByNumber

`issues.getByNumber`

Get one issue by its human-readable number, such as LGC-12

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.issues.getByNumber({ issueNumber: 'LGC-12' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `issueNumber` | `string` | Yes | Issue number, e.g. LGC-12 |

Looks an issue up by its human-readable number, such as `LGC-12`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | Leiga numeric id |
| `issueNumber` | `string \| null` | No | Human-readable, e.g. SAMPL-23 |
| `summary` | `string \| null` | No | — |
| `projectId` | `number \| null` | No | Leiga numeric id |
| `issueTypeId` | `number \| null` | No | Leiga numeric id |
| `issueTypeName` | `string \| null` | No | — |
| `statusId` | `number \| null` | No | Leiga numeric id |
| `statusName` | `string \| null` | No | — |
| `statusType` | `number \| null` | No | — |
| `priorityId` | `number \| null` | No | Leiga numeric id |
| `priorityName` | `string \| null` | No | — |
| `assigneeId` | `number \| null` | No | Leiga numeric id |
| `assigneeName` | `string \| null` | No | — |
| `assigneeVO` | `object \| null` | No | — |
| `createBy` | `number \| null` | No | Leiga numeric id |
| `createByVO` | `object \| null` | No | — |
| `createTime` | `number \| null` | No | Unix epoch milliseconds |
| `updateBy` | `number \| null` | No | Leiga numeric id |
| `updateByVO` | `object \| null` | No | — |
| `updateTime` | `number \| null` | No | Unix epoch milliseconds |
| `dueDate` | `number \| null` | No | Unix epoch milliseconds |
| `startDate` | `number \| null` | No | Unix epoch milliseconds |
| `description` | `string \| null` | No | HTML |
| `sprint` | `string \| number \| null` | No | Sprint id, absent when the issue is not in one |
| `estimateLabour` | `number \| null` | No | — |
| `totalRemainingLabour` | `number \| null` | No | — |
| `isArchived` | `number \| null` | No | — |
| `issueNumberOrAlias` | `string \| null` | No | — |
| `tags` | `object[] \| null` | No | — |
| `customFieldData` | `Record<string, any> \| null` | No | Custom field values keyed by field code, e.g. customfield\_213979997 |

> [accordion] assigneeVO full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   userName?: string | null,
>   profilePicture?: string | null,
>   accountEnabled?: number | null
> } | null
> ```

> [accordion] createByVO full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   userName?: string | null,
>   profilePicture?: string | null,
>   accountEnabled?: number | null
> } | null
> ```

> [accordion] updateByVO full type
>
> ```ts theme={null}
> {
>   userId?: number | null,
>   userName?: string | null,
>   profilePicture?: string | null,
>   accountEnabled?: number | null
> } | null
> ```

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

***

### list

`issues.list`

Query the issues in a project, with filters and paging

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.issues.list({ projectId: 123456, statusTypes: [2, 3], pageSize: 25 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Project to query |
| `pageNumber` | `number` | No | Page number, from 1 |
| `pageSize` | `number` | No | Page size |
| `summary` | `string` | No | Filter on summary text |
| `orderBy` | `createTime \| updateTime` | No | Field to sort by |
| `sort` | `ASC \| DESC` | No | Sort direction |
| `statusTypes` | `number[]` | No | Status types to include: 2 not started, 3 in progress, 4 done |

Returns `{ issues, total }`, where `total` counts every match and `issues` holds one page. `statusTypes` filters by phase (2 not started, 3 in progress, 4 done); `orderBy` accepts `createTime` or `updateTime` and `sort` accepts `ASC` or `DESC`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `issues` | `object[]` | Yes | — |
| `total` | `number` | Yes | — |

> [accordion] issues full type
>
> ```ts theme={null}
> {
>   id: number,
>   summary: string,
>   issueTypeId?: number | null,
>   issueTypeName?: string | null,
>   issueTypeVO?: {
>     id?: number | null,
>     code?: string | null,
>     name?: string | null
>   } | null,
>   priorityId?: number | null,
>   priorityName?: string | null,
>   statusType?: number | null,
>   statusName?: string | null,
>   assigneeId?: number | null,
>   assigneeName?: string | null,
>   assigneeVO?: {
>     userId?: number | null,
>     userName?: string | null,
>     profilePicture?: string | null,
>     accountEnabled?: number | null
>   } | null,
>   updateBy?: number | null,
>   updateByVO?: {
>     userId?: number | null,
>     userName?: string | null,
>     profilePicture?: string | null,
>     accountEnabled?: number | null
>   } | null,
>   updateTime?: number | null,
>   dueDate?: number | null,
>   sprintName?: string | null,
>   tags?: {
>     id?: number | null,
>     tagName?: string | null
>   }[] | null,
>   customFieldData?: Record<string, any> | null
> }[]
> ```

***

### types

`issues.types`

List the issue types a project offers, such as bug or task

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.issues.types({ projectId: 123456 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Leiga numeric id |

Lists the issue types a project offers, each with an `id`, `code` and `name`.

**Output**

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

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

***

## Members

### list

`members.list`

List the members of a project with their roles

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.members.list({ projectId: 123456 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Leiga numeric id |
| `keyword` | `string` | No | Filter on a name or email |

A GET with `projectId` and an optional `keyword` filter, answering each member with their departments and project roles.

**Output**

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

> [accordion] members full type
>
> ```ts theme={null}
> {
>   userId: number,
>   userName?: string | null,
>   orgEmail?: string | null,
>   head?: string | null,
>   departmentVOList?: {
>     id?: number | null,
>     deptName?: string | null
>   }[] | null,
>   roleVOList?: {
>     id?: number | null,
>     roleCode?: string | null,
>     roleName?: string | null
>   }[] | null
> }[]
> ```

***

## Projects

### get

`projects.get`

Get one project by id, with its metadata

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.projects.get({ projectId: 123456 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Leiga numeric id |

Takes `projectId` as a query parameter and answers a single project object with `projectName`, `projectKey`, `leader`, `createTime` and `updateTime`.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | Leiga numeric id |
| `projectName` | `string` | Yes | — |
| `projectKey` | `string` | Yes | — |
| `description` | `string \| null` | No | — |
| `leader` | `string \| null` | No | Leader display name |
| `leaderId` | `number \| null` | No | Leiga numeric id |
| `avatar` | `number \| null` | No | — |
| `url` | `string \| null` | No | Console URL for the project |
| `archived` | `number \| null` | No | — |
| `status` | `number \| null` | No | — |
| `projectCategory` | `number \| null` | No | — |
| `createBy` | `number \| null` | No | Leiga numeric id |
| `createTime` | `number \| null` | No | Unix epoch milliseconds |
| `updateTime` | `number \| null` | No | Unix epoch milliseconds |

***

### getByKey

`projects.getByKey`

Get one project by its key, such as LGC

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.projects.getByKey({ projectKey: 'LGC' });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectKey` | `string` | Yes | Project key, e.g. LGC |

The same object as `projects.get`, looked up by `projectKey` instead of id.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | Leiga numeric id |
| `projectName` | `string` | Yes | — |
| `projectKey` | `string` | Yes | — |
| `description` | `string \| null` | No | — |
| `leader` | `string \| null` | No | Leader display name |
| `leaderId` | `number \| null` | No | Leiga numeric id |
| `avatar` | `number \| null` | No | — |
| `url` | `string \| null` | No | Console URL for the project |
| `archived` | `number \| null` | No | — |
| `status` | `number \| null` | No | — |
| `projectCategory` | `number \| null` | No | — |
| `createBy` | `number \| null` | No | Leiga numeric id |
| `createTime` | `number \| null` | No | Unix epoch milliseconds |
| `updateTime` | `number \| null` | No | Unix epoch milliseconds |

***

### list

`projects.list`

List the projects in the organization

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.projects.list({});
```

**Input:** *empty object*

Returns `{ projects }`, each one `{ id, pname, pkey, archived }`. `pkey` is the prefix used in issue numbers such as `LGC-12`.

**Output**

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

> [accordion] projects full type
>
> ```ts theme={null}
> {
>   id: number,
>   pname: string,
>   pkey: string,
>   archived?: number | null
> }[]
> ```

***

### templates

`projects.templates`

List the project templates available for new projects

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.projects.templates({});
```

**Input:** *empty object*

Lists the templates that `project add` accepts, each with a `code`.

**Output**

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

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

***

## Sprints

### get

`sprints.get`

Get one sprint by id

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.sprints.get({ sprintId: 789 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `sprintId` | `number` | Yes | Leiga numeric id |

Answers one sprint by id.

**Output**

| Name | Type | Required | Description |
| - | - | - | - |
| `id` | `number` | Yes | Leiga numeric id |
| `name` | `string \| null` | No | — |
| `goal` | `string \| null` | No | — |
| `projectId` | `string \| number \| null` | No | — |
| `assignee` | `number \| null` | No | Leiga numeric id |
| `assigneeName` | `string \| null` | No | — |
| `startDate` | `number \| null` | No | Unix epoch milliseconds |
| `endDate` | `number \| null` | No | Unix epoch milliseconds |
| `started` | `number \| null` | No | 1 once the sprint has started |
| `status` | `number \| null` | No | 1 planned, 2 active, 3 closed |
| `estimatePointTotal` | `number \| null` | No | — |
| `issueTypeCountMap` | `Record<string, number> \| null` | No | — |

***

### list

`sprints.list`

List a project sprints with per-issue-type counts

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.sprints.list({ projectId: 123456 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Leiga numeric id |

A POST with `projectId` in the body. Each sprint carries `startDate` and `endDate` in epoch milliseconds plus `issueTypeCountMap`, which groups its issues by type.

**Output**

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

> [accordion] sprints full type
>
> ```ts theme={null}
> {
>   id: number,
>   name?: string | null,
>   goal?: string | null,
>   projectId?: string | number | null,
>   assignee?: number | null,
>   assigneeName?: string | null,
>   startDate?: number | null,
>   endDate?: number | null,
>   started?: number | null,
>   status?: number | null,
>   estimatePointTotal?: number | null,
>   issueTypeCountMap?: Record<string, number> | null
> }[]
> ```

***

## Tags

### list

`tags.list`

List the tags defined in a project

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.tags.list({ projectId: 123456 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Leiga numeric id |

Returns `{ tags }`, each one `{ id, tagName }`.

**Output**

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

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

***

## Workflows

### list

`workflows.list`

List the workflow steps a project uses

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.workflows.list({ projectId: 123456 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Leiga numeric id |

A POST with `projectId` in the body, listing the workflow steps a project uses.

**Output**

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

> [accordion] workflows full type
>
> ```ts theme={null}
> {
>   id: number,
>   workflowName: string,
>   workflowDesc?: string | null,
>   defaultValue?: boolean | null,
>   issueTypes?: {
>     id?: number | null,
>     code?: string | null,
>     name?: string | null,
>     description?: string | null
>   }[] | null,
>   states?: {
>     stateId: number,
>     stateName?: string | null,
>     stateCategory?: number | null
>   }[] | null
> }[]
> ```

***

### nextStates

`workflows.nextStates`

List the states an issue can move to from its current one

**Risk:** `read`

```ts theme={null}
await corsair.leiga.api.workflows.nextStates({ projectId: 123456, stateId: 213980052, defId: 213980057 });
```

**Input**

| Name | Type | Required | Description |
| - | - | - | - |
| `projectId` | `number` | Yes | Leiga numeric id |
| `stateId` | `number` | Yes | Current state id, from a workflow states entry |
| `defId` | `number` | Yes | Workflow definition id, the workflow itself |

Needs all three of `projectId`, `stateId` and `defId`: Leiga answers a bare state id with `code 100 "defId should not be null"` on HTTP 200. `defId` is the workflow id, which `issues.types` reports as `workflowId`, and `stateId` is one of that workflow's `states` entries.

**Output**

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

> [accordion] states full type
>
> ```ts theme={null}
> {
>   stateId: number,
>   stateName?: string | null,
>   stateCategory?: number | null
> }[]
> ```

***


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