Skip to content
Niftyhelp 2026.10.2 Support

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.
reply_timeout_secondsinteger or nullHow long the provider may take to answer each call that writes something (a title, a summary, a document's, image's or note's reading). Each call waits the longer of this and its own standard limit (90 seconds, or 5 minutes for a document, image or note). Null: the standard limits. Checks and model lists keep 90 seconds.
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
scopefull | readfull may read and change anything a token may; read may only read (GET, HEAD and POST /mcp).
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.
text_sizeTextSizeThe interface's text size; medium is the default.
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

BackupReason

Why it was made; the words are the vocabulary's backup_reasons.

before_update | before_restore | manual | scheduled

CalendarAlert

FieldTypeDescription
alert_atdate-timeWhen to alert.
minutesintegerMinutes before the event starts: its feed's alert_minutes.
eventCalendarEventOne occurrence of a feed's event (a repeating event gives one per instance), or one of the owner's own events (entry_id set, feed_id null: edit it through /calendar_entries). Otherwise read only.

CalendarAlertSound

For calendar alerts. music_box is the default; none is silent.

arpeggio | music_box | door_knock | window_knock | none

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.

CalendarEntry

One of the owner's own events, on My Nifty Calendar: a single day, all day or from a start to an end time. Synced; deleting one records a calendar_entry deletion. GET /calendar shows it as a CalendarEvent with entry_id set.

FieldTypeDescription
type_keyEventTypeKeyA key from event_types, or null for No type. On creation, omission assigns a type once, from the owner's rules (/calendar_type_rules) and then deterministic ones; while it has no type, a rule added or changed later may give it one. Sending it, even null, is the owner's choice, which no rule changes. On update, omission preserves the saved type.
received_via_apiReceivedViaAPI or nullHow it came: through the Send to Nifty API (GET /send_api), or null.
idULIDA record's ID.
titlestring
datedateThe day (in time_zone when timed).
all_dayboolean
start_timestring or nullHH:MM in time_zone; null when all day.
end_timestring or nullHH:MM in time_zone; null when all day.
time_zonestring or nullAn IANA zone; null when all day.
starts_atdate-time or nullThe start as an instant; null when all day.
ends_atdate-time or nullThe end as an instant; null when all day.
locationstring or null
notesstring or nullPlain text.
created_atdate-time
updated_atdate-time

CalendarEntryResponse

FieldTypeDescription
dataCalendarEntryOne of the owner's own events, on My Nifty Calendar: a single day, all day or from a start to an end time. Synced; deleting one records a calendar_entry deletion. GET /calendar shows it as a CalendarEvent with entry_id set.

CalendarEvent

One occurrence of a feed's event (a repeating event gives one per instance), or one of the owner's own events (entry_id set, feed_id null: edit it through /calendar_entries). Otherwise read only.

FieldTypeDescription
type_keyEventTypeKeyA key from event_types, or null for No type. On creation, omission assigns a type once, from the owner's rules (/calendar_type_rules) and then deterministic ones; while it has no type, a rule added or changed later may give it one. Sending it, even null, is the owner's choice, which no rule changes. On update, omission preserves the saved type.
received_via_apiReceivedViaAPI or nullAn own event (entry_id) the Send to Nifty API added; null otherwise.
keystringOpaque; the same for this occurrence across syncs.
link_keystringOpaque; what notes link to (Note.event.link_key, GET /notes?event=). An own event's is its entry_id. A feed's is the same across syncs and, for an event that doesn't repeat, even when it moves; for a repeating one it names this occurrence.
feed_idULID or nullThe feed it's from; null for the owner's own events (My Nifty Calendar).
entry_idULID or nullThe owner's own event (CalendarEntry.id); null for a feed's.
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.
repeatsbooleanOne of a repeating event's occurrences: by a rule (rrule) or by dates alone (RDATE, rrule null). False for the owner's own.
series_keystring or nullOpaque; the same for every occurrence of a repeating event (repeats), moved ones too, and apart from other feeds' events; null when it doesn't repeat, and for the owner's own events. Groups a week's repeats.
ignoredevent | repeats | nullIgnored (/calendar/ignored_events): this occurrence (event) or every occurrence of its event (repeats, when both apply); null when not. Only GET /calendar and a note's linked event give an ignored one.

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.
alert_minutesinteger or nullMinutes before its timed events start that the desktop app alerts (0: as they start); null when off. See GET /calendar/alerts.
hidden_from_todaybooleanIts events stay off Today, This week and Next week (and the today tool); Calendar still shows them.
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

CalendarTypeRule

One of the owner's rules for an event's type.

FieldTypeDescription
idULIDA record's ID.
type_keyRuleTypeKeyA key from event_types, or null for No type (Nifty's own rules then don't type the event). Null on create unless sent.
conditionsCalendarTypeRuleCondition[]All must match, in no particular sense of order.
positionintegerA sort key: order by position, then id. Gaps are possible after a delete.
created_atdate-time
updated_atdate-time

CalendarTypeRuleAttendeeCountCondition

How many take part: the organizer and each guest once, not rooms or resources (so the owner, when on the invite). An event listing nobody, and the owner's own, count 1.

FieldTypeDescription
kindattendee_count
comparisonat_least | at_most | exactly
countinteger

CalendarTypeRuleCalendarCondition

The event is on this calendar. At most one per rule.

FieldTypeDescription
kindcalendar
feed_idULID or nullA feed's id, or null for My Nifty Calendar.

CalendarTypeRuleCondition

One test of an event. Text is compared ignoring case, accents and repeated spaces: name_contains, location_contains and attendee_email_contains match it anywhere, name_equals the whole name.

CalendarTypeRuleTextCondition or CalendarTypeRuleAttendeeCountCondition or CalendarTypeRuleStartsBetweenCondition or CalendarTypeRuleCalendarCondition

CalendarTypeRuleResponse

FieldTypeDescription
dataCalendarTypeRuleOne of the owner's rules for an event's type.

CalendarTypeRuleSaved

FieldTypeDescription
dataCalendarTypeRuleOne of the owner's rules for an event's type.
metaobject

CalendarTypeRuleStartsBetweenCondition

The event starts at or after from and before to, in the owner's time zone; from after to runs past midnight (22:00 to 02:00). An all-day event never matches.

FieldTypeDescription
kindstarts_between
fromstring
tostringNot the same as from.

CalendarTypeRuleTextCondition

The event's name, location or an attendee's email address (never their name) has text.

FieldTypeDescription
kindname_contains | name_equals | location_contains | attendee_email_contains
textstringSpaces are squished; blank is a 422.

CalendarView

The view the Calendar opens in: day (the default) or week.

day | week

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.

Cover

A record's header: a colour (a cover_colors key in the vocabulary: a gradient or a solid; render each from your own palette, with a dark-mode version) or a photo the owner uploaded (PUT /projects/{id}/cover_photo), shown framed position percent down.

FieldTypeDescription
kindcolor | photo
colorstring or nullA cover_colors key (kind color).
photoCoverPhoto or null
positionintegerHow far down a photo is framed: 0 its top, 100 its foot.

CoverPhoto

A cover's uploaded photo. Its URLs are public but unguessable, as uploads' are.

FieldTypeDescription
urluriFitted within 2400×1600 (WebP): for a header.
preview_urluriFitted within 1024×768 (WebP): for a card.
thumb_urluriA 128px square (WebP): for a tile.
widthintegerThe uploaded image's width.
heightinteger
creditUnsplashCredit or nullWho took a photo from Unsplash, to show with it; null for the owner's own.

CoverWrite

A cover to set. Every project wears one, so null is a 422 on cover. Kind color needs a color; kind photo keeps the photo the cover has (upload a new one with PUT /projects/{id}/cover_photo), so it's for moving position. An unknown colour, a photo when there's none, or a position out of range is a 422 on cover.<field>. A project created without one gets one of the colours its projects use least, at random. A photo a colour replaces is deleted.

FieldTypeDescription
kindcolor | photo
color optionalstringA cover_colors key (kind color).
position optionalintegerDefault: the cover's own, else 50.

CreatedSound

Played when a task, person or project is created. blip_blip is the default; none is silent.

blip_blip | pop_drop | shimmer | kalimba_pair | none

DeletedSound

Played when something is deleted, removed, revoked or disconnected. paper_away is the default; none is silent.

knock_away | falling | bloop | paper_away | none

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, an image (kind: image: a screenshot or a photo, its text read by OCR), or an email (kind: email, POST /email_imports) with its PDF attachments inside it. 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
received_via_apiReceivedViaAPI or nullHow it came: through the Send to Nifty API (GET /send_api), or null.
idULIDA record's ID.
kindpdf | email | image
namestring
dated_ondateIts date: when it was written, sent or received, as against created_at. The owner's choice when dated_on_set; else an email's (or an email's attachment's) sent date, else the date the Document summaries AI task read from it, else the day it was added. A sent or added date is the day in the owner's time zone.
dated_on_setbooleanThe owner chose dated_on.
folder_idULID or nullAn attachment's is its email's.
email_idULID or nullThe email this PDF was attached to. It lives inside the email, which moves and deletes it too.
emailEmailDetails or nullAn email's headers and attachments; null for a PDF.
from_emailEmailOrigin or nullA PDF added from an email that wasn't kept (it had nothing to say), with who sent it and when.
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
analysisDocumentAnalysisStateWhere the document's text and analysis are (GET /documents/{id}/analysis has the rest). Each change gives the document a new updated_at.
created_atdate-time
updated_atdate-time

DocumentAnalysis

A document's analysis: what the PDF says of itself, how much text was read (an image's by OCR), and the Document summaries AI task's result. facts are the fields every type may have; fields the type's own. Both list every field in order, with null values for what the document doesn't state. The summary is Markdown written by a model: render it without HTML, links or images.

