Skip to content

People

People are the core entity in Nametag. Only name is required; everything else, from phone numbers to important dates, is optional and can be added incrementally.

All endpoints on this page require authentication (session cookie or API token) and operate only on people owned by the authenticated user. Deleted people are excluded unless an endpoint says otherwise.

GET /api/people

Returns all people for the authenticated user, sorted alphabetically by name.

Query parameters

ParameterTypeDescription
groupIdsstringComma-separated group IDs. Only people belonging to at least one of these groups are returned.
includeDetailsbooleanDefaults to true. Set to false to skip multi-value fields (phones, emails, addresses, URLs, IM handles, locations, custom fields) for a lighter list-view payload.
includeAllbooleanSet to true to also include important dates, person-to-person relationships, and typed custom field values. Used by data export.
Terminal window
curl https://your-instance.example.com/api/people?includeDetails=false \
-H "Authorization: Bearer ntag_xxx"
{ "people": [ { "id": "clx1", "name": "Ada", "surname": "Lovelace" } ] }
POST /api/people

Adds a new person. Can include group memberships, important dates, multi-value contact fields, and a relationship type either to you or, via connectedThroughId, to another person.

Request body

FieldTypeNotes
namestringRequired, 1-100 characters.
surname, middleName, secondLastName, nicknamestring or nullOptional name components.
prefix, suffixstring or nullHonorific prefix/suffix (Dr., Jr.).
organization, jobTitlestring or null
genderstring or null
anniversary, lastContactISO date string or null
notesstring or nullMarkdown, up to 10,000 characters.
relationshipToUserIdstring or nullID of a relationship type describing how this person relates to you.
connectedThroughIdstringIf set, creates a person-to-person relationship instead of a relationship to you.
groupIdsstring[]Group IDs to add this person to.
importantDatesarraySee Important dates below.
contactReminderEnabled, contactReminderInterval, contactReminderIntervalUnitContact reminder configuration.
cardDavSyncEnabledboolean
displayNameOverridestring or nullPer-person display name override, used in Nametag and CardDAV sync.
phoneNumbers, emails, addresses, urls, imHandles, locations, customFieldsarrayMulti-value vCard-style fields, each { type, ...fields }.
customFieldValuesarray{ templateId, value } pairs for typed custom field templates.
Terminal window
curl -X POST https://your-instance.example.com/api/people \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Ada",
"surname": "Lovelace",
"organization": "Analytical Engine Society",
"groupIds": ["clxgroup1"],
"phoneNumbers": [{ "type": "mobile", "number": "+1 555 0100" }],
"importantDates": [{ "type": "BIRTHDAY", "date": "1815-12-10" }]
}'
{ "person": { "id": "clx1", "name": "Ada", "surname": "Lovelace" } }

Returns 403 if you’ve reached your plan’s people limit, 400 for validation errors.

GET /api/people/{id}

Returns full details including relationships, groups, and important dates.

Terminal window
curl https://your-instance.example.com/api/people/clx1 \
-H "Authorization: Bearer ntag_xxx"
{ "person": { "id": "clx1", "name": "Ada", "surname": "Lovelace" } }
PUT /api/people/{id}

Accepts the same fields as create, all optional. When groupIds, importantDates, or any multi-value field array is provided, it fully replaces the existing set for that field, it does not merge.

Terminal window
curl -X PUT https://your-instance.example.com/api/people/clx1 \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{ "jobTitle": "Mathematician" }'
{ "person": { "id": "clx1", "name": "Ada", "jobTitle": "Mathematician" } }
DELETE /api/people/{id}

Soft-deletes a person. Restorable within the 30-day retention period.

Request body (all optional)

