nessie

API

HTTP API, kas darbina katru Nessie klientu, un kā tajā autentificēties.

Kas ir API

Nessie ir viens HTTP API. Administratora tīmekļa lietotne, macOS un iOS klienti un attālais izpildītāja fona process ir parasti tā klienti, un nekas, ko tie var darīt, nav sasniedzams citādi. Tas ir JSON API virs Fastify servera, tas nav GraphQL, un tam nav atsevišķas „publiskas” apakškopas: virsma, ko izsauc jūsu pašu skripti, ir tā pati, ko izsauc produkts.

Ceļā nav versijas segmenta. Visi maršruti atrodas zem /api, izņemot ienākošo MCP galapunktu POST /mcp un dažus /.well-known/ atklāšanas dokumentus. Saderību nodrošina tikai lauku pievienošana, tāpēc klients, kas ignorē to, ko neatpazīst, turpina darboties.

Bāzes URL

Nessie tiek pašmitināts, tāpēc bāzes URL ir jebkura izcelsme (origin), kurā jūsu izvietojums nodrošina API — operators to iestata kā NESSIE_API_PUBLIC_URL, un tā pati vērtība ir tā, ko API izmanto, kad tam jāveido pašam savs absolūtais URL. Mūsu darbināmajā instancē tas ir https://api.nessie.works; izstrādes instance, kas palaista ar pnpm dev, atbild adresē http://localhost:5454.

Administratora tīmekļa lietotne atrodas citā izcelsmē nekā API, tāpēc pārlūkprogrammu klientiem piemēro CORS atļauto sarakstu (NESSIE_CORS_ORIGINS). Pieprasījumiem no skripta vai servera nav izcelsmes, ko pārbaudīt, un tie nav ietekmēti.

Autentifikācija

Katrs pieprasījums ārpus nelielas, apzināti publiskas maršrutu kopas nes piekļuves marķieri standarta galvenē:

Authorization: Bearer <token>

Marķieris ir parakstīts JWT, ko izveido API. Tas ir īslaicīgs — pēc noklusējuma trīsdesmit minūtes (NESSIE_AUTH_TOKEN_TTL) — un tas ir vienīgais akreditācijas dats, ko parasts izsaucējs jebkad uzrāda. Nessie nav ilgstošu personīgo API atslēgu. Ja vēlaties, lai skripts izsauc API, tas pieteicas tāpat kā cilvēka pārlūkprogramma un atjauno savu marķieri, kamēr darbojas.

Marķiera iegūšana

POST /api/auth/session izveido sesiju. Atbildē tiek atgriezts piekļuves marķieris un izsaucēja identitāte, un atjaunošanas marķieris tiek iestatīts kā atsevišķa tikai HTTP sīkdatne.

Kā pierādāt, kas esat, atkarīgs no tā, kā instance ir izvietots. Instance, kas darbojas režīmā local, pieņem e-pastu un paroli. Instancē hosted vai selfHosted pieteikšanās ar paroli tiek noraidīta ar 403 PASSWORD_AUTH_DISABLED, un vienīgais ceļš iekšā ir konfigurētais identitātes sniedzējs — tāpēc kontam nekad nevar izaugt otrs, vājāks identitātes ceļš blakus tam.

Pieteikšanās caur identitātes sniedzēju

Vienotā pieteikšanās ir OAuth autorizācijas koda apmaiņa ar PKCE trīs soļos. Nessie pašu identitātes sniedzējs ir UnlikeOtherAI, kas arī pārvalda organizāciju un komandu struktūru, ko instance atspoguļo; tālākā apmaiņa ir tāda pati jebkuram konfigurētam sniedzējam.

  1. GET /api/auth/providers uzskaita, ko šī instance pieņem, katrs ar providerId, nosaukumu un to, vai pieteikšanās lapai jānovirza uz to automātiski.
  2. GET /api/auth/providers/:providerId/authorize ar codeChallenge, redirectUri un state kā vaicājuma parametriem atbild ar { data: { authorizeUrl } }. Nosūtiet cilvēku turp.
  3. Sniedzējs viņus atgriež jūsu redirectUri ar kodu. Nosūtiet to atpakaļ kā POST /api/auth/session ar { providerId, code, codeVerifier, redirectUri } — visi četri ir vajadzīgi kopā, un nepilnīga kopa ir 400 EXTERNAL_AUTH_INCOMPLETE.

