API
HTTP-rajapinta, jonka kautta jokainen Nessie-asiakas toimii, ja ohje sen käyttöön kirjautumiseen.
Mitä API on
Nessiessä on yksi HTTP-rajapinta. Hallintasovellus, macOS- ja iOS-asiakkaat sekä etäsuorittimen daemon ovat kaikki tavallisia tämän rajapinnan asiakkaita, eikä niiden tekemiseen ole mitään muuta reittiä. Kyseessä on JSON-rajapinta, joka toimii Fastify-palvelimen päällä. Se ei ole GraphQL, eikä sillä ole erillistä ”julkista” osajoukkoa: rajapinta, jota omat skriptisi kutsuvat, on sama, jota tuote itse kutsuu.
Polussa ei ole versiosegmenttiä. Jokainen reitti on polun /api alla, paitsi sisääntuleva MCP-päätepiste POST /mcp ja muutama /.well-known/-löytöasiakirja. Yhteensopivuus hoidetaan lisäämällä vain kenttiä, joten asiakas, joka ohittaa tuntemattomat kentät, toimii edelleen.
Perus-URL
Nessie on itse isännöitävä, joten perus-URL on se origin, jossa käyttöönottosi palvelee rajapintaa. Ylläpitäjä asettaa sen muuttujaan NESSIE_API_PUBLIC_URL, ja sama arvo on se, jota API käyttää, kun sen pitää luoda oma absoluuttinen URL. Ylläpitämässämme instanssissa se on https://api.nessie.works. Komennolla pnpm dev käynnistetty kehitysinstanssi vastaa osoitteessa http://localhost:5454.
Hallintasovellus on eri origin kuin rajapinta, joten selainasiakkaisiin sovelletaan CORS-sallittujen listaa (NESSIE_CORS_ORIGINS). Skriptien tai palvelimien pyynnöillä ei ole originia, jota tarkistettaisiin, joten ne eivät kuulu tämän piiriin.
Todentaminen
Jokainen pyyntö, paitsi harvat tarkoituksella julkiset reitit, kantaa käyttöoikeustunnusta tavallisessa otsakkeessa:
Authorization: Bearer <token>Tunnus on API:n allekirjoittama JWT. Se on lyhytikäinen: oletuksena kolmekymmentä minuuttia (NESSIE_AUTH_TOKEN_TTL). Se on ainoa tunniste, jonka tavallinen kutsuja koskaan esittää. Nessiessä ei ole pitkäikäisiä henkilökohtaisia API-avaimia. Jos haluat skriptin kutsuvan rajapintaa, se kirjautuu samalla tavalla kuin henkilön selain ja uusii tunnuksensa matkan varrella.
Tunnuksen hankkiminen
POST /api/auth/session luo istunnon. Se vastaa käyttöoikeustunnuksella ja kutsujan henkilöllisyydellä ja asettaa uusimistunnuksen erilliseen HTTP-only-evästeeseen.
Miten todistat henkilöllisyytesi, riippuu siitä, miten instanssi on otettu käyttöön. local-tilassa toimiva instanssi hyväksyy sähköpostiosoitteen ja salasanan. Instanssilla, joka on hosted- tai selfHosted-tilassa, salasanakirjautuminen evätään suoraan vastauksella 403 PASSWORD_AUTH_DISABLED, ja ainoa sisäänkäynti on määritetty identiteettitarjoaja. Tilillä ei siis voi olla toista, heikompaa tunnistautumistapaa sen rinnalla.
Kirjautuminen identiteettitarjoajan kautta
Yhden kirjautumisen (SSO) toteutus on OAuth-valtuutuskoodin vaihto PKCE:n kanssa, ja se tapahtuu kolmessa vaiheessa. Nessien oma identiteettitarjoaja on UnlikeOtherAI, joka omistaa myös organisaatio- ja tiimirakenteen, jota instanssi peilaa. Alla oleva vaihto on muodoltaan sama mille tahansa määritetylle tarjoajalle.
GET /api/auth/providerslistaa tämän instanssin hyväksymät tarjoajat. Jokaisella onproviderId, nimi ja tieto siitä, pitääkö kirjautumissivun ohjata siihen automaattisesti.GET /api/auth/providers/:providerId/authorize, jolle annetaan kyselyparametreinacodeChallenge,redirectUrijastate, vastaa muodossa{ data: { authorizeUrl } }. Ohjaa henkilö sinne.- Tarjoaja ohjaa henkilön takaisin
redirectUri-osoitteeseesi koodin kanssa. Lähetä koodi takaisin pyynnölläPOST /api/auth/session, jonka runko on{ providerId, code, codeVerifier, redirectUri }. Kaikki neljä kenttää vaaditaan yhdessä, ja puutteellinen joukko antaa vastauksen400 EXTERNAL_AUTH_INCOMPLETE.
Istunnon uusiminen
Uusimistunnus ei ole koskaan vastauksen rungossa. Se asetetaan HTTP-only-evästeeseen nimeltä nessie_refresh, jonka polku on /api/auth ja elinikä oletuksena kolmekymmentä päivää (NESSIE_AUTH_REFRESH_TOKEN_TTL). Kun kutsut POST /api/auth/refresh tuon evästeen kanssa, eväste kulutetaan, käyttöön annetaan uusi käyttöoikeustunnus ja tilalle asetetaan uusi eväste. Tunnukset vaihtuvat jokaisella uusimisella, joten varastettu tunnus on käyttökelpoinen vain siihen asti, kunnes oikea asiakas uusii istunnon seuraavan kerran.
Selain, johon on kirjautunut useilla tileillä, säilyttää yhden tällaisen evästeen kullekin kirjautumiselle nimeltä nessie_refresh_<slot>, ja pyynnön kohde ilmoitetaan otsakkeella x-nessie-account-slot. Asiakas, joka ei lähetä tätä otsaketta, käsittelee evästettä nessie_refresh, mikä riittää komentoriviasiakkaalle.
Komentoriviasiakas tarvitsee siis evästetiedoston. curl-komennolla se tarkoittaa valitsinta --cookie-jar kirjautumispyynnössä ja valitsinta --cookie uusimispyynnössä, kuten alla olevassa esimerkissä.
Mitä tarkistetaan jokaisessa pyynnössä
Todennus ei ole pelkkä allekirjoituksen tarkistus. Ennen kuin käsittelijä suoritetaan, API tarkistaa tunnuksen allekirjoituksen ja voimassaoloajan, varmistaa, ettei istuntoa ole peruttu (sekä koko käyttäjän tunnusversion että yksittäisen istuntotunnuksen osalta), ja lataa kutsujan jäsenyyden organisaatiossa, jonka tunnus nimeää. Käytöstä poistettu jäsenyys tuottaa vastauksen 403. Kun organisaatio on sidottu ulkoiseen identiteettitarjoajaan, kutsujan nykyinen tila tarkistetaan kyseisen tarjoajan kanssa pyynnön yhteydessä eikä lueta tunnuksesta. Näin ylävirrassa poistettu käyttöoikeus lakkaa toimimasta heti eikä vasta seuraavan vanhenemisen yhteydessä.
Muut kuin istuntotunnukset
Muita bearer-tunnisteita on kaksi, eikä kumpikaan ole yleiskäyttöinen avain. Äänilaitteen tunnistetta hyväksytään vain äänipuheluiden reiteillä, ja agentin tunnistetta vain MCP-päätepisteessä. Jos jompaakumpaa esitetään muualla, pyyntö hylätään vastauksella 403, jossa mainitaan tunniste, eikä sitä yritetä uudelleen heikompana istuntona. Katso, miten agentin tunniste myönnetään, kohdasta MCP ja yhdistetyt työkalut.
Vastauksen rakenne
Jokainen onnistunut vastaus on olio, jossa on avain data. Juuressa ei ole paljasta taulukkoa eikä ylimmän tason hyötykuormaa, joten asiakkaan ei tarvitse koskaan erotella muotoja:
{
"data": { "id": "3f1c…", "label": "engineering" }
}Listaus-päätepisteet lisäävät rinnalle olion meta. Ylimmälle tasolle ei lisätä mitään muuta.
Virheissä on myös yksi muoto, riippumatta siitä, mikä ne aiheutti:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A message needs content or at least one attachment",
"field": "body",
"details": { "formErrors": [], "fieldErrors": {} }
}
}code on koneluettava osa, ja sen perusteella kannattaa haarautua. message on tarkoitettu ihmiselle. field ja details ovat mukana, kun virhe on riittävän tarkka paikantamaan. Käsittelemätön palvelinvirhe on aina 500 INTERNAL_ERROR kiinteällä viestillä. Alkuperäinen virheteksti kirjataan lokiin, mutta sitä ei palauteta, koska se on voinut kerätä pyynnön dataa matkallaan.
Ensimmäiset vastaan tulevat virhekoodit
| Tila | Koodi | Merkitys |
|---|---|---|
| 400 | VALIDATION_ERROR | Runko tai kysely ei vastannut skeemaa. |
| 401 | AUTH_REQUIRED | Bearer-tunnusta ei ole, tai otsake on virheellinen. |
| 401 | TOKEN_EXPIRED | Käyttöoikeustunnus on vanhentunut. Uusi istunto ja yritä uudelleen. |
| 401 | TOKEN_REVOKED | Istunto on suljettu tai kaikki istunnot on pakotettu sulkeutumaan. |
| 403 | ACCOUNT_DEACTIVATED | Tämän organisaation jäsenyys on poistettu käytöstä. |
| 404 | NOT_FOUND | Reittiä ei ole, tai kutsujalle näkyvää tietuetta ei ole. |
| 429 | RATE_LIMITED | Raja on täynnä. Lue Retry-After. |
| 500 | INTERNAL_ERROR | Käsittelemätön palvelinvirhe, joka on tarkoituksella epämääräinen. |
Sivutus
Listaus-päätepisteet sivutetaan läpinäkymättömällä avainkursorilla, ei offsetilla. Rivejä lisätään lukemisen aikana, ja offsetilla toinen sivu toistaisi hiljaa tietueen, jonka ensimmäinen sivu jo näytti.
Kolme kyselyparametria hyväksytään: cursor, limit ja direction (forward tai backward). Oletussivun koko on 25 ja enimmäismäärä 100. Suurempi arvo rajataan eikä hylätä. Päätepisteet, jotka myös järjestävät tai suodattavat, lisäävät parametrit sort, order ja vapaamuotoisen haun q.
Sivun meta kertoo, missä kohdassa olet:
{
"data": [ … ],
"meta": {
"hasMore": true,
"nextCursor": "2026-09-12T08:31:44.005Z|8b2f…",
"prevCursor": null,
"total": 134
}
}nextCursor ja prevCursor ovat molemmat todellisia: Edellinen ja Seuraava ovat molemmat painikkeita, joita ihmiset odottavat. Kursorit ovat läpinäkymättömiä. Palvelin koodaa niihin oman lajittelöavaimensa, ja asiakas, joka jäsentää tai rakentaa niitä, hajoaa heti, kun listan järjestys muuttuu. total on mukana useimmissa listoissa. Se jätetään pois, kun laskeminen ei ole mielekästä, kuten järjestetyissä hakutuloksissa.
Pyyntörajat
Rajat ovat kiinteitä aikaikkunoita, ja ne otetaan käyttöön ennen kuin pyynnön runkoa edes luetaan. Hylätty pyyntö on 429 koodilla RATE_LIMITED ja Retry-After-otsakkeella sekunteina.
Useimmat rajat perustuvat asiakkaan IP-osoitteeseen. Tunnistautumiseen liittyvillä rajoilla, eli kirjautumisella, uusimisella, salasanan uudelleentodistuksella ja MCP-tunnisteiden kirjoituksella, on lisäksi tilikohtainen laskuri, ja pyyntö hylätään, kun kumpi tahansa raja täyttyy. Näin yksi osoite, joka yrittää monelle tilille, ja yksi tili, jota hyökätään monesta osoitteesta, törmäävät molemmat seinään. Kirjautuminen sallii oletuksena 10 yritystä IP-osoitetta kohden ja 5 yritystä sähköpostiosoitetta kohden kymmenessä minuutissa. Viestin lähettäminen sallii oletuksena 60 viestiä minuutissa, ja kirjoitukset polun /api/agents alla 60 minuutissa. Jokainen raja on määritettävissä käyttöönottokohtaisesti, joten pidä näitä oletusarvoina eikä sopimuksena. Terveystarkistukset ja reaaliaikaiset virrat ovat vapautettuja.
Reaaliaikaisuus
Listan kyseleminen toistuvasti ei ole oikea tapa seurata keskustelua. Sen sijaan on kolme suoratoistavaa päätepistettä:
GET /api/events/stream— palvelimen lähettämät tapahtumat kaikelle, minkä kirjautunut henkilö voi nähdä.GET /api/threads/:threadId/stream— palvelimen lähettämät tapahtumat yhdelle ketjulle. Se kunnioittaaLast-Event-ID-otsaketta, joten uudelleenyhdistäminen jatkaa eikä aloita alusta.GET /api/activity— WebSocket, joka kuljettaa aktiivisuussyötettä.
Selaimet eivät voi asettaa otsakkeita WebSocket-kättelyyn, joten WebSocket-reitti hyväksyy käyttöoikeustunnuksen myös kyselyparametrina ?token=. Se on ainoa paikka, jossa tunnus saa olla URL-osoitteessa. Kaikki muut reitit ottavat sen otsakkeessa.
Resurssiperheet
Päätepisteitä on selvästi yli tuhat, joten niitä ei ole järkevää luetella. Ne ryhmittyvät perheisiin, ja kun tiedät perheen etuliitteen, yksittäiset reitit ovat ennustettavia: kokoelma etuliitteessä, tietue sen alla ja nimetyt toiminnot POST-alipolkuina.
| Perhe | Etuliite | Mitä se kattaa |
|---|---|---|
| Todennus | /api/auth | Kirjautuminen, uusiminen, uloskirjautuminen, nykyinen identiteetti ja henkilön omat istunnot. |
| Kanavat ja ketjut | /api/channels, /api/threads | Keskustelumalli: kanavat sisältävät ketjuja, ketjut sisältävät viestejä ja vastaukset sisäkkäin juuren alla. |
| Agentit | /api/agents | Agenttien määritykset, niiden kanavasidonnat, keskustelut, tehtävälistat ja tila. |
| Projektit ja taulut | /api/projects, /api/tasks, /api/iterations | Työnseuranta: taulut ja sarakkeet projektin alla, niillä olevat tehtävät ja niiden päällä olevat iteraatiot. |
| Tietämys | /api/knowledge-base | Versioitujen sivujen ja tiedostojen tilat, kommentit, takalinkit ja haku. |
| Posti | /api/mail, /api/mailbox-connections | Yhdistetyt postilaatikot, agenttien postilaatikot ja luonnokset, jotka agentti kirjoitti henkilön hyväksyttäväksi. |
| Hyväksynnät | /api/approvals | Jono toimista, joita agentti ei saa tehdä yksin, ja yksi kutsu, joka ratkaisee ne. |
| Tarkastusloki | /api/audit-log | Organisaation hash-ketjutettu tarkastusloki vahvistusrajapintoineen. Omistajat ja ylläpitäjät. |
| Kustannukset ja käyttö | /api/ledger, /api/billing | Token- ja kustannuskirjanpito, budjetit ja ajoajat sekä erikseen krediitit ja täydennykset. Omistajat ja ylläpitäjät. |
| Organisaatio ja tiimit | /api/organizations, /api/teams, /api/users | Organisaation, tiimien ja jäsenyyksien hallinta, kutsut mukaan lukien. |
| Triggerit | /api/triggers | Aikataulut ja webhookit, jotka käynnistävät agenttityötä, sekä niiden laukaisuhistoria. |
| Puhelut ja ääni | /api/calls, /api/voice | Kanavan sisäiset puhelut sekä äänenavustajan istunto, litterointi ja laitetunnisteet. |
| Suorittimet | /api/executors, /api/execution-environment-templates | Koneet, joilla agentit työskentelevät, niiden ympäristöt ja daemonin parituskanava. |
| Ajot | /api/runs | Käynnissä olevat agenttiajot: peruutus, jatkaminen, uudelleenkäynnistys ja sitominen suorittimeen. |
| Lataukset | /api/uploads, /api/attachments | Lataa tiedosto ensin ja liitä palautettu tunnus sitten viestiin. |
| Haku | /api/messages/search | Viestihaku, koko organisaatiossa tai yhteen kanavaan rajattuna. |
| Salaisuudet ja asetukset | /api/secrets, /api/settings/scoped | Vain kirjoitettava salaisuuksien tallennus eksplisiittisillä oikeuksilla ja kerroksittaiset asetusarvot. |
| Yhdistetyt työkalut | /api/mcp | MCP-palvelimet, joihin tämä instanssi ottaa yhteyden. Katso MCP ja yhdistetyt työkalut. |
| Terveys | /api/health | Elinkelpoisuus ja valmius, molemmat julkisia. /api/health/ready tarkistaa myös tietokannan. |
Oikeudet tarkistetaan reittikohtaisesti, ei perheittäin. Karkeasti sanottuna tarkastusloki, kustannusrekisteri, käytäntösäännöt ja päättelyn hallintapinta ovat organisaation omistajien ja ylläpitäjien pintoja. Keskustelut, projektit, tietämys ja hyväksynnät ovat taas avoinna kaikille jäsenille, ja ne rajautuvat sen mukaan, mitä kyseinen jäsen todella näkee.
Esimerkkejä
Kirjaudu sisään ja säilytä uusimisevästeet
local-tilassa olevassa instanssissa salasanalla. Käyttöoikeustunnus tulee vastauksen rungossa, ja uusimistunniste menee evästetiedostoon.
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
}
}
}
}Kun tunnus vanhenee, vaihda eväste uuteen:
curl -sS -X POST https://api.example.com/api/auth/refresh \
--cookie nessie.cookies --cookie-jar nessie.cookiesVastaus on sama { token, me }-muoto, ja evästetiedostossa on nyt uusittu uusimistunniste.
Listaa kanavat, jotka näet
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
}
]
}Lisää ?teamId=… rajataksesi yhteen tiimiin tai ?includeArchived=true sisällyttääksesi arkistoidut kanavat. defaultThreadId on se ketju, johon lähetät seuraavaksi.
Lähetä viesti
Viestissä on oltava joko content-sisältöä tai vähintään yksi ladattu liite. Lähetä Idempotency-Key, niin uudelleen lähetetty pyyntö ratkeaa samaan viestiin, jonka ensimmäinen yritys loi, eikä lähetä toista kopiota.
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."}'Uusi viesti on 201:
{
"data": {
"message": {
"id": "d70e…",
"threadId": "c41a…",
"role": "user",
"content": "Deploying the migration now.",
"createdAt": "2026-09-16T09:04:11.882Z"
},
"pendingAgentInvites": []
}
}Saman idempotenssiavaimen toisto vastaa 200, alkuperäisellä viestillä ja tyhjällä pendingAgentInvites-taulukolla, koska ensimmäinen yritys on jo hoitanut taulukon kuvaamat ilmoitukset ja lähetyksen.
Kaksi tämän reitin virhevastausta kannattaa käsitellä erikseen. Chatin pituusrajan ylittävä sisältö on 413 MESSAGE_TOO_LARGE, ja oikea vastaus on ladata teksti tiedostona. Sisältö, joka rakenteellisesti näyttää tunnukselta, on 422 SECRET_INTERCEPTED. Palvelin hylkää sen ennen kuin viesti tallennetaan, välitetään tai kirjataan lokiin, ja tunnus kuuluu tallennettavaksi osoitteeseen /api/secrets.