Skip to content
Niftyhelp 2026.10.1-beta.1 Support

Beta This is the help for Nifty 2026.10.1-beta.1, which isn't released yet. Help for the current release

Schemas

The objects the API sends and takes.

On this page

Accent

The accent colour. Iris is the default.

iris | coral | jade | saffron | orchid | steel

AIModel

FieldTypeDescription
idULIDA record's ID.
ai_provider_idULIDA record's ID.
identifierstring
namestring
is_defaultbooleanAt most one model is the default; with none, only tasks with their own model run.
created_atdate-time
updated_atdate-time

AIModelResponse

FieldTypeDescription
dataAIModel

AIProvider

FieldTypeDescription
idULIDA record's ID.
namestring
kindAIProviderKindopenai_compatible covers OpenAI, Ollama, LM Studio, llama.cpp and vLLM. mock needs no network and isn't available in production.
base_urlstring or null
api_key_setbooleanWhether a key is stored. The key itself is never returned.
last_succeeded_atdate-time or nullThe last successful check, trial or AI call.
last_failed_atdate-time or null
last_errorstring or nullThe last failure's message; cleared by a success.
last_error_reasonstring or nulllast_error as a sentence fit to show, e.g. “Ollama rejected the API key.” for an HTTP 401 or 403 when a key is stored. Null when last_error is.
created_atdate-time
updated_atdate-time

AIProviderKind

openai_compatible covers OpenAI, Ollama, LM Studio, llama.cpp and vLLM. mock needs no network and isn't available in production.

openai_compatible | anthropic | mock

AIProviderResponse

FieldTypeDescription
dataAIProvider

AITask

FieldTypeDescription
keystringStable, e.g. note_titles.
namestring
descriptionstring
enabledbooleanOff until the owner turns it on.
ai_model_idULID or nullThe model the task uses; null for the default model. With neither, the task does nothing.
reasoningAITaskReasoningHow hard a reasoning model thinks before replying; none answers at once. Sent to OpenAI-compatible providers as reasoning_effort; null (the default) sends nothing, leaving it to the model. Anthropic and Mock models ignore it (the value is kept). Anything else is a 422.
max_output_tokensinteger or nullThe most tokens a reply may use (reasoning included); null for default_max_output_tokens.
default_max_output_tokensintegerThe task's own reply budget, used while max_output_tokens is null (note titles: 2,048).
backfill_pendinginteger or nullHow many records POST …/backfill would queue now; null for a task without a backfill.
updated_atdate-time or nullThe last change to its settings; null until first configured.

AITaskReasoning

How hard a reasoning model thinks before replying; none answers at once. Sent to OpenAI-compatible providers as reasoning_effort; null (the default) sends nothing, leaving it to the model. Anthropic and Mock models ignore it (the value is kept). Anything else is a 422.

none | low | medium | high | null

AITaskResponse

FieldTypeDescription
dataAITask

ApiToken

FieldTypeDescription
idinteger
namestring
created_atdate-time
expires_atdate-time or null
last_used_atdate-time or null

Appearance

FieldTypeDescription
accentAccentThe accent colour. Iris is the default.
themeThemesystem follows the device's light or dark setting. The default.
code_themeCodeThemeCode blocks in notes: match follows the theme (the default); light or dark keeps them in that scheme.
updated_atdate-timeWhen the owner record last changed.

AppearanceResponse

FieldTypeDescription
dataAppearance

Avatar

Absolute URLs that redirect to the image. Anyone with a link can load it (long and unguessable; owner decision). Thumb is 128 px square and large 256 px square, both WebP.

FieldTypeDescription
urluri
thumb_urluri
large_urluri

CalendarAttendee

Someone invited to an event (or its organizer). Matched to a person when the event is read, so never stale: a live person with this email address (ignoring case), else the one live person whose name is this name (ignoring case and accents; none when two or more share it).

FieldTypeDescription
namestringTheir name as the feed gives it, else their email address.
emailstring or nullTheir email address, lower case; null when the feed gives none.
organizerbooleanThe event's organizer (listed first).
person_idULID or nullThe person they are; null when none matches.

CalendarEvent

One occurrence of a feed's event (a repeating event gives one per instance). Read only.