FieldTypeDescription
deleteOrphansbooleanAlso delete people who would become disconnected from the network.
orphanIdsstring[]Specific orphan IDs to delete, if you don’t want all of them.
deleteFromCardDavbooleanAlso remove the contact from the connected CardDAV server.
Terminal window
curl -X DELETE https://your-instance.example.com/api/people/clx1 \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{ "deleteOrphans": false }'
{ "message": "Person deleted" }
POST /api/people/{id}/restore
Terminal window
curl -X POST https://your-instance.example.com/api/people/clx1/restore \
-H "Authorization: Bearer ntag_xxx"
{ "person": { "id": "clx1", "name": "Ada", "deletedAt": null } }
GET /api/people/search

Searches name, surname, middle name, second last name, and nickname. Case-insensitive, returns up to 20 results.

Query parameters

ParameterTypeRequired
qstringYes, minimum 1 character.
Terminal window
curl "https://your-instance.example.com/api/people/search?q=ada" \
-H "Authorization: Bearer ntag_xxx"
{ "people": [ { "id": "clx1", "name": "Ada", "surname": "Lovelace" } ] }
GET /api/people/search-index

Returns a flat, denormalized dataset for client-side search indexing. Multi-value fields (phones, emails, etc.) are joined into single space-separated strings.

Terminal window
curl https://your-instance.example.com/api/people/search-index \
-H "Authorization: Bearer ntag_xxx"
{ "people": [ { "id": "clx1", "name": "Ada", "phones": "+1 555 0100", "groups": "Colleagues" } ] }
GET /api/people/{id}/orphans

Returns people who are only connected to your network through this person, useful as a warning before deletion.

Terminal window
curl https://your-instance.example.com/api/people/clx1/orphans \
-H "Authorization: Bearer ntag_xxx"
{ "orphans": [ { "id": "clx2", "fullName": "Charles Babbage" } ] }
POST /api/people/bulk

Runs one action against multiple people. Specify either personIds or selectAll: true.

Delete

{
"action": "delete",
"personIds": ["clx1", "clx2"],
"deleteOrphans": false,
"deleteFromCardDav": false
}

Add to groups

{
"action": "addToGroups",
"selectAll": true,
"groupIds": ["clxgroup1"]
}

Set relationship type

{
"action": "setRelationship",
"personIds": ["clx1"],
"relationshipTypeId": "clxtype1"
}
Terminal window
curl -X POST https://your-instance.example.com/api/people/bulk \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{ "action": "addToGroups", "personIds": ["clx1", "clx2"], "groupIds": ["clxgroup1"] }'
{ "success": true, "affectedCount": 2 }
POST /api/people/bulk/orphans

Computes the aggregate orphan list for a proposed bulk delete, before you commit to it.

Terminal window
curl -X POST https://your-instance.example.com/api/people/bulk/orphans \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{ "personIds": ["clx1", "clx2"] }'
{ "orphans": [ { "id": "clx3", "fullName": "Charles Babbage" } ], "hasCardDavSync": false }
GET /api/people/{id}/graph

Returns a D3-compatible graph (nodes, edges) centered on this person, showing their direct connections.

Terminal window
curl https://your-instance.example.com/api/people/clx1/graph \
-H "Authorization: Bearer ntag_xxx"
{
"nodes": [ { "id": "clx1", "label": "Ada Lovelace", "groups": [], "colors": [], "isCenter": true } ],
"edges": []
}
GET /api/people/duplicates

Scans all contacts and groups likely duplicates by name, email, phone, and birthday similarity. Dismissed pairs are excluded.

Terminal window
curl https://your-instance.example.com/api/people/duplicates \
-H "Authorization: Bearer ntag_xxx"
{
"groups": [
{
"people": [ { "id": "clx1", "name": "Ada" }, { "id": "clx4", "name": "Ada" } ],
"similarity": 0.92
}
]
}
GET /api/people/{id}/duplicates
Terminal window
curl https://your-instance.example.com/api/people/clx1/duplicates \
-H "Authorization: Bearer ntag_xxx"
{ "duplicates": [ { "personId": "clx4", "name": "Ada", "similarity": 0.92 } ] }
POST /api/people/duplicates/dismiss
Terminal window
curl -X POST https://your-instance.example.com/api/people/duplicates/dismiss \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{ "personAId": "clx1", "personBId": "clx4" }'
{ "dismissed": true }
POST /api/people/merge