FieldTypeDescription
statusreading | no_text | unreadable | not_analysed | pending | done | failed
errorstring or nullWhy the last try failed (failed only).
typestring or null
type_labelstring or null
summarystring or nullMarkdown.
factsDocumentField[]
fieldsDocumentField[]
modelstring or nullThe name of the model that wrote it.
analysed_atdate-time or null
pages_analysedinteger or nullWhen the model was given only part of the document (a long one, or a model with a small context): how many pages, from the first. Null when it read all of it.
imageDocumentImageProcessing or nullAn image's reading by the Image processing AI task; null for anything else, or an image it hasn't read.
pdfobjectThe PDF's own information, where it has it (all null for an image).
textobject

DocumentAnalysisResponse

FieldTypeDescription
dataDocumentAnalysisA document's analysis: what the PDF says of itself, how much text was read (an image's by OCR), and the Document summaries AI task's result. facts are the fields every type may have; fields the type's own. Both list every field in order, with null values for what the document doesn't state. The summary is Markdown written by a model: render it without HTML, links or images.

DocumentAnalysisState

Where the document's text and analysis are (GET /documents/{id}/analysis has the rest). Each change gives the document a new updated_at.

FieldTypeDescription
statusreading | no_text | unreadable | not_analysed | pending | done | failedreading: the text is still to be read, shortly after the upload. no_text: it has no text to read (a scanned PDF, or an image without words). unreadable: it can't be read (encrypted or broken). not_analysed: it has text but no analysis (the Document summaries AI task is off, or was when it was read). pending: queued or under way; an earlier result, if any, stays until it's replaced. done: analysed. failed: the last try failed.
typestring or nullThe document type's key, e.g. energy_bill; null until analysed.
type_labelstring or null

DocumentField

