Person links
How two people are related to each other.
List links between people
GET/person_links
curl "$NIFTY_URL/api/v1/person_links" \
-H "Authorization: Bearer $NIFTY_TOKEN"
Query parameters
| Name | Description |
|---|---|
person_idULID · optional | Only links involving this person, on either side. |
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",
"person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"kind": "spouse",
"related_person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"note": "Met at university",
"created_at": "2026-10-10T09:30:00Z",
"updated_at": "2026-10-10T09:30:00Z"
}
],
"meta": {
"next_cursor": "eyJrIjpbIjIwMjYtMTAtMDlUMDg6MzA6MDBaIl19",
"limit": 1,
"total_count": 1
}
}
Link two people
POST/person_links
kind may be any role. Links are stored one way only, so an inverse role swaps the people
({ person_id: B, kind: "child", related_person_id: A } comes back as A is B's parent), and a
symmetric one puts the lower id first. Two people can have several links of different kinds,
but only one of each kind, whichever way round. A duplicate, a self-link or an unknown person
is a 422.
To link someone new, send new_person_name instead of person_id: the person is created with the
link, in one transaction, so a 422 creates neither. A rejected name is a 422 on new_person_name,
alongside the link's other errors. With person_id too, or not a string, it's a 400.
curl -X POST "$NIFTY_URL/api/v1/person_links" \
-H "Authorization: Bearer $NIFTY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"person_link":{"person_id":"01j9zq3k8m5x2v7c4n6b0t1r9e","kind":"sibling","related_person_id":"01j9zq3q1r3s5t7v9w1x3y5z7a","note":"Twins"}}'
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 |
|---|---|
person_linkobject | |
person_link.person_idULID · optional | A record's ID. |
person_link.new_person_namestring · optional | Create only, instead of person_id. Someone new, created with the link; normalised as a person's name. |
person_link.related_person_idULID · optional | A record's ID. |
person_link.kindPersonLinkRole · optional | A role in a person link. Each inverse follows its forward role; the rest are symmetric. |
person_link.notestring or null · optional | Spaces are squished; blank is null. |
Response
201 Created Errors: 400 401 403 409 415 422 429
{
"data": {
"id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"kind": "spouse",
"related_person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"note": "Met at university",
"created_at": "2026-10-10T09:30:00Z",
"updated_at": "2026-10-10T09:30:00Z"
}
}
Get a link
GET/person_links/{id}
curl "$NIFTY_URL/api/v1/person_links/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",
"person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"kind": "spouse",
"related_person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"note": "Met at university",
"created_at": "2026-10-10T09:30:00Z",
"updated_at": "2026-10-10T09:30:00Z"
}
}
Change a link
PATCH/person_links/{id}
Also PUT /person_links/{id}, the same.
Only the fields sent change, then the link is stored one way as on POST, so the people may swap.
curl -X PATCH "$NIFTY_URL/api/v1/person_links/01j9zq3k8m5x2v7c4n6b0t1r9e" \
-H "Authorization: Bearer $NIFTY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"person_link":{"person_id":"01j9zq3k8m5x2v7c4n6b0t1r9e","kind":"sibling","related_person_id":"01j9zq3q1r3s5t7v9w1x3y5z7a","note":"Twins"}}'
Path parameters
| Name | Description |
|---|---|
idULID | A record's ID. |
Request body
| Name | Description |
|---|---|
person_linkobject | |
person_link.person_idULID · optional | A record's ID. |
person_link.new_person_namestring · optional | Create only, instead of person_id. Someone new, created with the link; normalised as a person's name. |
person_link.related_person_idULID · optional | A record's ID. |
person_link.kindPersonLinkRole · optional | A role in a person link. Each inverse follows its forward role; the rest are symmetric. |
person_link.notestring or null · optional | Spaces are squished; blank is null. |
Response
200 OK Errors: 400 401 403 404 415 422 429
{
"data": {
"id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"kind": "spouse",
"related_person_id": "01j9zq3k8m5x2v7c4n6b0t1r9e",
"note": "Met at university",
"created_at": "2026-10-10T09:30:00Z",
"updated_at": "2026-10-10T09:30:00Z"
}
}
Remove a link
DELETE/person_links/{id}
Permanent. Writes a person_link deletion record. Both people get a new updated_at.
curl -X DELETE "$NIFTY_URL/api/v1/person_links/01j9zq3k8m5x2v7c4n6b0t1r9e" \
-H "Authorization: Bearer $NIFTY_TOKEN"
Path parameters
| Name | Description |
|---|---|
idULID | A record's ID. |
Response
204 Deleted Errors: 401 403 404 429