Sesijas atjaunošana

Atjaunošanas marķieris nekad neatrodas atbildes saturā. Tas tiek iestatīts kā tikai HTTP sīkdatne ar nosaukumu nessie_refresh, kas attiecas uz ceļu /api/auth, ar noklusējuma derīguma termiņu trīsdesmit dienas (NESSIE_AUTH_REFRESH_TOKEN_TTL). Izsaucot POST /api/auth/refresh ar šo sīkdatni, tā tiek izlietota, izsniegts jauns piekļuves marķieris un tās vietā iestatīta jauna sīkdatne — marķieri rotē, tāpēc nozagts marķieris derīgs tikai līdz brīdim, kad īstais klients nākamreiz atjaunos.

Pārlūkprogramma, kas pieteikusies vairākos kontos, glabā vienu šādu sīkdatni katrai pieteikšanās reizei ar nosaukumu nessie_refresh_<slot>, un ar galveni x-nessie-account-slot norāda, uz kuru attiecas pieprasījums. Klients, kas šādu galveni nesūta, attiecas uz nessie_refresh — un tas ir viss, kas nepieciešams komandrindas klientam.

Komandrindas klientam tāpēc vajadzīga sīkdatņu glabātuve. Ar curl tā ir --cookie-jar pieteikšanās izsaukumā un --cookie atjaunošanā, kā zemāk redzamajā piemērā.

Ko pārbauda katrā pieprasījumā

Autentifikācija nav tikai paraksta pārbaude. Pirms apstrādātājs darbojas, API pārbauda marķiera parakstu un derīguma termiņu, apstiprina, ka sesija nav atsaukta (gan pēc lietotāja mēroga marķiera versijas, gan pēc atsevišķā sesijas ID), un ielādē izsaucēja dalību organizācijā, ko nosauc marķieris. Deaktivizēta dalība ir 403. Ja organizāciju atbalsta ārējs identitātes sniedzējs, izsaucēja pašreizējais statuss tiek pārbaudīts pret šo sniedzēju pieprasījumā, nevis nolasīts no marķiera, tāpēc piekļuve, kas ārēji noņemta, pārtrauc darboties uzreiz, nevis nākamajā derīguma termiņa beigās.

Akreditācijas dati, kas nav sesijas marķieri

Pastāv vēl divi nesēja tipa akreditācijas dati, un neviens nav vispārējas nozīmes atslēga. Balss ierīces akreditācijas dati tiek pieņemti tikai balss zvanu maršrutos; aģenta piekļuves akreditācijas dati — tikai MCP galapunktā. Ja tos uzrāda jebkur citur, tie tiek noraidīti ar 403, kas nosauc akreditācijas datus, nevis atkārtoti mēģināti kā vājāka sesija — par to, kā tiek izsniegti aģenta akreditācijas dati, skatiet MCP un savienotie rīki.

Atbildes apvalks

Katra veiksmīga atbilde ir objekts ar atslēgu data. Nav tīra masīva un nav augstākā līmeņa satura saknē, tāpēc klientam nekad nav jāatšķir struktūra:

{
  "data": { "id": "3f1c…", "label": "engineering" }
}

Saraksta galapunkti blakus pievieno objektu meta. Augstākajā līmenī nekas cits nekad netiek pievienots.

Kļūdām ir arī viena struktūra neatkarīgi no tā, kas tās izraisīja:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "A message needs content or at least one attachment",
    "field": "body",
    "details": { "formErrors": [], "fieldErrors": {} }
  }
}

code ir mašīnlasāmā daļa, un pēc tās jāpieņem lēmums; message ir domāts cilvēkam. field un details ir klāt, kad kļūda ir pietiekami konkrēta, lai to atrastu. Neapstrādāta servera kļūda vienmēr ir 500 INTERNAL_ERROR ar fiksētu ziņojumu — pamatā esošais kļūdas teksts tiek reģistrēts, nekad neatgriezts, jo tas var būt uztvēris pieprasījuma datus, kamēr tiek izvadīts.