One extracted value. value by kind: text and enum a string, date "YYYY-MM-DD", money { minor, currency } (an integer in the currency's minor unit, and its ISO code), number a number in unit, bool a boolean, list an array of objects keyed by columns' keys. Null when not stated.

FieldTypeDescription
keystring
labelstring
kindtext | date | money | number | enum | bool | list
unitstring or null
valueanySee kind; null when not stated.
columns optionalobject[]A list's item fields (list only).

DocumentImageProcessing

What the Image processing AI task made of an image, while it's on: it reads the picture with a model that can see it. done: its transcription is the document's text (text), it may have named the image, and description says what it shows. While pending, the document's analysis is reading. failed: the text OCR read is used.

FieldTypeDescription
statuspending | done | failed
descriptionstring or null
modelstring or nullThe name of the model that read it.
errorstring or nullWhy it failed (failed only).

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, an image (kind: image: a screenshot or a photo, its text read by OCR), or an email (kind: email, POST /email_imports) with its PDF attachments inside it. 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.

DocumentText

FieldTypeDescription
textstringAt most 200,000 characters; a PDF's pages each after a --- Page N --- line.
truncatedbooleanPages or characters were left out.
read_bypdf | ocr | model | email | nullWhat read it: the PDF's own text, Nifty's OCR, the Image processing task's model, or an email's body. Null until it's read.
ocr_textstring or nullThe text Nifty's OCR read, where the model's reading is text (read_by: model), even when they agree.

DocumentTextResponse

FieldTypeDescription
dataDocumentText

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 or project counts as deleted.
person_ids optionalULID[] or null
dated_on optionaldate or nullYYYY-MM-DD: the owner's choice, which nothing else replaces. Null goes back to Nifty's choice. One that isn't a date is a 422.

EmailAddress

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

EmailAttachment

FieldTypeDescription
filenamestring
content_typestring
byte_sizeinteger
statussaved | removed | not_savedsaved: a document inside the email (document_id). removed: it was, and was deleted. not_saved: not a PDF, so not kept.
document_idULID or nullThe document it became (saved only).

EmailDetails

An email's headers, from the original when it was forwarded. Its body is body_url's page; its text is the document's text (search, summaries and the people it names read it, with its attachments').

FieldTypeDescription
subjectstring or null
fromEmailParty or null
toEmailParty[]
ccEmailParty[]
sent_atdate-time or null
forwardedbooleanIt was forwarded; this is the original it forwards.
forward_notestring or nullWhat the forwarder wrote above the forward.
forwarded_atdate-time or nullWhen it reached Nifty by email forwarding (GET /email_forwarding); null when it was imported as a file.
has_htmlbooleanIts body is HTML (else plain text).
remote_imagesbooleanIts HTML loads images from elsewhere, which body_url blocks unless asked.
body_urluriGET /documents/{id}/email_body: absolute, and needs the token.
attachmentsEmailAttachment[]Every attachment, in the email's order.

EmailForwarding

FieldTypeDescription
availablebooleanPlus is available (GET /plus): the address accepts email, and it and the senders can be changed.
unavailable_reasonnot_connected | inactive | read_only | nullAs GET /plus's. Emails that arrived before the subscription ended are still collected while inactive.
addressstring or nullWhere to forward emails; null until Plus first makes it.
sendersobject
waitingintegerEmails waiting to be collected at the last check (at most 30: more are refused).
errorunreachable | nullunreachable: the forwarding service couldn't be reached at the last check; the rest is as last known.
checked_atdate-time or nullWhen the forwarding service last answered.
collected_atdate-time or nullWhen an email was last collected.
lostintegerEmails let go because they were sealed for another copy of Nifty (before Plus moved here), since last dismissed.
unreadableintegerEmails let go because they couldn't be read as emails, since last dismissed.

EmailForwardingResponse

FieldTypeDescription
dataEmailForwarding

EmailImportResponse

FieldTypeDescription
dataobject

EmailOrigin

FieldTypeDescription
subjectstring or null
fromEmailParty or null
sent_atdate-time or null
forwarded_atdate-time or nullWhen it reached Nifty by email forwarding; null when it was imported as a file.

EmailParty

FieldTypeDescription
namestring or null
addressstring or null
person_idULID or nullThe one live person with this address, matched as it's read (so never stale); else null.

Error

FieldTypeDescription
errorobject

ErrorReportFrame

FieldTypeDescription
functionstringBlank when unknown.
filestringA path or URL; only a URL's path is kept.
lineinteger0 when unknown.
columninteger0 when unknown.

EventTypeKey

A key from event_types, or null for No type. On creation, omission assigns a type once, from the owner's rules (/calendar_type_rules) and then deterministic ones; while it has no type, a rule added or changed later may give it one. Sending it, even null, is the owner's choice, which no rule changes. On update, omission preserves the saved type.

string or null

Fact

What you know about a person under one fact label: at most one fact per person and label. Synced; deleting one, its label or its person records a fact deletion (undoing the person's delete removes it).

FieldTypeDescription
idULIDA record's ID.
person_idULIDA record's ID.
label_idULIDA record's ID.
textstring
edited_atdate-timeRead-only. The last change to the text or label: when the fact was last updated, to show.
created_atdate-time
updated_atdate-timeFor sync. Also changes when the person's delete is undone.

FactLabel

What a fact is about, shared by every person. Synced; deleting one records a fact_label deletion.

FieldTypeDescription
idULIDA record's ID.
namestring
iconstring or nullA Lucide icon name, or null for none. 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

FactLabelCount

FieldTypeDescription
fact_label_idULIDA record's ID.
fact_countinteger

FactLabelResponse

FieldTypeDescription
dataFactLabelWhat a fact is about, shared by every person. Synced; deleting one records a fact_label deletion.

FactResponse

FieldTypeDescription
dataFactWhat you know about a person under one fact label: at most one fact per person and label. Synced; deleting one, its label or its person records a fact deletion (undoing the person's delete removes it).

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' and their attachments' 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).

GettingStarted

FieldTypeDescription
startedobjectWhether each area has anything in it yet, deleted things aside.
hiddenGettingStartedTip[]The tips the owner has hidden.

GettingStartedResponse

FieldTypeDescription
dataGettingStarted

GettingStartedTip

A getting-started tip: today, Today's welcome; calendar, Calendar's card.

today | calendar

HiddenCalendars

What the Calendar and Today's Meeting leave out: calendar feeds by id, nifty (My Nifty Calendar) and the kinds of Nifty's own dates (tasks, project_dates, key_dates). Sorted. None by default.

string[]

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

LibrarySort

How a Library place sorts. By name, A to Z, is the default.

FieldTypeDescription
byname | date | size
descendingboolean

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
person_idULID or nullThe owner's own person (is_me). Change the name and time zone there (PATCH /people/{id}). Null only before setup.
namestringThe owner's person's name.
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); a server's has none from setup until the welcome's Signing in step sets one.
welcomedbooleanWhether the owner has finished the app's welcome (POST /welcome). Until then the app shows it in place of everything else.
time_zonestringThe owner's time zone, by its picker name, e.g. "London" or "Eastern Time (US & Canada)", for their person's time_zone.
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.
two_factorbooleanWhether sign-in asks for a code from an authenticator app (any in GET /authenticators).
password_sign_inbooleanWhether this server takes a password at sign-in. False on the desktop app's own server, where only the app signs in (so the password, username, authenticators and signing out don't apply).

