# List position assignments

Operation ID: `teamMemberPositions`

Group: PSA › Team Members

[Open in the interactive reference](https://docs.api.lensing.ai/lensing/v1/endpoints/teamMemberPositions)

`GET /psa/team-member-positions`

Read-only: Reads and returns; changes nothing.

Lists position assignments. Each position assignment links one person or placeholder to one project position. For the people on a project's team regardless of position, use GET psa/team-members.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Api-Version` | header | string · v1 | yes | The API version this request targets, named by its public identifier. Required on every request; omitting it, or naming a version this company does not have, is answered with 400. This document describes version `v1`. |

## Query surface

- `psaProjectId` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- `projectPositionId` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- `teamMemberId` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- `placeholderId` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- `invoiced` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- `lastModifiedDate` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- Orderable: psaProjectId, lastModifiedDate
- Selectable: id, psaProjectId, projectPositionId, positionName, teamMemberId, placeholderId, invoiced, lastModifiedDate
- `page[size]` — Page size
- `page[cursor]` — Opaque continuation cursor

## Response

`200` Success

Under `data`, an array of teamMemberPositionsRow:

| Field | Type | Required | Filter | Sort | Description |
| --- | --- | --- | --- | --- | --- |
| `id` | string | no | no | no | The unique identifier for the position assignment. |
| `psaProjectId` | number | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | yes | The id of the PSA project this record belongs to. It is a numeric key you can filter on here, not the UUID that GET psa/projects/:id takes. |
| `projectPositionId` | number \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | no | The id of the project position this assignment fills. It is a numeric key you can filter on here, not the UUID that GET psa/positions/:id takes. |
| `positionName` | string \| null | no | no | no | The name of the project position, paired with projectPositionId. It is returned but cannot be filtered or sorted on, and there is no endpoint to find an assignment by position name. |
| `teamMemberId` | number \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | no | The id of the assigned person's team-roster record. Absent for placeholder-only assignments. It is a numeric key, not the UUID that GET psa/team-members/:id takes. |
| `placeholderId` | number \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | no | The id of the placeholder filling this position, when it is filled by a placeholder rather than a person. It is a numeric key, not the UUID that GET psa/placeholders/:id takes. |
| `invoiced` | boolean \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | no | Whether this assignment's work has been invoiced. An invoiced assignment cannot be deleted. |
| `lastModifiedDate` | date-time \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | yes | The date and time this assignment last changed, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |

```json
{
  "data": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "psaProjectId": 0,
      "projectPositionId": 0,
      "positionName": "<positionName>",
      "teamMemberId": 0,
      "placeholderId": 0,
      "invoiced": true,
      "lastModifiedDate": "2026-01-15T09:30:00.000Z"
    }
  ],
  "pagination": {
    "hasMore": true,
    "nextCursor": "<nextCursor>"
  }
}
```

## Statuses

- `400` — Invalid request or business failure
- `401` — The request carries no valid access token.
- `403` — Not authorized
- `404` — Not found
- `429` — Too many requests from this client address. The response has no body and no `Retry-After` header.
- `500` — Internal server error
