> For the complete documentation index, see [llms.txt](https://teamleader-sdk.mcore-services.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://teamleader-sdk.mcore-services.dev/api-reference/projects/project-lines.md).

# Project Lines

Manage project lines (tasks, materials, groups) in Teamleader Focus projects.

The lines of a project — its tasks, materials and groups, in order — `projects-v2/projectLines.*`.

Lines are created through `ProjectTasks`, `Materials` and `Groups`; this resource lists them and moves tasks and materials in and out of groups.

```php
Teamleader::projectLines()
```

|                          |                                                               |
| ------------------------ | ------------------------------------------------------------- |
| Class                    | `McoreServices\TeamleaderSDK\Resources\Projects\ProjectLines` |
| Create / update / delete | — / — / —                                                     |
| Pagination               | No                                                            |

## Endpoints

* `projects-v2/projectLines.addToGroup`
* `projects-v2/projectLines.list`
* `projects-v2/projectLines.removeFromGroup`

## Filters

Passed as the first argument to `list()`. Any other key throws.

| Filter       | Description                                                                |
| ------------ | -------------------------------------------------------------------------- |
| `assignees`  | Assignees \[{type: user\|team, id}]; a null entry matches unassigned lines |
| `project_id` | UUID of the project (required)                                             |
| `types`      | Line types: nextgenTask, nextgenMaterial, nextgenProjectGroup              |

## Accepted values

Public constants on the class. Body fields and enum values outside these lists throw before the request is sent.

| Constant         | Values                                                  |
| ---------------- | ------------------------------------------------------- |
| `ASSIGNEE_TYPES` | `team`, `user`                                          |
| `LINE_TYPES`     | `nextgenTask`, `nextgenMaterial`, `nextgenProjectGroup` |

## Methods

### `list()`

```php
list(array $filters = [], array $options = []): array
```

List a project's lines

```
list(['project_id' => $id])
list(['project_id' => $id, 'types' => ['nextgenTask']])
list(['project_id' => $id, 'assignees' => [['type' => 'user', 'id' => $userId]]])
list(['project_id' => $id, 'assignees' => [null]])   // unassigned lines
```

* `$filters` — project\_id (required), types, assignees — or the pre-2.2.9 form with types / assignees nested under `filter`
* `$options` — None; the endpoint takes no paging, sorting or includes

**Throws** `InvalidArgumentException` When project\_id is missing, or on an unknown key or value

### `addToGroup()`

```php
addToGroup(string $lineId, string $groupId): array
```

Add an existing task or material to a group

* `$lineId` — The ID of the task or material (may not be a group)
* `$groupId` — The ID of the group

### `removeFromGroup()`

```php
removeFromGroup(string $lineId): array
```

Remove a task or material from the group it is currently in

* `$lineId` — The ID of the task or material (may not be a group)

### `forProject()`

```php
forProject(string $projectId)
```

### `ofType()`

```php
ofType(array $types)
```

* `$types` — nextgenTask, nextgenMaterial and/or nextgenProjectGroup

### `tasksOnly()`

```php
tasksOnly()
```

### `materialsOnly()`

```php
materialsOnly()
```

### `groupsOnly()`

```php
groupsOnly()
```

### `assignedTo()`

```php
assignedTo(string $type, string $id)
```

Add an assignee to match; call more than once to match any of several

* `$type` — user or team

### `unassigned()`

```php
unassigned(?string $projectId = null): array
```

Get lines nobody is assigned to

Before v2.2.9 this sent no assignee filter at all and so returned every line: `assignees => null` was dropped by an isset() check. It now sends `assignees: [null]`, as the API documents. Combined with assignedTo(), it returns the unassigned lines plus that assignee's.

* `$projectId` — Optional project ID if not already set

### `get()`

```php
get(): array
```

Execute the query with pending filters (fluent interface terminator)

### `getResponseStructure()`

```php
getResponseStructure(): array
```

Get response structure documentation

## Examples

Get all lines for a project:

```php
$lines = Teamleader::projectLines()->list([
                "project_id" => "49b403be-a32e-0901-9b1c-25214f9027c6"
            ]);
```

Get only tasks for a project:

```php
$tasks = Teamleader::projectLines()->list([
                "project_id" => "49b403be-a32e-0901-9b1c-25214f9027c6",
                "types" => ["nextgenTask"],
            ]);
```

Get lines assigned to specific user:

```php
$lines = Teamleader::projectLines()->list([
                "project_id" => "49b403be-a32e-0901-9b1c-25214f9027c6",
                "assignees" => [
                    ["type" => "user", "id" => "66abace2-62af-0836-a927-fe3f44b9b47b"],
                ],
            ]);
```

Get unassigned lines:

```php
$unassigned = Teamleader::projectLines()->unassigned("project-uuid");
```

Add a task or material to a group:

```php
$result = Teamleader::projectLines()->addToGroup(
                "a14a464d-320a-49bb-b6ee-b510c7f4f66c",
                "0daf76e6-5141-4fb0-866f-01916a873a38"
            );
```

Remove a task or material from its current group:

```php
$result = Teamleader::projectLines()->removeFromGroup(
                "a14a464d-320a-49bb-b6ee-b510c7f4f66c"
            );
```

Use fluent methods for filtering:

```php
$tasks = Teamleader::projectLines()
                ->forProject("project-uuid")
                ->ofType(["nextgenTask"])
                ->assignedTo("user", "user-uuid")
                ->get();
```