MeResponse

FieldTypeDescription
dataMe

NiftyCalendar

The settings of My Nifty Calendar, the built-in calendar of the owner's own events. Not synced.

FieldTypeDescription
colorstringA key from the vocabulary's colors.
hidden_from_todaybooleanIts events stay off Today, This week and Next week (and the today tool); Calendar still shows them.
updated_atdate-time

NiftyCalendarResponse

FieldTypeDescription
dataNiftyCalendarThe settings of My Nifty Calendar, the built-in calendar of the owner's own events. Not synced.

Note

FieldTypeDescription
received_via_apiReceivedViaAPI or nullHow it came: through the Send to Nifty API (GET /send_api), or null.
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
moodstring or nullHow the owner felt when writing it, a key from the vocabulary's moods; null when none.
kindstring or nullIts type, a key from the vocabulary's note_kinds (1-to-1, meeting, journal…); null when it has none. The owner chooses it, or a linked event gives it (one attendee besides the owner a one_to_one, more a meeting), or AI does with the title (the note_titles task). Keys are only ever added.
kind_sourcestring or nullRead-only. Who set kind: owner (a write; with kind null, the owner chose no type), event (a linked event) or ai; null when nobody has. The owner's choice is never replaced; an event's replaces AI's.
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.
eventNoteEvent or nullRead-only (PUT/DELETE /notes/{id}/event, or event on create). The calendar event it's about; null when none.
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, category, mood or type 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 or chooses the type, a linked event gives the type (each of which leaves edited_at and edit_version), or the note is pinned or unpinned, or its event linked or unlinked (likewise).

NoteAnalysis

What the Note insights AI task read from a note. status: off, the task is off (or has no model) and the note hasn't been read; too_short, the note is too short to read; not_read, it hasn't been read yet; queued, it waits to be read (run_at: once edits settle, or now); reading, it's being read; read; or failed, the last reading failed (error). While queued or reading, what was read before stays. stale: the note changed since it was read. The summary and each insight's text are written by a model: render them without HTML, links or images.

FieldTypeDescription
statusoff | too_short | not_read | queued | reading | read | failed
enabledbooleanNote insights is on, with a model: the note can be read (again).
run_atdate-time or nullWhen a queued reading runs.
staleboolean
read_atdate-time or nullWhen the insights were last read.
modelstring or nullThe name of the model that read them.
versionstring or nullThe version of the reading instructions.
truncatedbooleanOnly the start of a long note was sent.
errorstring or nullWhy the last reading failed.
summaryNoteAnalysisSummary or null
summary_removedbooleanThe owner removed the summary (DELETE /notes/{id}/summary): readings don't write one until they ask (POST /notes/{id}/analyze).
insightsNoteInsight[]

NoteAnalysisResponse

FieldTypeDescription
dataNoteAnalysisWhat the Note insights AI task read from a note. status: off, the task is off (or has no model) and the note hasn't been read; too_short, the note is too short to read; not_read, it hasn't been read yet; queued, it waits to be read (run_at: once edits settle, or now); reading, it's being read; read; or failed, the last reading failed (error). While queued or reading, what was read before stays. stale: the note changed since it was read. The summary and each insight's text are written by a model: render them without HTML, links or images.

NoteAnalysisSummary

A long note's summary. skipped: the note is too short for one (markdown null); failed: the last try failed (error; an earlier summary isn't kept).

FieldTypeDescription
statusread | failed | skipped
markdownstring or nullMarkdown bullet points.
modelstring or null
read_atdate-time or null
errorstring or null

NoteEvent

The calendar event a note is about: one of the owner's own (entry_id) or one occurrence of a feed's (feed_id). It stays when the event goes (deleted, gone from its feed, hidden, or its feed removed), naming what was linked; GET /notes/{id}/event says whether it's still there.

FieldTypeDescription
link_keystringThe event's CalendarEvent.link_key.
entry_idULID or nullOne of the owner's own events; null for a feed's.
feed_idULID or nullThe feed of a feed's event (which may have been removed since); null for an own one.
titlestringThe event's title when it was linked; blank when it had none.
all_daybooleanAs when it was linked.
starts_atdate-time or nullWhen it started, as when it was linked; null when all day.
start_ondateThe day it started in the owner's time zone, as when it was linked.
linked_atdate-time

NoteEventInput

