Project members
The people on a project, and their roles.
On this page
List project members
GET/project_members
People on projects.
Members whose person and project are both live. Filters combine (AND); sync unfiltered.
curl "$NIFTY_URL/api/v1/project_members" \
-H "Authorization: Bearer $NIFTY_TOKEN"
Query parameters
| Name | Description |
|---|---|
project_idULID · optional | A record's ID. |
person_idULID · optional | A record's ID. |
orderid | created_at | updated_at · optional | The field to sort by; ties are broken by id, so the order is stable. |
directionasc | desc · optional | asc (ascending) or desc (descending), for order. |
updated_sincedate-time · optional | Only records updated at or after this time (ISO 8601 with Z or a UTC offset), ordered by updated_at, id. |
cursorstring · optional | meta.next_cursor from the previous page. |
limitinteger · optional | Items per page, up to 100; a larger number is taken as 100. |
counttrue | false · optional | true adds meta.total_count: the size of the filtered set (with updated_since too), ignoring cursor and limit. Anything but true or false is a 400. |
Response
200 OK Errors: 400 401 429
{
"data": [
{
"id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"project_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"role": "Builder",
"created_at": "2026-10-10T09:30:00Z",
"updated_at": "2026-10-10T09:30:00Z"
}
],
"meta": {
"next_cursor": "eyJrIjpbIjIwMjYtMTAtMDlUMDg6MzA6MDBaIl19",
"limit": 1,
"total_count": 1
}
}
Add a project member
POST/project_members
Add a person to a project.
A person is on a project once. A duplicate, or an unknown or deleted person or project, is a 422.
To add someone new, send new_person_name instead of person_id: the person is created with the
member, in one transaction, so a 422 creates neither. A rejected name is a 422 on new_person_name,
alongside the member's other errors. With person_id too, or not a string, it's a 400.
curl -X POST "$NIFTY_URL/api/v1/project_members" \
-H "Authorization: Bearer $NIFTY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"project_member":{"project_id":"01j9zq3p4q6r8s0t2v5w7x9y1z","person_id":"01j9zq3k8m5x2v7c4n6b0t1r9e","role":"Builder"}}'
Headers
| Name | Description |
|---|---|
Idempotency-Keystring · optional | Makes a POST safe to retry for 24 hours. Needs a bearer token (400 under session auth). |
Request body
| Name | Description |
|---|---|
project_memberobject | |
project_member.project_idULID · optional | Create only. |
project_member.person_idULID · optional | Create only. |
project_member.new_person_namestring · optional | Create only, instead of person_id. Someone new, created with the member; normalised as a person's name. |
project_member.rolestring or null · optional | Free text. Spaces are squished; blank is null. |
Response
201 Created Errors: 400 401 403 409 415 422 429
{
"data": {
"id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"project_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"role": "Builder",
"created_at": "2026-10-10T09:30:00Z",
"updated_at": "2026-10-10T09:30:00Z"
}
}
Get a project member
GET/project_members/{id}
curl "$NIFTY_URL/api/v1/project_members/01j9zq3k8m5x2v7c4n6b0t1r9e" \
-H "Authorization: Bearer $NIFTY_TOKEN"
Path parameters
| Name | Description |
|---|---|
idULID | A record's ID. |
Response
200 OK Errors: 401 404 429
{
"data": {
"id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"project_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"role": "Builder",
"created_at": "2026-10-10T09:30:00Z",
"updated_at": "2026-10-10T09:30:00Z"
}
}
Change a member's role
PATCH/project_members/{id}
Also PUT /project_members/{id}, the same.
Only role changes; project_id and person_id are ignored (remove the member and add another instead).
curl -X PATCH "$NIFTY_URL/api/v1/project_members/01j9zq3k8m5x2v7c4n6b0t1r9e" \
-H "Authorization: Bearer $NIFTY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"project_member":{"project_id":"01j9zq3p4q6r8s0t2v5w7x9y1z","person_id":"01j9zq3k8m5x2v7c4n6b0t1r9e","role":"Builder"}}'
Path parameters
| Name | Description |
|---|---|
idULID | A record's ID. |
Request body
| Name | Description |
|---|---|
project_memberobject | |
project_member.project_idULID · optional | Create only. |
project_member.person_idULID · optional | Create only. |
project_member.new_person_namestring · optional | Create only, instead of person_id. Someone new, created with the member; normalised as a person's name. |
project_member.rolestring or null · optional | Free text. Spaces are squished; blank is null. |
Response
200 OK Errors: 400 401 403 404 415 422 429
{
"data": {
"id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"project_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"role": "Builder",
"created_at": "2026-10-10T09:30:00Z",
"updated_at": "2026-10-10T09:30:00Z"
}
}
Remove a project member
DELETE/project_members/{id}
Remove a person from a project.
Permanent. Writes a project_member deletion record. The project gets a new updated_at.
curl -X DELETE "$NIFTY_URL/api/v1/project_members/01j9zq3k8m5x2v7c4n6b0t1r9e" \
-H "Authorization: Bearer $NIFTY_TOKEN"
Path parameters
| Name | Description |
|---|---|
idULID | A record's ID. |
Response
204 Deleted Errors: 401 403 404 429