FieldTypeDescription
keystringOpaque; the same for this occurrence across syncs.
feed_idULIDA record's ID.
titlestringBlank when the event has none.
all_dayboolean
starts_atdate-time or nullTimed events only.
ends_atdate-time or nullTimed events only; at or after starts_at.
start_ondate or nullAll-day events only.
end_ondate or nullAll-day events only: the last day, inclusive.
locationstring or null
descriptionstring or nullPlain text, at most 4,000 characters.
urlstring or nullAn http(s) link the event gives.
meetingCalendarMeeting or nullThe online meeting to join, found in the event's conference properties, URL, location or description; null when none.
attendee_countinteger
attendee_namesstring[]The first 10 attendees' names (else their addresses).
attendeesCalendarAttendee[]The first 10 attendees, the organizer first, each matched to a person when one fits. attendee_count counts every attendee (but not an organizer who isn't one).
rrulestring or nullThe repeat rule (RFC 5545 RRULE value, e.g. FREQ=WEEKLY;BYDAY=MO); null unless it repeats.

CalendarFeed

An iCal address whose events the calendar shows, read only. Synced; removing one records a calendar_feed deletion. Every sync attempt gives it a new updated_at. Its events aren't records: read them with GET /calendar.

FieldTypeDescription
idULIDA record's ID.
namestring
colorstringA key from the vocabulary's colors.
address_hoststringThe address's host, shown instead of the address (which is secret).
sourcegoogle | outlook | icloud | nullWhere the calendar lives, from the host: a key from the vocabulary's calendar_sources; null when unknown.
sync_everyCalendarSyncFrequencyHow often the feed is fetched; the words are the vocabulary's calendar_sync_frequencies.
last_synced_atdate-time or nullThe last successful sync (changed or not).
last_attempt_atdate-time or null
sync_errorCalendarFeedSyncError or nullWhy the latest syncs failed; null while healthy. The events shown are from last_synced_at.
created_atdate-time
updated_atdate-time

CalendarFeedResponse

FieldTypeDescription
dataCalendarFeedAn iCal address whose events the calendar shows, read only. Synced; removing one records a calendar_feed deletion. Every sync attempt gives it a new updated_at. Its events aren't records: read them with GET /calendar.

CalendarFeedSyncError

FieldTypeDescription
codeCalendarSyncErrorCodeWhy a feed couldn't be read; the words are the vocabulary's calendar_sync_errors.
http_statusinteger or nullThe server's HTTP status, when it answered with one.
failuresintegerTries that have failed in a row.

CalendarMeeting

FieldTypeDescription
providerCalendarMeetingProviderThe words are the vocabulary's meeting_providers.
urluriAn https link to join the meeting.

CalendarMeetingProvider

The words are the vocabulary's meeting_providers.

google_meet | teams | zoom | webex | whereby | jitsi | goto | other

CalendarProjectDate

FieldTypeDescription
datedate
kinddeadline | start
projectProjectMembers, role changes and member removals change the project's updated_at, as does a member's person being deleted or restored.

CalendarRange

FieldTypeDescription
fromdate
todate
todaydateToday in the owner's time zone.
eventsCalendarEvent[]
tasksTask[]
project_datesCalendarProjectDate[]
key_datesUpcomingKeyDate[]
peoplePerson[]Each person an event's attendees name (person_id), once, by name.

CalendarSyncErrorCode

Why a feed couldn't be read; the words are the vocabulary's calendar_sync_errors.

not_found | denied | server_error | unreachable | timed_out | tls | too_big | not_calendar | too_many_events | refused_address | address_unreadable | not_saved

CalendarSyncFrequency

How often the feed is fetched; the words are the vocabulary's calendar_sync_frequencies.

15_minutes | 30_minutes | hourly | 6_hours | daily

Category

FieldTypeDescription
idULIDA record's ID.
namestring
colorstringA palette key from GET /category_choices (e.g. teal). Render it from your own palette.
iconstring or nullA Lucide icon name, or null for none (show a dot). May be one no longer in the picker.
positionintegerA sort key: order by position, then id. Gaps are possible after a delete.
created_atdate-time
updated_atdate-time

CategoryChoices

FieldTypeDescription
colorsobject[]
iconsstring[]

CategoryNoteCount

FieldTypeDescription
category_idULIDA record's ID.
note_countinteger

CategoryResponse

FieldTypeDescription
dataCategory

CodeTheme

Code blocks in notes: match follows the theme (the default); light or dark keeps them in that scheme.

match | light | dark

Company

Where people work. The name keeps its casing; matching ignores case.

FieldTypeDescription
idULIDA record's ID.
namestring
created_atdate-time
updated_atdate-time

CompanyResponse

FieldTypeDescription
dataCompanyWhere people work. The name keeps its casing; matching ignores case.

Connection

One of a person's links, from their side. person_id is this person's kind.

FieldTypeDescription
idULIDThe person link's id.
person_idULIDThe other person.
kindPersonLinkRoleA role in a person link. Each inverse follows its forward role; the rest are symmetric.
notestring or null

ContactLabels

FieldTypeDescription
suggestionsstring[]
defaultstring or nullThe label a new one starts with.

Deletion

FieldTypeDescription
typestringThe resource type, e.g. "person".
idULIDA record's ID.
deleted_atdate-time

Discovery

FieldTypeDescription
app"nifty"
versionstringThe server's version; dev in an unreleased build.
min_shell_versionstringThe oldest desktop app that can open this server.
api_versionsobject[]

Document

A PDF. Synced; deleting one records a document deletion. Embeds no other record's data, only ids, so renaming a folder or a linked record changes no document. Linking or unlinking it, deleting or restoring a record it's linked to (or a list, person or project hiding a linked task), and deleting its folder while it's deleted give it a new updated_at. Notes, projects, tasks and people don't list their documents: filter GET /documents.

FieldTypeDescription
idULIDA record's ID.
namestring
folder_idULID or null
note_idsULID[]Linked live notes, by id.
project_idsULID[]
task_idsULID[]
person_idsULID[]
linksobject[]Its links to live records, for DELETE /document_links/{id}. Notes, projects, tasks, then people; each by id.
fileobject
created_atdate-time
updated_atdate-time

A document's link to one note, project, task or person; the other three are null. Not synced (a document lists its own in links).

FieldTypeDescription
idULIDA record's ID.
document_idULIDA record's ID.
note_idULID or null
project_idULID or null
task_idULID or null
person_idULID or null
created_atdate-time

DocumentLinkResponse

FieldTypeDescription
dataDocumentLinkA document's link to one note, project, task or person; the other three are null. Not synced (a document lists its own in links).

DocumentLinkWrite

document_id and exactly one of note_id, project_id, task_id and person_id.

FieldTypeDescription
document_idULIDA record's ID.
note_id optionalULID or null
project_id optionalULID or null
task_id optionalULID or null
person_id optionalULID or null

DocumentResponse

FieldTypeDescription
dataDocumentA PDF. Synced; deleting one records a document deletion. Embeds no other record's data, only ids, so renaming a folder or a linked record changes no document. Linking or unlinking it, deleting or restoring a record it's linked to (or a list, person or project hiding a linked task), and deleting its folder while it's deleted give it a new updated_at. Notes, projects, tasks and people don't list their documents: filter GET /documents.

DocumentWrite

FieldTypeDescription
name optionalstringSpaces are squished. Needn't be unique.
folder_id optionalULID or nullNull: no folder. Not an id, or an unknown folder, is a 422.
note_ids optionalULID[] or nullReplaces its links to notes; null or [] removes them. An unknown or deleted id, or one that isn't an id, is a 422 on the field.
project_ids optionalULID[] or null
task_ids optionalULID[] or nullA task in a deleted list, person or project counts as deleted.
person_ids optionalULID[] or null

EmailAddress

FieldTypeDescription
idULIDA record's ID.
addressstring
labelstring or null
created_atdate-time
updated_atdate-time

Error

FieldTypeDescription
errorobject

Folder

A folder of documents. Synced; deleting one records a folder deletion. No counts or paths (build them from parent_id).

FieldTypeDescription
idULIDA record's ID.
namestringUnique among its siblings, ignoring case.
parent_idULID or nullThe folder it's in; null at the top level.
colorstringA key from the vocabulary's colors (e.g. teal).
iconstring or nullA Lucide icon name, or null for the default folder icon. May be one no longer in the vocabulary's picker_icons.
created_atdate-time
updated_atdate-time

FolderCount

FieldTypeDescription
folder_idULID or nullThe folder; null for the documents in no folder.
document_countinteger
byte_sizeintegerThe sum of these documents' PDFs' file.byte_size.

FolderResponse

FieldTypeDescription
dataFolderA folder of documents. Synced; deleting one records a folder deletion. No counts or paths (build them from parent_id).

KeyDate

A date that comes round every year. Synced; destroying one records a key_date deletion.

FieldTypeDescription
idULIDA record's ID.
kindKeyDateKind
labelstring or nullNames an other date ("Sobriety"), or adds to any other kind ("Wedding").
dayinteger
monthinteger
yearinteger or nullNull when unknown.
created_atdate-time
updated_atdate-time

KeyDateKind

birthday | anniversary | work_anniversary | first_met | name_day | memorial | other

Licence

FieldTypeDescription
statelicensed | trial | read_onlylicensed: a valid key covers this version. trial: the 14-day free trial. read_only: neither, so writes get 403 read_only.
problemrevoked | not_covered | nullWhy the stored key doesn't apply: revoked, or not_covered (this version came out after its updates_until). Null without a key, or when it applies.
licenseeLicensee or nullThe stored key's owner (even with a problem); null without a key.
key_idstring or nullThe stored key's ID, for support.
order_referencestring or nullThe order the key was sold with (the payment provider's reference), when it has one; null otherwise.
issued_ondate or null
updates_untildate or nullThe key covers every version released until then; Nifty keeps working after it.
trial_ends_atdate-timeThe end of the free trial, 14 days after first launch (in the past once it's ended).
trial_days_leftintegerWhole days left in the trial, rounded up; 0 once it's ended.
released_ondate or nullWhen this version was released; null in a development build.
onboardedbooleanThe welcome has been answered (or a key added).
updated_atdate-time

LicenceResponse

FieldTypeDescription
dataLicence

Licences

FieldTypeDescription
groupsobject[]In display order.
licencesobject[]

Licensee

FieldTypeDescription
namestring
emailstring

Me

FieldTypeDescription
namestring
usernamestringWhat the owner signs in with.
has_passwordbooleanWhether the owner has a password. The desktop app's owner starts without one, so can't sign in elsewhere until one is set (PUT /password).
time_zonestringThe owner's time zone, by its picker name, e.g. "London" or "Eastern Time (US & Canada)".
time_zone_ianastringThe same zone's IANA identifier, e.g. "Europe/London", for Intl and other time zone libraries.
todaydateToday's date in the owner's time zone.
tokenApiToken or nullThe token making the request; null under session auth.
csrf_tokenstring or nullUnder session auth, the session's current CSRF token for X-CSRF-Token (signing in again changes it); null with a bearer token.

MeResponse

FieldTypeDescription
dataMe

Note

FieldTypeDescription
idULIDA record's ID.
titlestring or null
namestringRead-only. What to call it in a list or a link, never blank. The title; without one, the body's first 60 characters (to a word, with mentions as @Name); else "Untitled note".
title_generatedbooleanRead-only. The title was written by AI (the note_titles task), which keeps it current as the note changes. Once a write changes or clears title, the title is the owner's and AI leaves it.
category_idULID or null
tag_idsULID[]Read-only, sorted. The tags in the body.
person_idsULID[]Read-only, sorted. The people mentioned in the body (their order is in body_html).
project_idsULID[]Read-only, sorted. The projects referenced in the body, deleted ones excluded.
body_htmlstringSee "Note bodies". "" when empty.
body_textstring
pinnedbooleanRead-only; change it with POST/DELETE /notes/{id}/pin.
pinned_atdate-time or nullRead-only. When it was pinned; null when it isn't.
edit_versionintegerRead-only. Goes up by one with each edited_at change; send it with an update to detect edits made elsewhere.
edited_atdate-timeRead-only. The last change to the title, body or category through a write.
created_atdate-time
updated_atdate-timeAlso changes when a tag in the body is renamed, merged or deleted, a mentioned person or referenced project is renamed, deleted or restored, the category is deleted, AI writes the title (which leaves edited_at and edit_version), or the note is pinned or unpinned (likewise).

NoteFields

A note's writable fields (NoteInput).

FieldTypeDescription
title optionalstring or nullSpaces are squished; blank is null. Send it only when the owner changed it: any change makes the title the owner's (title_generated false), and AI no longer touches it.
category_id optionalULID or nullAn unknown id is a 422 on category_id.
body_html optionalstring or nullSee "Note bodies". Null or "" clears it.
edit_version optionalintegerUpdates only (ignored on create). The note's edit_version these changes are based on; if it has moved on, the update is 409 conflict.

NoteResponse

FieldTypeDescription
dataNote

NoteSummary

A note in a list (GET /notes?fields=summary). As Note, without body_html and body_text.

FieldTypeDescription
idULIDA record's ID.
titlestring or null
namestringAs Note's.
title_generatedbooleanAs Note's.
category_idULID or null
tag_idsULID[]As Note's.
person_idsULID[]As Note's.
project_idsULID[]As Note's.
excerptstringThe body as one line (mentions "@Name", tags "#name", references "^Name", images left out), at most 240 characters, cut at a word with "...". "" when empty.
image_countintegerThe images in the body.
pinnedbooleanAs Note's.
pinned_atdate-time or nullAs Note's.
edit_versionintegerAs Note's.
edited_atdate-timeAs Note's.
created_atdate-time
updated_atdate-timeAs Note's.

PaginationMeta

FieldTypeDescription
next_cursorstring or nullPass as cursor for the next page; null on the last page.
limitinteger
total_count optionalintegerOnly with count=true. Every record in the filtered set, on every page.

Person

FieldTypeDescription
idULIDA record's ID.
namestring
avatarAvatar or null
key_datesKeyDate[]
email_addressesEmailAddress[]
phone_numbersPhoneNumber[]
social_profilesSocialProfile[]
positionsPosition[]Their jobs, in the order added. Change them with the person's PATCH; company_id names a /companies record.
relationshipsRelationshipKey[]Their relationships to the owner, in list order.
connectionsConnection[]Read-only. Their links to other people, by link id. Change them through /person_links.
created_atdate-time
updated_atdate-timeAlso changes when a key date, a contact detail, a position, the photo, a relationship or a connection changes.

PersonFields

A person's writable fields (PersonInput). Each array follows the rules on PATCH. A social profile's platform equal to the one currently detected for it is no change, so a GET sent back as a PATCH keeps it detected.

FieldTypeDescription
name optionalstring
avatar optionalstring or nullThe photo, saved with the rest: an upload's signed_id from POST /uploads, or null to remove it. Omitted keeps it. Only an upload nothing uses yet is accepted; any other signed id (e.g. a note's image, or an unknown one) is a 422 on avatar, "isn’t a new upload". The photo rules apply (a JPEG, PNG, WebP or GIF of 10 MB or less). Anything but a string or null is a 400. A replaced or removed photo is deleted.
relationships optionalRelationshipKeyInput[]The whole set of relationships to the owner. Omitted keeps them; [] clears them. An unknown key is a 422.
key_dates optionalobject[]A new row needs kind, day and month; the year is optional (1900 to this year, not in the future). label is required for other. A new row with no day, month, year or label is ignored. At most one birthday: to make another existing row the birthday, change the old birthday to another kind in an earlier request (in one request it can be refused, depending on the rows' order).
email_addresses optionalobject[]
phone_numbers optionalobject[]
social_profiles optionalobject[]
positions optionalobject[]A row with id changes it, one without adds, _destroy removes. Each needs a title or a company (a new row with neither is a 422 on title). The company changes when company_id or company_name is sent: company_id names a /companies record (an unknown one is a 422), company_name finds a company ignoring case or adds it, and null or a blank name clears it. Sending both non-null is a 422 on company_name. A company no position names any more is deleted (it appears in /deletions). An id sent twice in one request is a 422 on the later row.

"person_id is related_person_id's kind". Always stored one way: kind is a forward or symmetric role (parent, never child), and a symmetric link has the lower id in person_id. Creating, changing or removing a link also changes both people's updated_at.

FieldTypeDescription
idULIDA record's ID.
person_idULIDA record's ID.
kindPersonLinkRoleA role in a person link. Each inverse follows its forward role; the rest are symmetric.
related_person_idULIDA record's ID.
notestring or null
created_atdate-time
updated_atdate-time

PersonLinkResponse

FieldTypeDescription
dataPersonLink"person_id is related_person_id's kind". Always stored one way: kind is a forward or symmetric role (parent, never child), and a symmetric link has the lower id in person_id. Creating, changing or removing a link also changes both people's updated_at.

PersonLinkRole

A role in a person link. Each inverse follows its forward role; the rest are symmetric.

spouse | partner | ex_partner | sibling | step_sibling | cousin | sibling_in_law | parent | child | step_parent | step_child | guardian | ward | grandparent | grandchild | aunt_uncle | niece_nephew | parent_in_law | child_in_law | godparent | godchild | friend | acquaintance | housemate | neighbour | introduced | introduced_by | coworker | business_partner | manager | report | mentor | mentee | teacher | student | employer | employee | client | supplier | landlord | tenant

PersonResponse

FieldTypeDescription
dataPerson

PersonSummary

A person's name, photo and relationships to the owner, where a list shows them; GET /people/{id} has the rest.

FieldTypeDescription
idULIDA record's ID.
namestring
avatarAvatar or null
relationshipsRelationshipKey[]As Person's.

PhoneNumber

FieldTypeDescription
idULIDA record's ID.
numberstringAs typed.
labelstring or null
created_atdate-time
updated_atdate-time

Position

A job title, a company, or both (never neither). Synced; destroying one records a position deletion.

FieldTypeDescription
idULIDA record's ID.
titlestring or null
company_idULID or nullA /companies record; its name comes from there.
created_atdate-time
updated_atdate-time

Project

Members, role changes and member removals change the project's updated_at, as does a member's person being deleted or restored.

FieldTypeDescription
idULIDA record's ID.
namestringUnique among projects, ignoring case.
statusProjectStatusplanned, active and on_hold are open; done and cancelled are closed.
status_changed_atdate-time or nullWhen the status last changed (its latest status event); null if no change is recorded.
start_datedate or null
deadlinedate or null
my_rolestring or nullThe owner's role on the project.
external_referencestring or null
external_urluri or nullAn http or https link.
description_htmlstringText-only HTML (no attachments), sanitised as notes are. "" when empty.
description_textstring
membersobject[]Read-only, by id. The project's members who aren't deleted people; write them through /project_members.
created_atdate-time
updated_atdate-time

ProjectActivity

One entry of a project's activity. The record named by kind is set; the others are absent.

FieldTypeDescription
kindnote | task | document | event | created
atdate-timeA note's created_at, a task's completed_at, when a document was linked, an event's created_at, or the project's created_at.
note optionalNoteSummaryA note in a list (GET /notes?fields=summary). As Note, without body_html and body_text.
task optionalTaskEmbeds no other record's data (only ids), so renaming a list changes no task. Renaming a person, project or tag named in the description gives it a new updated_at (description_text changes), as does deleting or restoring its home (it leaves and rejoins the listings, with a deletion record), the expiry archiving it, another task's move renumbering it, or a document being linked or unlinked, or deleted, restored or purged while linked (has_documents).
document optionalDocumentA PDF. Synced; deleting one records a document deletion. Embeds no other record's data, only ids, so renaming a folder or a linked record changes no document. Linking or unlinking it, deleting or restoring a record it's linked to (or a list, person or project hiding a linked task), and deleting its folder while it's deleted give it a new updated_at. Notes, projects, tasks and people don't list their documents: filter GET /documents.
event optionalProjectEventA change to a project, never edited: updated_at is created_at until restoring its project (or a member event's person) gives it a new one. status: from and to are statuses. deadline: dates, from null when one was set and to null when it was removed. member_added and member_removed: person_id, and for member_added the role they were added with; from and to null.

ProjectEvent

A change to a project, never edited: updated_at is created_at until restoring its project (or a member event's person) gives it a new one. status: from and to are statuses. deadline: dates, from null when one was set and to null when it was removed. member_added and member_removed: person_id, and for member_added the role they were added with; from and to null.

FieldTypeDescription
idULIDA record's ID.
project_idULIDA record's ID.
kindstatus | deadline | member_added | member_removed
fromstring or nullA status key or a date (YYYY-MM-DD).
tostring or nullA status key or a date (YYYY-MM-DD).
person_idULID or null
rolestring or null
created_atdate-time
updated_atdate-time

ProjectMember

A person on a project, once each. Synced; removing one records a project_member deletion.

FieldTypeDescription
idULIDA record's ID.
project_idULIDA record's ID.
person_idULIDA record's ID.
rolestring or null
created_atdate-time
updated_atdate-time

ProjectMemberResponse

FieldTypeDescription
dataProjectMemberA person on a project, once each. Synced; removing one records a project_member deletion.

ProjectResponse

FieldTypeDescription
dataProjectMembers, role changes and member removals change the project's updated_at, as does a member's person being deleted or restored.

ProjectStatus

planned, active and on_hold are open; done and cancelled are closed.

planned | active | on_hold | done | cancelled

ProjectTaskCount

FieldTypeDescription
project_idULIDA record's ID.
openinteger
completedinteger
next_taskobject or null

ProjectWrite

FieldTypeDescription
name optionalstringSpaces are squished. A name another project has, ignoring case, is a 422.
status optionalProjectStatusplanned, active and on_hold are open; done and cancelled are closed.
start_date optionaldate or nullYYYY-MM-DD. One that isn't a date is a 422.
deadline optionaldate or nullYYYY-MM-DD; not before start_date (a 422).
my_role optionalstring or nullSpaces are squished; blank is null.
external_reference optionalstring or nullSpaces are squished; blank is null.
external_url optionalstring or nullhttp or https, with a host; without a scheme, https:// is added. Blank is null.
description_html optionalstring or nullHTML, sanitised as note bodies are. Attachments and images are dropped. A NUL or more than 1 MB is a 422. Null or "" clears it.

RelationshipKey

A relationship to the owner: any person link role except introduced and introduced_by (an introduction needs a third person), seen from the owner's side ("Ada is your mentee"). The family ones are spouse to godchild.

spouse | partner | ex_partner | sibling | step_sibling | cousin | sibling_in_law | parent | child | step_parent | step_child | guardian | ward | grandparent | grandchild | aunt_uncle | niece_nephew | parent_in_law | child_in_law | godparent | godchild | friend | acquaintance | housemate | neighbour | coworker | business_partner | manager | report | mentor | mentee | teacher | student | employer | employee | client | supplier | landlord | tenant

RelationshipKeyInput

A relationship key on input. The retired keys in_law and close_friend are still accepted as sibling_in_law and friend; responses only ever use the current keys. A blank one is ignored.

RelationshipKey or in_law | close_friend or

RelationshipTypes

FieldTypeDescription
relationshipsobject[]
person_linksobject[]
key_date_kindsobject[]A key date's kinds, in display order.
social_platformsobject[]A social profile's platforms, in display order.

SearchGroup

FieldTypeDescription
typeperson | project | note | task | document | task_list | folder
resultsSearchResult[]Best match first.
has_morebooleanThere are more matches than limit.

SearchResult

FieldTypeDescription
idULIDThe person's, project's, note's, task's, document's, task list's or folder's id.
titlestring or nullA person's, project's, document's, task list's or folder's name, a note's title (null for an untitled note), or a task's title.
subtitlestring or nullNull for a person. For a project, its status and, if it's open with a deadline, when it's due in the owner's time zone ("Active · due today", "Active · due tomorrow", "Active · due 12 Nov", "On hold · overdue", "Done"). For a note, the start of its text (at most 120 characters). For an open task, its home (a list's, person's or project's name, or "Inbox") and, with a deadline, when it's due ("Errands · due Friday", "Inbox · overdue by 2 days"); for a closed one, how and when it closed in the owner's time zone ("Completed 3 Oct", "Expired 3 Oct", "Won’t do 3 Oct"). For a document, its folder's path ("Home › Insurance"), "Unsorted" when it has no folder and no links, or null. For a task list, "List". For a folder, "Folder" at the top level, else "Folder · " and its parent's path ("Folder · Home › Insurance").
leadingobjectWhat the omnibar shows before the title: a person's photo (url is its thumbnail, or null without one), a colour swatch (a note's category colour, null without a category; a task list's or folder's colour) or a Lucide icon by name (projects, tasks, documents).

SocialProfile

FieldTypeDescription
idULIDA record's ID.
urluri
platformwebsite | linkedin | instagram | facebook | x | bluesky | mastodon | threads | github | youtube | tiktok | other
platform_detectedbooleanTrue when platform was worked out from the link rather than chosen.
labelstring or null
created_atdate-time
updated_atdate-time

System

FieldTypeDescription
versionstringThe running version; dev in a development build.
channelUpdateChannelstable (the default) gets stable releases; beta gets betas too, and stable releases newer than them.
update_checksbooleanWhether it checks daily (the owner's setting; false when managed).
update_checks_managedbooleanUpdates come from elsewhere (the desktop app, a package manager: --update-checks=off), so update_checks can't change.
update_checks_managed_bydesktop | nullWho manages updates: desktop when this is the desktop app's own server (--desktop-secret-stdin), whose updates come with the app; null otherwise.
plain_httpbooleanIt's reachable beyond this machine over plain http (no TLS).
updateSystemUpdate

SystemResponse

FieldTypeDescription
dataSystem

SystemUpdate

FieldTypeDescription
statusup_to_date | available | not_covered | unknown | offnot_covered: a newer release is out but this install's licence doesn't cover it (not_covered_reason), so it isn't offered.
not_covered_reasonupdates_ended | nullWith not_covered: updates_ended when the release came out after the licence's updates_until. Null otherwise. Revocation doesn't withhold updates: each release refuses the keys it lists (the licence's problem).
latest_released_ondate or nullWhen latest_version was released; null before any check.
can_checkbooleanThis build can check (it has a release signing key and a release version) and checks aren't managed.
latest_versionstring or nullThe channel's newest release at the last successful check; null before any check, or when the channel has no release yet (up_to_date).
notes_urluri or nulllatest_version's release notes (Markdown).
checked_atdate-time or nullThe last check's time, successful or not.
dismissedbooleandismissed_version is at least latest_version.
errorstring or nullWhy the last check failed; null after a successful one.

Tag

Shown with a leading #. The name keeps its casing; matching ignores case.

FieldTypeDescription
idULIDA record's ID.
namestringNo whitespace.
created_atdate-time
updated_atdate-time

TagResponse

FieldTypeDescription
dataTagShown with a leading #. The name keeps its casing; matching ignores case.

Task

Embeds no other record's data (only ids), so renaming a list changes no task. Renaming a person, project or tag named in the description gives it a new updated_at (description_text changes), as does deleting or restoring its home (it leaves and rejoins the listings, with a deletion record), the expiry archiving it, another task's move renumbering it, or a document being linked or unlinked, or deleted, restored or purged while linked (has_documents).

FieldTypeDescription
idULIDA record's ID.
titlestring
statusTaskStatusarchived is "Won't do", or expired: archived when its expires_on has passed.
start_ondate or null
deadline_ondate or null
expires_ondate or null
completed_atdate-time or nullSet while completed.
archived_atdate-time or nullSet while archived. It expired (rather than "Won't do") when this is the owner's midnight after expires_on.
task_list_idULID or nullThe home: at most one of task_list_id, person_id and project_id; none is the Inbox.
person_idULID or null
project_idULID or null
positionintegerIts home's manual order: sort by position, then id. Closed tasks keep theirs. Gaps and ties are possible, and it may be zero or negative.
description_htmlstringSee "Note bodies" (no images). "" when empty.
description_textstring
has_documentsbooleanA live document is linked to it (GET /documents?task_id=).
expiredbooleanArchived by its expiry rather than by hand ("Won't do"), in the owner's time zone.
created_atdate-time
updated_atdate-time

TaskCounts

FieldTypeDescription
inboxintegerIn the Inbox (inbox=true&status=open).
todayintegerStarted today or earlier, the Inbox too (view=today).
due_soonintegerOverdue or due within 14 days (view=due_soon).
overdueintegerDue before today.
task_listsobject[]Every live list, by position, with its open tasks.
page optionalobjectOnly when a page is named. Its keys, in the order the page shows them (labels and icons in the vocabulary's task_count_kinds): overview: open, overdue. today: open, completed_today. planned, one_day: open. logbook: completed, wont_do, expired. One home: open, completed (all-time).

TaskList

One of a task's homes. Synced; deleting one records task_list and task deletions.

FieldTypeDescription
idULIDA record's ID.
namestringUnique among lists, ignoring case.
colorstringA palette key from GET /category_choices (e.g. amber).
iconstring or nullA Lucide icon name, or null for the default list icon. May be one no longer in the picker.
positionintegerA sort key: order by position, then id. Gaps are possible after a delete.
created_atdate-time
updated_atdate-time

TaskListResponse

FieldTypeDescription
dataTaskListOne of a task's homes. Synced; deleting one records task_list and task deletions.

TaskResponse

FieldTypeDescription
dataTaskEmbeds no other record's data (only ids), so renaming a list changes no task. Renaming a person, project or tag named in the description gives it a new updated_at (description_text changes), as does deleting or restoring its home (it leaves and rejoins the listings, with a deletion record), the expiry archiving it, another task's move renumbering it, or a document being linked or unlinked, or deleted, restored or purged while linked (has_documents).

TaskStatus

archived is "Won't do", or expired: archived when its expires_on has passed.

open | completed | archived

TaskWrite

A home id that isn't an id, an unknown or deleted home, or two home ids at once (a 422 on base), are 422s.

FieldTypeDescription
title optionalstringSpaces are squished.
description_html optionalstring or nullSee "Note bodies": mentions, tags and project references by id. An image (signed-id) is a 422 on description. Null or "" clears it.
start_on optionaldate or nullYYYY-MM-DD. Today (owner's zone) or earlier puts it in view=today. One that isn't a date is a 422.
deadline_on optionaldate or nullNot before start_on (a 422), unless the deadline has already passed: an overdue task can start today.
expires_on optionaldate or nullNot before start_on or deadline_on, nor, on an open task, before today (each a 422). The task stays open through that day and is archived from the next, with archived_at that midnight in the owner's zone.
status optionalTaskStatusAny status can change to any other. completed sets completed_at, archived sets archived_at, open clears both, and reopening a task whose expires_on has passed clears it. Sending the current status changes nothing.
task_list_id optionalULID or nullThe home. Sending one home id clears the other two; all three null is the Inbox.
person_id optionalULID or null
project_id optionalULID or null
position optionalinteger1-based among the (new) home's open tasks; out-of-range values are clamped.
document_ids optionalULID[] or nullThe task's documents after the save: the full set, linked and unlinked in the save's transaction. Omitted leaves them as they are; null or [] unlinks them all. An unknown or deleted one is a 422 on documents, and nothing saves. Not an array of ids is a 400.
document_uploads optionalstring[] or nullsigned_ids of PDFs from POST /uploads, each becoming a document (named from its filename) linked to the task, in the save. One that isn't an unused PDF upload is a 422 on documents, and nothing saves.

Theme

system follows the device's light or dark setting. The default.

system | light | dark

Today

FieldTypeDescription
datedateToday in the owner's time zone.
tasks_todayintegerOpen, started today or earlier (view=today).
tasks_due_not_todayintegerOverdue or due within 14 days, not in today's (view=due_not_today).
tasks_inboxintegerOpen in the Inbox.
key_dates_in_fortnightintegerLive people's key dates falling from today to day 14.
deadlines_in_fortnightintegerOpen projects due from today to day 14.
overdue_deadlinesintegerOpen projects due before today.
notes_this_weekintegerNotes edited since the start of six days ago.
pinned_notesinteger

ULID

A record's ID.

string

UpcomingDeadline

FieldTypeDescription
datedateThe project's deadline.
overduebooleanThe deadline is before today.
projectProjectMembers, role changes and member removals change the project's updated_at, as does a member's person being deleted or restored.

UpcomingKeyDate

FieldTypeDescription
datedate
yearsinteger or nullThe years it marks (the age a birthday turns). Null without a year, or on the first one.
key_dateKeyDateA date that comes round every year. Synced; destroying one records a key_date deletion.
personPersonSummaryA person's name, photo and relationships to the owner, where a list shows them; GET /people/{id} has the rest.

UpdateChannel

stable (the default) gets stable releases; beta gets betas too, and stable releases newer than them.

stable | beta

Upload

FieldTypeDescription
signed_idstringThe signed-id to embed in a note body, or send in a task's document_uploads.
urluriAbsolute; redirects to the file. Anyone with the link can load it.
filenamestring
content_typeimage/jpeg | image/png | image/webp | image/gif | application/pdf
byte_sizeinteger
widthinteger or nullNull for a PDF.
heightinteger or null

UploadLimit

FieldTypeDescription
content_typesstring[]
max_bytesinteger

Vocabulary

relationships, person_links, key_date_kinds and social_platforms are as in RelationshipTypes.

any

WholeNumberInput

A whole number, or one written as a string ("5"); null or "" is none.

integer or null or string

Menu

2026.10.1-beta.1Contact support