A calendar event to link a note to, as GET /calendar gives it: an own event's entry_id, or a feed's occurrence by its feed_id, key and date (the day it starts in the owner's time zone). A repeating event links that one occurrence. One that isn't an event (an unknown or deleted entry, or no such occurrence that day), or one naming both kinds, is a 422 on event.

FieldTypeDescription
entry_id optionalULIDA record's ID.
feed_id optionalULIDA record's ID.
key optionalstringThe occurrence's CalendarEvent.key.
date optionaldate

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.
mood optionalstring or nullA key from the vocabulary's moods; null clears it. Anything else is a 422 on mood.
kind optionalstring or nullA key from the vocabulary's note_kinds; null is no type. Anything else is a 422 on kind. Send it only when the owner chose it: it's theirs from then on (kind_source owner), even null, so neither an event nor AI types the note again. Left out, the type stays as it is.
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.
event optionalNoteEventInputCreate only (an update with it is a 422 on event; use PUT /notes/{id}/event). Links the new note to this calendar event, in the same save.

NoteInsight

One thing the note says that's worth remembering, resting on the words in quote (the note holds them). Dates are the owner's days: when it happens (event_on, to event_until), and when it's worth raising again (check_on). lifespan: lasting (a fact), until_date (it matters until its dates pass) or fades (current context). An insight keeps its id and first_seen_at while later readings find it again (the same kind and quote). The owner's corrections (not_right, their wording, links added or removed) stay with it through later readings. One marked not_right is wrong: apart from checking insights, nothing should use it.

FieldTypeDescription
idintegerLocal to this install.
kindstringA key from the vocabulary's insight_kinds.
textstringOne sentence; "you" is the owner.
quotestring
openbooleanStill to be done
event_ondate or null
event_untildate or null
check_ondate or null
lifespanlasting | until_date | fades
first_seen_atdate-time
not_rightbooleanThe owner marked it as not right.
editedbooleantext is the owner's wording.
subjectsNoteInsightSubject[]

NoteInsightChoice

A person an unmatched name could be.

FieldTypeDescription
idULIDA record's ID.
namestring

NoteInsightSubject

What an insight is about: a person, project, task or company (id; null once it's gone for good), the note's event, or a name Nifty couldn't match to anyone. name is the record's current name, else the name it had. A name that could be several people lists them in choices and isn't matched. A task is either what the insight is about (about) or the same promise (same). matched_by says how Nifty found the record in the note, for checking its matching: me, mention, attendee, full_name, email, alias, first_name, shared_first_name, task, project_mention, name, position, linked, event, or owner for a link the owner added (more may come).

FieldTypeDescription
typeperson | project | task | company | event | name
idULID or null
namestring
deletedbooleanThe record has been deleted.
task_relationabout | same | null
matched_bystring or null
choicesNoteInsightChoice[]

NoteResponse

FieldTypeDescription
dataNote

NoteSummary

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

FieldTypeDescription
idULIDA record's ID.
titlestring or null
namestringAs Note's.
title_generatedbooleanAs Note's.
category_idULID or null
moodstring or nullAs Note's.
kindstring or nullAs Note's.
kind_sourcestring or nullAs Note's.
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.

Now

FieldTypeDescription
taskTaskEmbeds 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, a document being linked or unlinked, or deleted, restored or purged while linked (has_documents, document_ids), or a note being attached or detached, or deleted or restored while attached (note_ids).
sincedate-time
stops_atdate-time or nullWhen it will stop by itself, if nothing else stops it first.

NowResponse

FieldTypeDescription
dataNow or null

NowStopTimes

Times of day (HH:MM, the owner's time zone) at which Now stops by itself, earliest first. No duplicates (a 422).

string[]

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.

PeopleArrange

How People lays out faces: A to Z (az, the default) or under how they relate to you (groups).

az | groups

PeopleShow

Which of People's groups shows: all (the default), a relationship_groups key from the vocabulary, or others, everyone in none.

string

Person

FieldTypeDescription
idULIDA record's ID.
namestring
aliasesstring[]Other names you call them by ("Mum", "Spud"), in the order given. Search and mentions find them by these too.
is_mebooleanRead-only. Whether this is you, the owner. Exactly one person is.
time_zonestring or nullTheir time zone, an IANA zone from the time zone list (Europe/London). Null: yours. Yours is always set, and is the app's: it decides "today".
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.
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 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
aliases optionalstring[]Replaces their aliases. Spaces are squished; blank ones, and repeats ignoring case and accents, are dropped. More than 10 is a 422 on aliases; one over 50 characters, or with a comma, a 422 on aliases[i]. Anything but an array of strings (null among them) is a 400.
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.
time_zone optionalstring or nullAn IANA zone from the time zone list (Europe/London), or null for none. Anything else is a 422, as is null for you (is_me).
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 and photo, where a list shows them; GET /people/{id} has the rest.

FieldTypeDescription
idULIDA record's ID.
namestring
avatarAvatar or null

PhoneNumber

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

Plus

FieldTypeDescription
statenot_connected | connected | moved | copiednot_connected: never connected, or disconnected here. connected: linked to a subscription. moved: Plus was moved to another install. copied: this install's data was found in two places, so the account service disconnected both; connect again.
availablebooleanPlus features can be used now. Connected, the subscription active or past due, and Nifty not read-only.
unavailable_reasonnot_connected | inactive | read_only | nullWhy available is false: not_connected (any state but connected), inactive (the subscription isn't active), or read_only (Nifty is read-only; the subscription is still charged). Null when available.
install_namestring or nullThe name this install has on the account (for example “Nifty on Ada's MacBook”); null when not connected.
account_urluriThe account page's way to a code: sign in, subscribe, and get a code to connect with.
accountPlusAccount or nullThe account and subscription as last checked; null unless connected.
errorunreachable | nullThe last problem: unreachable (the account service couldn't be reached at the last check; the rest is as last known). Null when none.
checked_atdate-time or nullWhen the account service last answered.

PlusAccount

FieldTypeDescription
emailstring
statusactive | past_due | inactiveactive. past_due: a payment failed and Stripe is retrying; Plus still works. inactive: no current subscription.
planPlusPlan or null
period_enddate-time or nullWhen the current period ends; the subscription renews then unless cancel_at_period_end.
cancel_at_period_endboolean

PlusPlan

monthly or yearly.

monthly | yearly

PlusResponse

FieldTypeDescription
dataPlus

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
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
coverCover or nullThe project's header. Every project has one; null only when its photo's upload is missing.
membersobject[]Read-only, by id. The project's members who aren't deleted people, you (is_me) among them when you're on it, with your role; write them through /project_members.
pinnedbooleanPinned for quick access. Set through /projects/{id}/pin.
pinned_atdate-time or nullWhen it was pinned (the menu's order); null when it isn't.
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 | task_change | document | event | created
atdate-timeA note's created_at, a task's completed_at, when a task was added or removed, 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, body_text and event.
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, a document being linked or unlinked, or deleted, restored or purged while linked (has_documents, document_ids), or a note being attached or detached, or deleted or restored while attached (note_ids).
task_change optionalProjectTaskChangeA task added to the project (made there, moved in, or restored) or removed from it (moved out, or deleted). A change reversed within 10 minutes (a delete undone, a slip) is dropped instead of recorded.
document optionalDocumentA PDF, an image (kind: image: a screenshot or a photo, its text read by OCR), or an email (kind: email, POST /email_imports) with its PDF attachments inside it. 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

ProjectLastActivity

FieldTypeDescription
project_idULIDA record's ID.
last_activity_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.

ProjectsOrder

How Projects orders its sections: by deadline (the default), name, or newest first by when each was created or its latest activity.

deadline | name | created | activity

ProjectStatus

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

planned | active | on_hold | done | cancelled

ProjectTaskChange

A task added to the project (made there, moved in, or restored) or removed from it (moved out, or deleted). A change reversed within 10 minutes (a delete undone, a slip) is dropped instead of recorded.

FieldTypeDescription
idULIDA record's ID.
changeadded | removed
task_idULIDA record's ID.
titlestringThe task's title at the time.

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).
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.
cover optionalCoverWriteA cover to set. Every project wears one, so null is a 422 on cover. Kind color needs a color; kind photo keeps the photo the cover has (upload a new one with PUT /projects/{id}/cover_photo), so it's for moving position. An unknown colour, a photo when there's none, or a position out of range is a 422 on cover.<field>. A project created without one gets one of the colours its projects use least, at random. A photo a colour replaces is deleted.

ReceivedViaAPI

A record the Send to Nifty API added (GET /send_api), shown in its details as "Received".

FieldTypeDescription
atdate-timeWhen it reached Nifty Plus.
sourcestring or nullThe sender's label for itself, if it gave one.

RelationshipKey

Deprecated: how someone relates to you is now a person link to you. A role someone can have to you: any person link role except introduced and introduced_by (an introduction needs a third person), seen from your 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

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.

RuleTypeKey

A key from event_types, or null for No type (Nifty's own rules then don't type the event). Null on create unless sent.

string or null

SearchGroup

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

SearchLeadingAvatar

A search result's person photo.

FieldTypeDescription
type"avatar"
urluri or null

SearchLeadingIcon

A search result's Lucide icon.

FieldTypeDescription
type"icon"
namestring

SearchLeadingSwatch

A search result's colour swatch.

FieldTypeDescription
type"swatch"
colorstring or nullA colour key, e.g. "jade".

SearchResult

FieldTypeDescription
idstringThe person's, project's, note's, task's, document's, task list's, folder's or company's id (a ULID); an event's key.
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), a task's or event'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"). For an event, its day in the owner's time zone (with the year unless it's this year's), its times or "All day", and its calendar's name ("Tue 7 Oct · 10:00–11:00 · Work"); an event with no title is titled "(No title)". With scope=link, a note's and document's are as described there.
event optionalCalendarEventAn event's occurrence, as GET /calendar gives it; absent for other types.
leadingSearchLeadingAvatar or SearchLeadingSwatch or SearchLeadingIconWhat 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, folder's or event's calendar's colour) or a Lucide icon by name (projects, tasks, documents).

SendAPI

FieldTypeDescription
availablebooleanPlus is available (GET /plus): deposits are accepted, and a token can be made.
unavailable_reasonnot_connected | inactive | read_only | nullAs GET /plus's. Items that arrived before the subscription ended are still collected while inactive.
urlstring or nullWhere the API is, for the help's examples; null until the service has said.
tokensSendAPIToken[]The tokens, oldest first, without the tokens themselves (shown only when each is made): as the service last listed them.
waitingintegerItems waiting to be collected at the last check.
errorunreachable | nullunreachable: the service couldn't be reached at the last check; the rest is as last known.
checked_atdate-time or nullWhen the service last answered.
collected_atdate-time or nullWhen an item was last collected.
skippedintegerItems Nifty couldn't add (one failing its checks, or failing 3 times over an hour), since last dismissed.
lostintegerItems let go because they were sealed for another copy of Nifty (before Plus moved here), since last dismissed.
expiredintegerItems not collected within 7 days, since last dismissed.

SendAPIResponse

FieldTypeDescription
dataSendAPI

SendAPIToken

FieldTypeDescription
idstring
namestring
endingstringThe token's last four characters.
created_atdate-time
last_used_atdate-time or nullWhen it was last used, to the hour; null if never.

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

Sounds

FieldTypeDescription
onbooleanWhether any sound plays. On by default.
volumeSoundVolumeHow loud every sound plays, as a percentage. 100, the default, is full volume.
task_completedTaskCompletedSoundPlayed when a task is ticked off. tap_trio is the default; none is silent.
createdCreatedSoundPlayed when a task, person or project is created. blip_blip is the default; none is silent.
deletedDeletedSoundPlayed when something is deleted, removed, revoked or disconnected. paper_away is the default; none is silent.
calendar_alertCalendarAlertSoundFor calendar alerts. music_box is the default; none is silent.
updated_atdate-timeWhen the owner record last changed.

SoundsResponse

FieldTypeDescription
dataSounds

SoundVolume

How loud every sound plays, as a percentage. 100, the default, is full volume.

integer

SuggestedPerson

FieldTypeDescription
person_idULIDA record's ID.
person_namestringThe person's name when it was suggested.
emailstring or nullTheir email address the text holds; null when it names them instead.

Suggestion

A person a document names: their full name or an email address of theirs is in its text (found without AI). The owner accepts it by linking the document to the person (POST /document_links, however it's linked), or declines it. Synced; one withdrawn (the document read again no longer names them, or the person was deleted) or purged (its document or person purged) records a suggestion deletion.

FieldTypeDescription
idULIDA record's ID.
kindperson
statuspending | accepted | declined
sourceSuggestionSource
titlestringThe person's name when it was suggested.
personSuggestedPerson
result_idULID or nullThe document link accepting it made; null until accepted.
decided_atdate-time or nullWhen it was accepted or declined.
created_atdate-time
updated_atdate-time

SuggestionResponse

FieldTypeDescription
dataSuggestionA person a document names: their full name or an email address of theirs is in its text (found without AI). The owner accepts it by linking the document to the person (POST /document_links, however it's linked), or declines it. Synced; one withdrawn (the document read again no longer names them, or the person was deleted) or purged (its document or person purged) records a suggestion deletion.

SuggestionSource

FieldTypeDescription
typedocument
idULIDA record's ID.
titlestring or nullThe document's name; null once it's gone.

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.
error_reportsbooleanErrors and crashes are reported, with no user data (the owner's setting, default false; true on a beta). A development build never sends any, whatever this says.
error_reports_forcedbooleanThis is a beta, which always sends error reports, so error_reports is true and can't change.
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 What's new page in the public help (a beta's on beta.help.thenifty.app).
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, a document being linked or unlinked, or deleted, restored or purged while linked (has_documents, document_ids), or a note being attached or detached, or deleted or restored while attached (note_ids).

FieldTypeDescription
planned_start_ondate or nullThe start it was first planned for: its first start_on, settled ten minutes after it was set, then fixed. Null until it has a start. Tasks made before this was kept have the start they had then.
delaysintegerHow many times it's been put off (GET /tasks/{id}/history): its start moved later or was cleared, or was first set to a later day while it was due or overdue. Changes within ten minutes of its creation aren't kept; those within ten minutes of a kept change's first time count once with it, and one that undoes it doesn't count.
deadline_movesintegerHow many times its deadline has moved later or been cleared, counted as delays is.
delegated_atdate-time or nullWhen it was delegated to assignee_id; null when it isn't, or was delegated before this was kept.
now_sincedate-time or nullWhen the owner started working on it, while it's Now (GET /now); null otherwise. At most one task is Now.
received_via_apiReceivedViaAPI or nullHow it came: through the Send to Nifty API (GET /send_api), or null.
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 and project_id; neither is the Inbox.
project_idULID or null
assignee_idULID or nullThe person it's delegated to (never Me); null: the owner's own. A delegated task stays in its list or project, but leaves the Inbox and the smart views but delegated and logbook. While the person is deleted (undo) it's null and the task is the owner's again; their restore puts it back, and their purge clears it, each with a new updated_at.
positionintegerIts home's custom 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=).
document_idsULID[]The live documents linked to it, oldest link first (GET /tasks?document_id= lists a document's tasks).
note_idsULID[]The live notes it's attached to, oldest attachment first (GET /tasks?note_id= lists a note's tasks).
expiredbooleanArchived by its expiry rather than by hand ("Won't do"), in the owner's time zone.
created_atdate-time
updated_atdate-time

TaskCompletedSound

Played when a task is ticked off. tap_trio is the default; none is silent.

pop_in | tap_up | double_pop | tap_trio | sparkle | none

TaskCounts

FieldTypeDescription
inboxintegerIn the Inbox with no start date (view=inbox).
todayintegerStarted today or earlier, the Inbox too (view=today).
today_queueintegerToday's queue: started, or with no start and a deadline (view=today_queue). The Tasks section's Today lists it.
due_soonintegerOverdue or due within 14 days (view=due_soon).
overdueintegerDue before today
delegatedintegerDelegated to someone (view=delegated).
task_listsobject[]Every live list, by position, with its open tasks (delegated ones too).
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): inbox, upcoming: open. today: open, completed_today. logbook: completed, wont_do, expired. One home: open, completed (all-time).

TaskDateChange

One saved change to a task's start or deadline (GET /tasks/{id}/history). Each date's from and to are null when it had none.

FieldTypeDescription
idinteger
atdate-timeWhen the change was first made.
start_changedboolean
start_fromdate or null
start_todate or null
deadline_changedboolean
deadline_fromdate or null
deadline_todate or null
delaybooleanIt put the task off: one of delays.
deadline_movedbooleanIt moved the deadline later or cleared it: one of deadline_moves.

TaskHistoryResponse

FieldTypeDescription
dataTaskDateChange[]
metaany

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.

TaskOrder

How a task page orders its tasks: grouped by deadline (the default) or by start date, or the home's own order (custom).

deadline | start | custom

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, a document being linked or unlinked, or deleted, restored or purged while linked (has_documents, document_ids), or a note being attached or detached, or deleted or restored while attached (note_ids).

TaskSettings

FieldTypeDescription
now_stop_timesNowStopTimesTimes of day (HH:MM, the owner's time zone) at which Now stops by itself, earliest first. No duplicates (a 422).

TaskSettingsResponse

FieldTypeDescription
dataTaskSettings

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. People aren't homes: person_id is ignored.

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. A later start, or clearing it, counts in delays.
deadline_on optionaldate or nullYYYY-MM-DD. It may be before start_on: the task will be late. A later deadline, or clearing it, counts in deadline_moves.
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; both null is the Inbox.
project_id optionalULID or null
assignee_id optionalULID or nullDelegates it to this person, or null to take it back. Its home stays as it is. Me, or an unknown or deleted person, is a 422 on assignee_id; one that isn't an id is a 422 too.
position optionalinteger1-based among the (new) home's open tasks, its custom order; out-of-range values are clamped. Without one, a new open task goes to the top of its home, and a task moved to another home to the bottom.
before_task_id optionalULID or nullInstead of position (both is a 422): just before this open task in its (new) home, or null for the bottom, among every open task the home orders. One that isn't an open task there (or the task itself) is a 422.
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 or images 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 or PNG, JPEG or WebP image upload, or an image under POST /documents' minimum size, is a 422 on documents, and nothing saves.
note_ids optionalULID[] or nullThe notes it's attached to after the save: the full set, attached and detached in the save's transaction. Omitted leaves them as they are; null or [] detaches them all (a deleted note's link stays, for its undo). An unknown or deleted one is a 422 on notes, and nothing saves. Not an array of ids is a 400.

TextSize

The interface's text size; medium is the default.

small | medium | large

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

UnsplashCredit

Unsplash's attribution: "Photo by ‹name› on Unsplash", each linked. The links carry Unsplash's referral tags.

FieldTypeDescription
namestringThe photographer's name.
profile_urluriThe photographer's Unsplash page.
photo_urluriThe photo's Unsplash page.

UnsplashPhoto

FieldTypeDescription
idstring
altstringUnsplash's description, for alt text; may be blank.
widthinteger
heightinteger
colorstringThe photo's main colour, #rrggbb: a placeholder while it loads.
blur_hashstring or null
thumb_urluriAbout 400px wide, on images.unsplash.com.
preview_urluriAbout 1080px wide, on images.unsplash.com.
creditUnsplashCreditUnsplash's attribution: "Photo by ‹name› on Unsplash", each linked. The links carry Unsplash's referral tags.

UnsplashPhotosResponse

FieldTypeDescription
dataUnsplashPhoto[]
metaobject

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 and photo, 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

ViewPlace

One place's choices, each left out while it's the default. The place keys, and what each offers:

Place task_order completed_open library_sort
today, delegated deadline, start
inbox yes
today_also (Today's Also open) yes
task_list:<id>, project:<id> deadline, start, custom yes
person:<id> (their Tasks tab) deadline, start yes
library, library:unsorted, library:all (All files), folder:<id> yes

A place's choices stay until it's deleted for good (after its undo window). At most 2,000 places have choices at once: a change adding places past that is a 422 on places.

FieldTypeDescription
task_order optionalTaskOrderHow a task page orders its tasks: grouped by deadline (the default) or by start date, or the home's own order (custom).
completed_open optionalbooleanWhether its folded section (a home's Completed, Today's Also open) is open: only ever true here, as closed is the default.
library_sort optionalLibrarySortHow a Library place sorts. By name, A to Z, is the default.

Views

FieldTypeDescription
wide_textbooleanView → Wide text: long text wider than its comfortable measure. Off by default.
projects_orderProjectsOrderHow Projects orders its sections: by deadline (the default), name, or newest first by when each was created or its latest activity.
people_arrangePeopleArrangeHow People lays out faces: A to Z (az, the default) or under how they relate to you (groups).
people_showPeopleShowWhich of People's groups shows: all (the default), a relationship_groups key from the vocabulary, or others, everyone in none.
calendar_viewCalendarViewThe view the Calendar opens in: day (the default) or week.
hidden_calendarsHiddenCalendarsWhat the Calendar and Today's Meeting leave out: calendar feeds by id, nifty (My Nifty Calendar) and the kinds of Nifty's own dates (tasks, project_dates, key_dates). Sorted. None by default.
placesobjectEach place's own choices, by place key; only the places with a choice other than its default.

ViewsResponse

FieldTypeDescription
dataViews

Vocabulary

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

any

Webhook

An address Nifty sends signed events to. This server's own; not synced.

FieldTypeDescription
idULIDA record's ID.
namestring
urlstring
eventsWebhookEvent[]In the vocabulary's order.
enabledboolean
last_deliveryWebhookDelivery or nullIts newest delivery, test ones included; null before the first.
created_atdate-time
updated_atdate-time

WebhookCreated

any

WebhookCreatedResponse

FieldTypeDescription
dataWebhookCreated

WebhookDelivery

One event sent, or about to be.

FieldTypeDescription
idULIDA record's ID.
eventtask.created | task.completed | task.deadline_changed | task.start_changed | task.expired | document.uploaded | document.summarized | person.created | note.saved | test
outcomepending | succeeded | failedsucceeded is a 2xx reply. The words are the vocabulary's webhook_outcomes.
http_statusinteger or nullThe reply's status
errorstring or nullWhy it failed, as a sentence ("The address didn't answer within 10 seconds."); null when it succeeded or is pending.
duration_msinteger or nullHow long the request took.
payloadWebhookPayloadThe JSON body sent. data holds the event's record under its kind (task, document, person or note); it's empty for test.
response_bodystring or nullThe start of the reply's body, as text.
created_atdate-timeWhen the event happened.
sent_atdate-time or nullWhen it was sent; null while pending.

WebhookDeliveryResponse

FieldTypeDescription
dataWebhookDeliveryOne event sent, or about to be.

WebhookEvent

An event a webhook can be sent; the words are the vocabulary's webhook_events.

task.created | task.completed | task.deadline_changed | task.start_changed | task.expired | document.uploaded | document.summarized | person.created | note.saved

WebhookPayload

The JSON body sent. data holds the event's record under its kind (task, document, person or note); it's empty for test.

FieldTypeDescription
idULIDA record's ID.
typetask.created | task.completed | task.deadline_changed | task.start_changed | task.expired | document.uploaded | document.summarized | person.created | note.saved | test
created_atdate-timeWhen the event happened.
dataobject

WebhookResponse

FieldTypeDescription
dataWebhookAn address Nifty sends signed events to. This server's own; not synced.

WholeNumberInput

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

integer or null or string

Menu

2026.10.2Contact support