Merges secondaryId into primaryId. Relationships, groups, multi-value fields, and important dates transfer; the secondary contact is soft-deleted. fieldOverrides lets you pick specific field values to keep from either side.

Terminal window
curl -X POST https://your-instance.example.com/api/people/merge \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{ "primaryId": "clx1", "secondaryId": "clx4" }'
{ "person": { "id": "clx1", "name": "Ada", "surname": "Lovelace" } }

Important dates (birthdays, anniversaries, and custom dates) belong to a person and can carry reminder settings.

GET /api/people/{id}/important-dates
Terminal window
curl https://your-instance.example.com/api/people/clx1/important-dates \
-H "Authorization: Bearer ntag_xxx"
{ "importantDates": [ { "id": "clxdate1", "title": "Birthday", "date": "1815-12-10T00:00:00.000Z" } ] }
POST /api/people/{id}/important-dates
FieldTypeNotes
typestring or nullA predefined type (e.g. BIRTHDAY), or null for a custom date.
titlestringRequired if type is not set.
dateISO date stringRequired.
yearUnknownbooleanSet when only month/day is known.
reminderEnabledboolean
reminderTypeONCE | RECURRING | null
reminderIntervalinteger 1-99, or null
reminderIntervalUnitDAYS | WEEKS | MONTHS | YEARS, or null
Terminal window
curl -X POST https://your-instance.example.com/api/people/clx1/important-dates \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{
"type": "BIRTHDAY",
"date": "1815-12-10",
"reminderEnabled": true,
"reminderType": "RECURRING",
"reminderInterval": 3,
"reminderIntervalUnit": "DAYS"
}'
{ "importantDate": { "id": "clxdate1", "title": "", "date": "1815-12-10T00:00:00.000Z" } }

Returns 403 if you’ve reached your plan’s reminder limit.

PUT /api/people/{id}/important-dates/{dateId}

Same body as create.

Terminal window
curl -X PUT https://your-instance.example.com/api/people/clx1/important-dates/clxdate1 \
-H "Authorization: Bearer ntag_xxx" \
-H "Content-Type: application/json" \
-d '{ "date": "1815-12-10", "type": "BIRTHDAY", "reminderEnabled": false }'
{ "importantDate": { "id": "clxdate1", "reminderEnabled": false } }
DELETE /api/people/{id}/important-dates/{dateId}

Soft-deletes; restorable within the retention period.

Terminal window
curl -X DELETE https://your-instance.example.com/api/people/clx1/important-dates/clxdate1 \
-H "Authorization: Bearer ntag_xxx"
{ "message": "Important date deleted" }
POST /api/people/{id}/important-dates/{dateId}/restore
Terminal window
curl -X POST https://your-instance.example.com/api/people/clx1/important-dates/clxdate1/restore \
-H "Authorization: Bearer ntag_xxx"
{ "importantDate": { "id": "clxdate1", "deletedAt": null } }
POST /api/people/{id}/photo

multipart/form-data with a photo field. The image is cropped to 256x256, converted to JPEG, and stripped of EXIF data.

HEIC/HEIF files should be converted to JPEG first using POST /api/photos/convert before uploading, since the crop step requires a browser-decodable format.

Terminal window
curl -X POST https://your-instance.example.com/api/people/clx1/photo \
-H "Authorization: Bearer ntag_xxx" \
-F "photo=@ada.jpg"
{ "photo": "clx1-a1b2c3.jpg" }
DELETE /api/people/{id}/photo
Terminal window
curl -X DELETE https://your-instance.example.com/api/people/clx1/photo \
-H "Authorization: Bearer ntag_xxx"
{ "message": "Photo deleted" }
GET /api/photos/{personId}

Returns the raw image bytes with an appropriate Content-Type, served from disk.

Terminal window
curl https://your-instance.example.com/api/photos/clx1 \
-H "Authorization: Bearer ntag_xxx" \
-o ada.jpg