# Nxtly REST API v1 Baseadresse: `https://api.nxtly.app/v1` API-et svarer med JSON. Dokumentasjonssidene bruker HTML eller ren tekst. Vellykkede svar har `{ "success": true, "data": ... }`; feil har `{ "success": false, "error": { "code", "message", "fields?" } }`. Alle autentiserte svar sendes med `Cache-Control: no-store`. ## Kom i gang Åpne **Innstillinger → Integrasjoner → API-nøkler** i den oppdaterte Apple-appen, eller **Konto → Integrasjoner og API-nøkler** på nett. Velg arbeidsområde, gi nøkkelen et navn, velg rettigheter og utløpstid, og kopier nøkkelen. Hele nøkkelen vises bare én gang. Du må være eier eller administrator for å administrere nøkler. Du kan velge ditt personlige arbeidsområde og delte prosjekter du administrerer. Arbeidsområde-ID-en som vises, brukes som `X-Workspace` nedenfor. API-nøkler kan lese, opprette og endre dine egne notater i valgt arbeidsområde med egne notatrettigheter. Sett `NXTLY_API_KEY` til nøkkelen og `NXTLY_WORKSPACE` til arbeidsområdets UUID i integrasjonens konfigurasjon for hemmeligheter. Hent for eksempel åpne oppgaver: ```bash curl 'https://api.nxtly.app/v1/todos?status=open&sort=due&limit=20' \ -H "Authorization: Bearer $NXTLY_API_KEY" \ -H "X-Workspace: $NXTLY_WORKSPACE" ``` Opprett en oppgave med en nøkkel som har `tasks:write`: ```bash curl 'https://api.nxtly.app/v1/todos' \ -H "Authorization: Bearer $NXTLY_API_KEY" \ -H "X-Workspace: $NXTLY_WORKSPACE" \ -H 'Content-Type: application/json' \ --data '{"title":"Send tilbudet","priority":"high"}' ``` Tilbakekall nøkkelen i samme innstillingsbilde for å stoppe tilgangen umiddelbart. Utløpte og tilbakekalte nøkler kan ikke brukes igjen; opprett en ny nøkkel. ## Autentisering og prosjekttilgang Bruk `Authorization: Bearer ` for brukerøkter. Varige MCP- og API-integrasjoner bør bruke en nøkkel bundet til et arbeidsområde i samme header: `Authorization: Bearer nxtly_<64 heksadesimale tegn>`. Prosjektspesifikke kall bruker `X-Workspace: `. API-nøkler genereres kryptografisk tilfeldig, lagres bare som SHA-256-hash og kan bare brukes innenfor valgte arbeidsområder. Velg **Alle arbeidsområder** for tilgang etter brukerens nåværende medlemskap, inkludert fremtidige arbeidsområder. Vanlige rolle- og eierkrav gjelder fortsatt. Hele nøkkelen returneres bare ved oppretting. Tilgjengelige rettigheter: | Rettighet | Tilgang | |---|---| | `tasks:read` | Lese oppgaver, lister, tagger og søke i prosjektet | | `tasks:write` | Opprette oppgaver, lister og tagger | | `tasks:update` | Endre oppgaver, lister og tagger | | `tasks:complete` | Fullføre eller gjenåpne oppgaver (`status: done` eller `pending`); øvrige endringer krever også `tasks:update` | | `tasks:delete` | Slette oppgaver, lister og tagger; gjenopprette oppgaver | | `notes:read` | Lese og søke i dine egne notater i arbeidsområdet | | `notes:write` | Skrive nye notater | | `notes:update` | Endre eksisterende notater og legge til tekst | | `notes:delete` | Slette og gjenopprette egne notater | | `projects:read` | Lese prosjektinformasjon og medlemmer | | `projects:write` | Endre et prosjekt; eierkrav gjelder fortsatt | | `projects:delete` | Slette et prosjekt; eierkrav gjelder fortsatt | | `members:manage` | Lese, opprette og tilbakekalle invitasjoner samt endre og fjerne medlemmer | Tagger merker både oppgaver og notater. `/tags`-endepunktene godtar derfor enten oppgave- eller notatrettigheten for samme handling, for eksempel `tasks:read` eller `notes:read` for å lese. `/tags/{tag}/items` viser bare innholdstypene nøkkelen kan lese. Et brukertoken kan bruke hele API-et innenfor brukerens rettigheter. API-nøkler har ikke tilgang til kontoprofil, innlogging, hendelser, aksept av invitasjoner eller administrasjon av API-nøkler. Nøkler for alle arbeidsområder kan bruke `/combined/todos`, `/combined/notes`, `/combined/notes/{uuid}` og `/combined/search` med tilhørende leserettigheter. Nøkler for ett arbeidsområde kan ikke bruke samlevisninger. Søk returnerer bare innholdstyper nøkkelen har leserettighet til. ## Endepunkter ### Offentlig dokumentasjon | Metode | Sti fra domenets rot | Formål | |---|---|---| | `GET` | `/docs` | Denne REST API-referansen | | `GET` | `/docs/mcp` | MCP-veiledning og verktøyoversikt | | `GET` | `/docs/api.md` | REST-referansen som Markdown | | `GET` | `/docs/mcp.md` | MCP-veiledningen som Markdown | Legg til `?lang=nb` eller `?lang=en` for å velge norsk eller engelsk, også for Markdown. Alle stier nedenfor er relative til `/v1`, med mindre noe annet er oppgitt. ### Helse og innlogging | Metode | Sti | Formål | |---|---|---| | `GET` | `/health` | Helsesjekk som også kontrollerer databasen | | `POST` | `/auth/register` | Opprette bruker, personlig arbeidsområde og økt | | `POST` | `/auth/login` | Opprette en brukerøkt | | `POST` | `/auth/refresh` | Rotere oppfriskningstoken og utstede et nytt tokenpar | | `POST` | `/auth/logout` | Tilbakekalle et oppfriskningstoken | Registrering tar imot `name`, `email` og `password`. Innlogging tar imot `email`, `password` og valgfritt `device_name`. Oppfriskning og utlogging tar imot `refresh_token`. Tilgangstokener er kortvarige. Oppfriskningstokener roteres og må erstattes etter hver vellykkede oppfriskning. ### Bruker, prosjekter og samarbeid | Metode | Sti | Formål | |---|---|---| | `GET` | `/me` | Hente innlogget brukers profil | | `PATCH` | `/me` | Endre navn, innstillinger eller passord | | `GET` | `/me/workspaces` | Hente personlige og delte arbeidsområder med akseptert medlemskap | | `GET` | `/projects` | Hente tilgjengelige delte prosjekter | | `POST` | `/projects` | Opprette et delt prosjekt | | `GET` | `/projects/{project_id}` | Hente prosjekt, egen rolle og antall medlemmer | | `PATCH` | `/projects/{project_id}` | Endre navn på et prosjekt du eier | | `DELETE` | `/projects/{project_id}` | Slette et delt prosjekt du eier permanent | | `GET` | `/projects/{project_id}/members` | Hente medlemmer og roller | | `PATCH` | `/projects/{project_id}/members/{user_id}` | Endre rolle | | `DELETE` | `/projects/{project_id}/members/{user_id}` | Fjerne medlem eller forlate prosjektet | | `GET` | `/projects/{project_id}/invitations` | Hente ventende invitasjoner som administrator | | `POST` | `/projects/{project_id}/invitations` | Invitere via e-post og returnere privat delingslenke | | `DELETE` | `/projects/{project_id}/invitations/{invitation_id}` | Tilbakekalle invitasjon | | `GET` | `/invitations` | Hente ventende invitasjoner for innlogget e-postadresse | | `POST` | `/invitations/accept` | Godta et invitasjonstoken på 64 tegn | `POST /workspaces`, `PATCH /workspaces/{project_id}` og `DELETE /workspaces/{project_id}` beholdes som aliaser for eldre klienter. Prosjektrollene er `owner`, `admin`, `member` og `guest`. Eiere og administratorer administrerer medlemmer. Medlemmer oppretter og endrer delte oppgaver. Gjester har lesetilgang og ser bare oppgaver med `visibility: "guests"` eller oppgaver som er tildelt dem. Bare den som opprettet oppgaven, eller en administrator, kan slette, gjenopprette eller endre synligheten til oppgaven. Opprett en invitasjon med: ```json { "email": "person@example.com", "role": "member" } ``` Svaret inneholder `token`, `share_url` og `expires_at`. Tokenet vises bare i dette svaret, lagres som hash, utløper etter sju dager og er bundet til den inviterte e-postadressen. Det kan ikke brukes etter aksept eller tilbakekalling. ### API-nøkler Velg ett eller **Alle arbeidsområder**. Send `"workspace_scope": "all"` ved oppretting for alle; utelat feltet eller bruk `"single"` for ett arbeidsområde. List og tilbakekall egne nøkler for alle arbeidsområder med `GET /api-keys?workspace_scope=all` og `DELETE /api-keys/{key_id}?workspace_scope=all`. Bare oppretteren kan administrere disse nøklene, og tilgangen følger aktive medlemskap. Rettighetene vises i en tabell med én rad per innholdstype. Migrering 014 bevarer tidligere skriverettigheter for eksisterende nøkler; nye nøkler bruker separate rettigheter for oppretting, endring, fullføring og sletting. | Metode | Sti | Formål | |---|---|---| | `GET` | `/api-keys` | Liste nøkler uten selve hemmeligheten | | `POST` | `/api-keys` | Opprette nøkkel for ett eller alle arbeidsområder; hele nøkkelen returneres én gang | | `DELETE` | `/api-keys/{key_id}` | Tilbakekalle nøkkel umiddelbart | Disse endepunktene krever brukertoken. For nøkler til ett arbeidsområde kreves `X-Workspace` og rollen eier eller administrator. Nøkler for alle arbeidsområder administreres bare av oppretteren. ```json { "name": "MCP på min Mac", "scopes": ["tasks:read", "tasks:write", "tasks:update", "tasks:complete", "projects:read"], "expires_at": "2027-09-05T12:00:00Z" } ``` Appene tilbyr levetid på **30, 90, 180 eller 365 dager**, eller **Aldri** (standard: 90 dager). Send `expires_at` som et fremtidig ISO 8601-tidspunkt, eller `null` for ingen utløpsdato. ### Oppgaver | Metode | Sti | Formål | |---|---|---| | `GET` | `/todos` | Liste synlige oppgaver i arbeidsområdet | | `POST` | `/todos` | Opprette en oppgave | | `GET` | `/todos/{task_id}` | Hente én synlig oppgave | | `PATCH` | `/todos/{task_id}` | Endre oppgitte felt eller fullføre oppgaven | | `DELETE` | `/todos/{task_id}` | Flytte oppgaven til papirkurven | | `POST` | `/todos/{task_id}/restore` | Gjenopprette oppgaven | Listekallet støtter `list_id`, `status`, `priority`, `parent_id`, `tag` (UUID eller navn), `assignee` (`me` eller brukerens UUID), `sort` (`created`, `updated`, `due`, `priority`, `title`), `limit` (1–100) og heltallet `cursor` som spørringsparametere. En oppgave kan sendes slik: ```json { "title": "Publiser ny versjon", "description": "Siste gjennomgang og publisering", "status": "pending", "priority": "high", "visibility": "team", "assignee_ids": ["bruker-uuid-1", "bruker-uuid-2"], "list_id": null, "parent_id": null, "tags": ["bug", "feature"], "due_date": "2027-03-01T09:00:00Z", "reminder_at": "2027-03-01T08:30:00Z", "location": "Oslo", "visible_from": "2027-02-20", "recurrence": { "interval_days": 7 } } ``` Statusverdiene er `pending`, `in_progress` og `done`. Prioritet er `low`, `medium`, `high` eller `urgent`. Synlighet er `private`, `team` eller `guests`. `assignee_ids` støtter opptil 100 aksepterte prosjektmedlemmer. Det eldre feltet `assignee_id` støttes fortsatt. Svaret inkluderer `created_by` og hele listen `assignees`. Når en gjentakende oppgave fullføres, flyttes den frem til neste gjentakelse og venter til neste `visible_from`-dato. `tags` erstatter dine tagger på oppgaven. `add_tags` og `remove_tags` endrer bare de oppgitte. Alle tre tar tag-navn eller tag-UUID-er; se [Tagger](#tagger). ### Tagger Tagger er personlige. De tilhører brukeren som lager dem, og kan settes på alle oppgaver og notater brukeren ser, i alle arbeidsområder, prosjekter og selskaper. Andre medlemmer ser aldri taggene dine, heller ikke på delte oppgaver, og dine endringer rører aldri deres tagger. | Metode | Sti | Formål | |---|---|---| | `GET` | `/tags` | Liste taggene dine med `todo_count`, `open_todo_count` og `note_count` | | `POST` | `/tags` | Opprette en tagg med `name` (høyst 50 tegn) og valgfri `color` (`#rrggbb`) | | `GET` | `/tags/{tag}` | Hente én tagg med tellere | | `GET` | `/tags/{tag}/items` | Hente alle oppgaver og notater med taggen, på tvers av arbeidsområder | | `PATCH` | `/tags/{tag}` | Endre `name` eller `color` | | `DELETE` | `/tags/{tag}` | Slette taggen og fjerne den fra alt innhold. Oppgavene og notatene beholdes | `{tag}` er taggens UUID eller navnet, for eksempel `/tags/bug/items`. Navn sammenlignes uten hensyn til store og små bokstaver, og en innledende `#` ignoreres. Et navn som finnes fra før gir `409 TAG_EXISTS` ved oppretting eller endring. Oppgaver og notater tar feltene `tags`, `add_tags` og `remove_tags` med navn eller UUID-er. Et navn som ikke finnes, opprettes. Oppgaven nedenfor får taggen `bug`, også om den ikke fantes: ```json POST /v1/todos { "title": "Appen krasjer ved oppstart", "tags": ["bug"] } ``` Den som kan se en oppgave, kan sette sine egne tagger på den, også med lesetilgang. En endring som bare gjelder tagger, endrer ikke selve oppgaven eller dens versjon. `/tags/{tag}/items` godtar `type` (`all`, `todos`, `notes`), `status` (som for oppgaver, for eksempel `open`) og `limit` (1–200 per type). Svaret inneholder `tag`, `todos` og `notes`. Hver oppgave og hvert notat har `workspace` med prosjektet eller det personlige arbeidsområdet det ligger i. `/combined/todos`, `/combined/notes`, `/todos` og `/notes` filtrerer også på `tag`. ### Lister, mapper og notater | Metode | Sti | Formål | |---|---|---| | `GET`, `POST` | `/lists` | Liste eller opprette oppgavelister | | `GET`, `PATCH`, `DELETE` | `/lists/{list_id}` | Hente, endre eller slette en liste | | `GET`, `POST` | `/folders` | Liste eller opprette notatmapper | | `GET`, `PATCH`, `DELETE` | `/folders/{folder_id}` | Hente, endre eller slette en mappe | | `GET`, `POST` | `/notes` | Liste eller opprette notater | | `GET`, `PATCH`, `DELETE` | `/notes/{note_id}` | Hente, endre eller flytte notat til papirkurven | | `POST` | `/notes/{note_id}/restore` | Gjenopprette et notat | Lister støtter `name`, `color`, `icon`, `sort_order` og de samme tre verdiene for synlighet som oppgaver. Notater og mapper er private for den som opprettet dem; prosjektsamarbeid gjelder foreløpig oppgavelister og oppgaver. ### Søk, samlevisninger og sanntidsoppdateringer | Metode | Sti | Formål | |---|---|---| | `GET` | `/search?q=...&limit=...` | Søke i synlige oppgaver og private notater i aktivt arbeidsområde | | `GET` | `/combined/search?q=...&limit=...` | Søke på tvers av arbeidsområder med akseptert medlemskap | | `GET` | `/combined/todos` | Hente synlige oppgaver på tvers av arbeidsområder, valgfritt med `tag` | | `GET` | `/combined/notes` | Hente private notater på tvers av arbeidsområder, valgfritt med `tag` | | `GET` | `/combined/sidebar` | Hente arbeidsområder, lister og mapper som trestruktur | | `POST` | `/events/token` | Bytte brukertoken mot kortvarig token for hendelsesstrøm | | `GET` | `/events?token=...` | Motta endringssignaler med Server-Sent Events | ## MCP Den eksterne MCP-serveren ligger på `https://api.nxtly.app/v1/mcp` og støtter innlogging med OAuth. Den lokale stdio-serveren støtter API-nøkler. Se [MCP-veiledningen](../mcp/README.md) for oppsett og verktøyoversikt. ## Synkronisering av lokal cache `POST /v1/sync` krever en bruker-JWT. API-nøkler og MCP OAuth-tokener kan ikke lese øyeblikksbildet for hele kontoen. Send `{ "changes": [...] }` med maksimalt 128 poster og en forespørsel på høyst 1 MB. En tom liste henter gjeldende øyeblikksbilde og servertid. Poster inneholder `kind` (`company`, `project`, `note`, `task`, og `tag` med taggfunksjonen), UUID `id`, `modified_us` (opprinnelig handlingstid i mikrosekunder siden Unix-epoken, UTC), UUID `operation_id`, `deleted` og `data`. Svaret inneholder `records` (hele det autoriserte øyeblikksbildet), `acknowledged` (operasjons-ID-er) og `server_time_us`. Gjentatte forsøk beholder opprinnelig tid og operasjons-ID. Ved konflikt vinner høyeste tidsstempel, deretter leksikografisk høyeste operasjons-ID. Sletting beholder en slettemarkør. Versjoner gjelder hele posten. Prosjektreferanser bruker UUID. Et prosjekt satt til `null` betyr personlig arbeidsområde. Oppgaver bruker `title`, `detail`, `status` (`backlog`, `doing`, `done`), `priority` (0–2), valgfritt `project_id`, `note_id`, `source_key`, `due_at_us` og `created_at_us`. Notater bruker `title`, `markdown`, `pinned`, `project_id` og `created_at_us`. Prosjekter bruker `name`, `summary`, `symbol`, `archived`, `company_id` og `created_at_us`. Selskaper bruker `name`, `summary` og `created_at_us`. Klienter som sender `"features": ["tags"]`, utveksler også tagger. Da finnes posttypen `tag` med `name`, `color` og `created_at_us`, og oppgaver og notater får `tag_ids`: en sortert liste med UUID-er for kontoens egne tagger. En endring av en delt oppgave eller et notat der bare `tag_ids` er endret, eller der kontoen ikke har skrivetilgang, oppdaterer bare kontoens tagger og lar resten av posten være. En tagg som opprettes uten nett med et navn som finnes fra før, slås sammen med den eksisterende. Klienter uten `features` får ingen taggdata, og endringene deres rører ikke tagger. REST-endringer av oppgaver kan inkludere `_action_time_us` og `_operation_id` for å sende handlinger utført uten nett. Oppretting kan også inkludere `_record_id` for trygt å gjenta et kall der svaret gikk tapt. Uten disse feltene bruker REST og MCP servertiden. Svar inneholder `X-Server-Time-Us` for kalibrering av enhetens klokke. Tidsstempler mer enn fem minutter frem i tid avvises. Øyeblikksbildet inkluderer valgfritt `can_edit` på delte poster og `can_add` på prosjekter. Klienter kan bruke dette til å deaktivere redigering uten å endre medlemsrettigheter. ## Tilbakestilling av passord - `POST /v1/auth/forgot-password` med `{email}`: 202 med samme svar for kjente og ukjente kontoer. Gir 503 når e-postsending ikke er konfigurert, eller 429 ved rategrense. - `POST /v1/auth/reset-password` med `{token,password}`: 200 etter én gangs bruk innen 30 minutter. Ugyldig, utløpt eller brukt token gir 400. Passord krever minst 8 tegn og maksimalt 72 byte. - Nytt passord tilbakekaller innloggingsøkter, oppfriskningstokener og OAuth-tilkoblinger umiddelbart. Brukeren må logge inn igjen. ## Markdown-notater og atomisk tilføyelse REST, Apple, web og MCP bruker samme `notes`-rader og UUID-er. `POST /v1/notes` og `PATCH /v1/notes/{uuid}` aksepterer `markdown` som et strengfelt på maksimalt 100 000 Unicode-kodepunkter. Tom streng tømmer innholdet. API-et skriver samme verdi til `content_text` og regenererer en escaped HTML-representasjon. Eldre klienter kan fortsatt bruke `content_text` og `content_json`; dersom både `markdown` og `content_text` sendes, må de være like. Detalj- og listesvar inneholder også `markdown`. ```json {"title":"Møtereferat","markdown":"# Agenda\n\n- [ ] Avklar levering","pinned":false} ``` - `GET /v1/notes?q=levering&limit=50`: søk i tittel og innhold i aktivt workspace. `%`, `_` og `!` behandles bokstavelig. `folder_id`, `pinned` og `cursor` kan kombineres. `meta.next_cursor` følger festede notater først og deretter ID, også når overgangen går fra festede til øvrige notater. - `GET /v1/combined/notes/{uuid}`: hent et eget notat uten `X-Workspace`, med `workspace`-referanse. Krever aktivt medlemskap og et prosjekt som ikke er slettet. Andres, slettede og utilgjengelige notater gir 404. Lagrede Siri-snarveier bruker dette for å finne gamle notater uten en listegrense. - `POST /v1/notes/{uuid}/append` med `{"text":"Ny oppfølging"}` legger til to linjeskift og teksten. Eksisterende innhold låses i en transaksjon, slik at samtidige tilføyelser beholdes. Tom tekst, feil type eller et samlet innhold over 100 000 tegn gir 400. Operasjonen er **ikke idempotent**: gjenta ikke automatisk etter et tvetydig nettutfall; les notatet først. Notater er private for oppretteren innenfor workspace-medlemskapet. Skriving krever rollen owner, admin eller member. Workspace-bundne API-nøkler krever `notes:read` for GET og søk, `notes:write` for POST /notes og `notes:update` for PATCH og POST /notes/{uuid}/append. Rettighetene gir ikke tilgang til å slette eller gjenopprette uten `notes:delete`. Deling krever alltid innlogging i appen. Brukerøkter og OAuth-tilkoblinger beholder sin eksisterende tilgang. MCP-OAuth-tokens fungerer bare gjennom `/v1/mcp`.