Kļūdu kodi, ar kuriem sastapsieties vispirms

StatussKodsNozīme
400VALIDATION_ERRORPieprasījuma saturs vai vaicājums neatbilst shēmai.
401AUTH_REQUIREDNav nesēja marķiera vai galvene ir bojāta.
401TOKEN_EXPIREDPiekļuves marķiera derīguma termiņš ir beidzies. Atjaunojiet un mēģiniet vēlreiz.
401TOKEN_REVOKEDSesija tika izrakstīta vai visas sesijas tika piespiedu kārtā pārtrauktas.
403ACCOUNT_DEACTIVATEDDalība šajā organizācijā ir deaktivizēta.
404NOT_FOUNDNav tāda maršruta vai ieraksta, kas redzams šim izsaucējam.
429RATE_LIMITEDIerobežojuma skaitītājs ir pilns. Lasiet Retry-After.
500INTERNAL_ERRORNeapstrādāta servera kļūda, apzināti neskaidra.

Lapošana

Saraksta galapunkti lapo ar necaurskatāmu atslēgas kursoru, nevis nobīdi — rindas tiek ievietotas, kamēr kāds lasa, un ar nobīdi otrā lapa klusām atkārto ierakstu, ko jau parādīja pirmā lapa.

Tiek pieņemti trīs vaicājuma parametri: cursor, limit un direction (forward vai backward). Noklusējuma lapa ir 25, un augšējā robeža ir 100; lielāka vērtība tiek samazināta, nevis noraidīta. Galapunkti, kas arī kārto vai filtrē, pievieno sort, order un brīvā teksta q.

Lapas meta norāda, kur atrodaties:

{
  "data": [ … ],
  "meta": {
    "hasMore": true,
    "nextCursor": "2026-09-12T08:31:44.005Z|8b2f…",
    "prevCursor": null,
    "total": 134
  }
}

nextCursor un prevCursor abi ir patiesi: Iepriekšējā un Nākamā ir vadīklas, ko cilvēks sagaida. Tie ir necaurskatāmi — serveris tajos kodē savu kārtošanas atslēgu, un klients, kas to parsē vai veido, pārtrauks darboties tiklīdz saraksts maina kārtošanu. total ir klāt lielākajā daļā sarakstu un izlaists tur, kur skaitīšana nav jēgas, piemēram, rangotos meklēšanas rezultātos.

Ātruma ierobežojumi

Ierobežojumi attiecas uz fiksētu logu un tiek piemēroti pirms pat pieprasījuma satura nolasīšanas. Noraidīts pieprasījums ir 429 ar kodu RATE_LIMITED un galveni Retry-After sekundēs.

Lielākā daļa ierobežojumu skaitītāju ir atkarīgi no klienta IP; tie, kas jutīgi pret akreditācijas datiem — pieteikšanās, atjaunošana, paroles atkārtota pierādīšana, MCP akreditācijas datu ierakstīšana — turklāt glabā skaitītāju katram kontam un noraida, kad jebkurš no tiem sasniegts, tāpēc gan viena adrese, kas uzbrūk daudziem kontiem, gan viens konts, kuru uzbrūk no daudzām adresēm, saskaras ar ierobežojumu. Pieteikšanās noklusējums ir 10 mēģinājumi uz IP un 5 uz e-pasta adresi desmit minūtēs; ziņas publicēšanas noklusējums ir 60 minūtē; ieraksti zem /api/agents — 60 minūtē. Katru slieksni var konfigurēt izvietojumā, tāpēc uztveriet šos kā piegādātos noklusējumus, nevis līgumu. Veselības pārbaudes un reāllaika straumes ir atbrīvotas.

Reāllaiks

Saraksta regulāra vaicāšana ir nepareizs veids, kā sekot sarunai. Tā vietā pastāv trīs straumēšanas galapunkti:

  • GET /api/events/stream — servera nosūtītie notikumi (server-sent events) visam, ko pieteicies cilvēks var redzēt.
  • GET /api/threads/:threadId/stream — servera nosūtītie notikumi vienam pavedienam. Tas ievēro Last-Event-ID, tāpēc atkārtota savienošanās turpina, nevis sāk no jauna.
  • GET /api/activity — WebSocket, pa kuru tiek pārraidīta aktivitātes plūsma.

