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.
List all people
Section titled “List all people”GET /api/peopleReturns all people for the authenticated user, sorted alphabetically by name.
Query parameters
| Parameter | Type | Description |
|---|---|---|
groupIds | string | Comma-separated group IDs. Only people belonging to at least one of these groups are returned. |
includeDetails | boolean | Defaults 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. |
includeAll | boolean | Set to true to also include important dates, person-to-person relationships, and typed custom field values. Used by data export. |
curl https://your-instance.example.com/api/people?includeDetails=false \ -H "Authorization: Bearer ntag_xxx"{ "people": [ { "id": "clx1", "name": "Ada", "surname": "Lovelace" } ] }Create a person
Section titled “Create a person”POST /api/peopleAdds 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
| Field | Type | Notes |
|---|---|---|
name | string | Required, 1-100 characters. |
surname, middleName, secondLastName, nickname | string or null | Optional name components. |
prefix, suffix | string or null | Honorific prefix/suffix (Dr., Jr.). |
organization, jobTitle | string or null | |
gender | string or null | |
anniversary, lastContact | ISO date string or null | |
notes | string or null | Markdown, up to 10,000 characters. |
relationshipToUserId | string or null | ID of a relationship type describing how this person relates to you. |
connectedThroughId | string | If set, creates a person-to-person relationship instead of a relationship to you. |
groupIds | string[] | Group IDs to add this person to. |
importantDates | array | See Important dates below. |
contactReminderEnabled, contactReminderInterval, contactReminderIntervalUnit | Contact reminder configuration. | |
cardDavSyncEnabled | boolean | |
displayNameOverride | string or null | Per-person display name override, used in Nametag and CardDAV sync. |
phoneNumbers, emails, addresses, urls, imHandles, locations, customFields | array | Multi-value vCard-style fields, each { type, ...fields }. |
customFieldValues | array | { templateId, value } pairs for typed custom field templates. |
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 a person by ID
Section titled “Get a person by ID”GET /api/people/{id}Returns full details including relationships, groups, and important dates.
curl https://your-instance.example.com/api/people/clx1 \ -H "Authorization: Bearer ntag_xxx"{ "person": { "id": "clx1", "name": "Ada", "surname": "Lovelace" } }Update a person
Section titled “Update a person”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.
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 a person
Section titled “Delete a person”DELETE /api/people/{id}Soft-deletes a person. Restorable within the 30-day retention period.
Request body (all optional)
| Field | Type | Description |
|---|---|---|
deleteOrphans | boolean | Also delete people who would become disconnected from the network. |
orphanIds | string[] | Specific orphan IDs to delete, if you don’t want all of them. |
deleteFromCardDav | boolean | Also remove the contact from the connected CardDAV server. |
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" }Restore a deleted person
Section titled “Restore a deleted person”POST /api/people/{id}/restorecurl -X POST https://your-instance.example.com/api/people/clx1/restore \ -H "Authorization: Bearer ntag_xxx"{ "person": { "id": "clx1", "name": "Ada", "deletedAt": null } }Search people
Section titled “Search people”GET /api/people/searchSearches name, surname, middle name, second last name, and nickname. Case-insensitive, returns up to 20 results.
Query parameters
| Parameter | Type | Required |
|---|---|---|
q | string | Yes, minimum 1 character. |
curl "https://your-instance.example.com/api/people/search?q=ada" \ -H "Authorization: Bearer ntag_xxx"{ "people": [ { "id": "clx1", "name": "Ada", "surname": "Lovelace" } ] }Get search index data
Section titled “Get search index data”GET /api/people/search-indexReturns a flat, denormalized dataset for client-side search indexing. Multi-value fields (phones, emails, etc.) are joined into single space-separated strings.
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" } ] }Find orphaned connections
Section titled “Find orphaned connections”GET /api/people/{id}/orphansReturns people who are only connected to your network through this person, useful as a warning before deletion.
curl https://your-instance.example.com/api/people/clx1/orphans \ -H "Authorization: Bearer ntag_xxx"{ "orphans": [ { "id": "clx2", "fullName": "Charles Babbage" } ] }Bulk actions
Section titled “Bulk actions”POST /api/people/bulkRuns 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"}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 }Find orphans for bulk deletion
Section titled “Find orphans for bulk deletion”POST /api/people/bulk/orphansComputes the aggregate orphan list for a proposed bulk delete, before you commit to it.
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 relationship graph for a person
Section titled “Get relationship graph for a person”GET /api/people/{id}/graphReturns a D3-compatible graph (nodes, edges) centered on this person, showing their direct connections.
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": []}Duplicate detection and merge
Section titled “Duplicate detection and merge”Find all duplicate groups
Section titled “Find all duplicate groups”GET /api/people/duplicatesScans all contacts and groups likely duplicates by name, email, phone, and birthday similarity. Dismissed pairs are excluded.
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 } ]}Find duplicate candidates for a person
Section titled “Find duplicate candidates for a person”GET /api/people/{id}/duplicatescurl https://your-instance.example.com/api/people/clx1/duplicates \ -H "Authorization: Bearer ntag_xxx"{ "duplicates": [ { "personId": "clx4", "name": "Ada", "similarity": 0.92 } ] }Dismiss a duplicate pair
Section titled “Dismiss a duplicate pair”POST /api/people/duplicates/dismisscurl -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 }Merge two contacts
Section titled “Merge two contacts”POST /api/people/mergeMerges 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.
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
Section titled “Important dates”Important dates (birthdays, anniversaries, and custom dates) belong to a person and can carry reminder settings.
List important dates for a person
Section titled “List important dates for a person”GET /api/people/{id}/important-datescurl 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" } ] }Create an important date
Section titled “Create an important date”POST /api/people/{id}/important-dates| Field | Type | Notes |
|---|---|---|
type | string or null | A predefined type (e.g. BIRTHDAY), or null for a custom date. |
title | string | Required if type is not set. |
date | ISO date string | Required. |
yearUnknown | boolean | Set when only month/day is known. |
reminderEnabled | boolean | |
reminderType | ONCE | RECURRING | null | |
reminderInterval | integer 1-99, or null | |
reminderIntervalUnit | DAYS | WEEKS | MONTHS | YEARS, or null |
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.
Update an important date
Section titled “Update an important date”PUT /api/people/{id}/important-dates/{dateId}Same body as create.
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 an important date
Section titled “Delete an important date”DELETE /api/people/{id}/important-dates/{dateId}Soft-deletes; restorable within the retention period.
curl -X DELETE https://your-instance.example.com/api/people/clx1/important-dates/clxdate1 \ -H "Authorization: Bearer ntag_xxx"{ "message": "Important date deleted" }Restore a deleted important date
Section titled “Restore a deleted important date”POST /api/people/{id}/important-dates/{dateId}/restorecurl -X POST https://your-instance.example.com/api/people/clx1/important-dates/clxdate1/restore \ -H "Authorization: Bearer ntag_xxx"{ "importantDate": { "id": "clxdate1", "deletedAt": null } }Photos
Section titled “Photos”Upload or replace a person photo
Section titled “Upload or replace a person photo”POST /api/people/{id}/photomultipart/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.
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" }Remove a person photo
Section titled “Remove a person photo”DELETE /api/people/{id}/photocurl -X DELETE https://your-instance.example.com/api/people/clx1/photo \ -H "Authorization: Bearer ntag_xxx"{ "message": "Photo deleted" }Get a person photo
Section titled “Get a person photo”GET /api/photos/{personId}Returns the raw image bytes with an appropriate Content-Type, served from disk.
curl https://your-instance.example.com/api/photos/clx1 \ -H "Authorization: Bearer ntag_xxx" \ -o ada.jpg