Pārlūkprogrammas nevar iestatīt galvenes WebSocket rokasspiedienā, tāpēc WebSocket maršruts piekļuves marķieri pieņem arī kā vaicājuma parametru ?token=. Tā ir vienīgā vieta, kur marķieris pieder URL; visi pārējie maršruti to saņem galvenē.

Resursu saimes

Galapunktu ir krietni vairāk nekā tūkstotis — pārāk daudz, lai tos uzskaitītu. Tie tiek grupēti saimēs, un, kad zināt saimes priedēkli, atsevišķie maršruti ir paredzami — kolekcija priedēklī, ieraksts zem tā un nosauktas darbības kā POST apakšceļi.

SaimePriedēklisKo aptver
Autentifikācija/api/authPieteikšanās, atjaunošana, izrakstīšanās, pašreizējā identitāte, cilvēka paša sesijas.
Kanāli un pavedieni/api/channels, /api/threadsSarunu modelis: kanāli satur pavedienus, pavedieni satur ziņas, atbildes ligzdojas zem saknes.
Aģenti/api/agentsAģentu definīcijas, to kanālu saistījumi, sarunas, uzdevumu saraksti un statuss.
Projekti un dēļi/api/projects, /api/tasks, /api/iterationsDarbu izsekošana: dēļi un kolonnas projekta ietvaros, uzdevumi uz tiem un iterācijas pāri tām.
Zināšanas/api/knowledge-baseVersētu lapu un failu telpas ar komentāriem, atpakaļsaitēm un meklēšanu.
Pasts/api/mail, /api/mailbox-connectionsSavienotās pastkastes, aģentu pastkastes un aģenta sagatavotie melnraksti, ko cilvēks apstiprina.
Apstiprinājumi/api/approvalsDarbību rinda, ko aģents nevar veikt vienpersoniski, un viens izsaukums, kas tās atrisina.
Audits/api/audit-logOrganizācijas auditēšanas pēdas ar jaucējķēdi un pārbaudes galapunktu. Īpašniekiem un administratoriem.
Izmaksas un lietojums/api/ledger, /api/billingMarķieru un izmaksu uzskaite, budžeti un darbību laiki; atsevišķi — kredīti un papildinājumi. Īpašniekiem un administratoriem.
Organizācija un komandas/api/organizations, /api/teams, /api/usersNomnieka, komandu un dalības administrēšana, ieskaitot uzaicinājumus.
Aktivizētāji/api/triggersGrafiki un tīmekļa āķi (webhook), kas sāk aģentu darbu, ar to aktivizēšanas vēsturi.
Zvani un balss/api/calls, /api/voiceZvani kanālā un balss asistenta sesija, transkripts un ierīču marķieri.
Izpildītāji/api/executors, /api/execution-environment-templatesMašīnas, uz kurām strādā aģenti, to vide un fona procesa savienošanas kanāls.
Darbības/api/runsAktīvas aģentu darbības: atcelt, turpināt, restartēt, piesaistīt izpildītājam.
Augšupielādes/api/uploads, /api/attachmentsVispirms augšupielādējiet failu, pēc tam saistiet atgriezto ID ar ziņu.
Meklēšana/api/messages/searchZiņu meklēšana visā organizācijā vai vienā kanālā.
Noslēpumi un iestatījumi/api/secrets, /api/settings/scopedTikai rakstāmi akreditācijas datu glabātuve ar skaidrām piešķirtajām tiesībām un slāņotas konfigurācijas vērtības.
Savienotie rīki/api/mcpMCP serveri, uz kuriem šī instance izsauc. Skatiet MCP un savienotie rīki.
Veselība/api/healthDarbspēja un gatavība, abi publiski. /api/health/ready papildus pārbauda datubāzi.

Tiesības tiek piemērotas katram maršrutam, nevis saimei. Plašāk: auditēšanas žurnāls, izmaksu virsgrāmata, politikas noteikumi un secinājumu vadības plakne ir virsmas organizācijas īpašniekiem un administratoriem, savukārt sarunas, projekti, zināšanas un apstiprinājumi ir atvērti katram dalībniekam un sašaurināti līdz tam, ko šis dalībnieks patiesi var redzēt.

Piemēri

Pieteikšanās un atjaunošanas sīkdatnes saglabāšana

Instancē režīmā local ar paroli. Piekļuves marķieris atgriežas saturā; atjaunošanas marķieris nonāk sīkdatņu glabātuvē.

curl -sS https://api.example.com/api/auth/session \
  --cookie-jar nessie.cookies \
  -H 'Content-Type: application/json' \
  -d '{"email":"ada@example.com","password":"…"}'
{
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
    "me": {
      "user": {
        "id": "1d4e…",
        "email": "ada@example.com",
        "displayName": "Ada Lovelace",
        "roleIds": ["owner"],
        "superAdmin": false
      },
      "session": {
        "sessionId": "9c07…",
        "issuedAt": "2026-09-16T09:00:00.000Z",
        "expiresAt": "2026-09-16T09:30:00.000Z"
      },
      "context": {
        "organizationId": "5a81…",
        "projectId": "7b12…",
        "teamId": "2e60…",
        "channelId": null,
        "bootstrapMode": false
      },
      "auth": {
        "providerId": "local",
        "providerType": "local-bootstrap",
        "autoRedirectToSso": false
      }
    }
  }
}

Kad marķieris beidzas, apmainiet sīkdatni pret jaunu:

curl -sS -X POST https://api.example.com/api/auth/refresh \
  --cookie nessie.cookies --cookie-jar nessie.cookies

Atbilde ir tā pati { token, me } struktūra, un sīkdatņu glabātuvē tagad ir rotētais atjaunošanas marķieris.

Uzskaitiet kanālus, ko varat redzēt

curl -sS https://api.example.com/api/channels \
  -H "Authorization: Bearer $TOKEN"
{
  "data": [
    {
      "id": "8b2f…",
      "label": "engineering",
      "type": "standard",
      "visibility": "public",
      "projectId": "…",
      "projectName": "Platform",
      "teamId": "…",
      "defaultThreadId": "c41a…",
      "unreadCount": 3,
      "lastMessageAt": "2026-09-15T18:22:07.441Z",
      "viewerCanManage": true
    }
  ]
}

Pievienojiet ?teamId=…, lai sašaurinātu līdz vienai komandai, vai ?includeArchived=true, lai iekļautu arhivētos kanālus. defaultThreadId ir tas, kurā nākamo reizi publicēsiet.

Publicējiet ziņu

Ziņai nepieciešams vai nu kāds content, vai vismaz viens augšupielādēts pielikums. Nosūtiet Idempotency-Key, un atkārtots pieprasījums atrisinās uz ziņu, ko izveidoja pirmais mēģinājums, nevis publicē otru kopiju.

curl -sS https://api.example.com/api/threads/c41a…/messages \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 0f9c2d16-8f4a-4c1e-9a77-6b0d4f2e1a53' \
  -d '{"content":"Deploying the migration now."}'

Jauna ziņa ir 201:

{
  "data": {
    "message": {
      "id": "d70e…",
      "threadId": "c41a…",
      "role": "user",
      "content": "Deploying the migration now.",
      "createdAt": "2026-09-16T09:04:11.882Z"
    },
    "pendingAgentInvites": []
  }
}

Tā paša idempotences atslēgas atkārtojums atbild ar 200, oriģinālo ziņu un tukšu pendingAgentInvites, jo pirmais mēģinājums jau veica brīdināšanu un nosūtīšanu, ko masīvs apraksta.

Divi šī maršruta noraidījumi ir vērts apstrādāt skaidri. Saturs, kas pārsniedz tērzēšanas garuma ierobežojumu, ir 413 MESSAGE_TOO_LARGE, un pareizā atbilde ir augšupielādēt tekstu kā failu. Saturs, kas strukturāli izskatās pēc akreditācijas datiem, ir 422 SECRET_INTERCEPTED — serveris noraida to pirms ziņas saglabāšanas, nosūtīšanas vai reģistrēšanas, un akreditācijas dati pieder /api/secrets.