nooks
GitHubInstall

Using the API

The base URL, how a token authenticates, and what comes back when something goes wrong.

Everything the app does, Nooks does over REST. There is no endpoint the browser has that a script does not, and a check in CI refuses one that ships without a route. If you can do it in the interface, you can do it from a shell.

The reference has a page per endpoint, generated from the same definitions the server is built from. This page is what you need before any of them.

The base URL

Everything lives under /api/v1 on your own instance:

https://nooks.example.com/api/v1

There is no hosted API, and no account anywhere but yours. The instance you point at is the one you run.

Authenticating

Every request carries an access token as a bearer token:

curl https://nooks.example.com/api/v1/lists \
  -H "Authorization: Bearer $NOOKS_TOKEN"

Make one in Settings → Access tokens. The secret is shown once, when it is created, and never again. Nooks stores only a hash of it, so a token that is lost is replaced rather than recovered.

What a token can reach

A token is somebody's access, narrowed. It never has more than the member who made it, and three things narrow it further:

  • The lists you pick. A list a token was not given is invisible to it. Not forbidden: invisible. It cannot be read, and it cannot be discovered to exist.
  • Read, write and delete, as separate abilities. A token that may write but not delete can tick an item off and cannot remove it.
  • An expiry, which you choose when you make it.

Admin work — adding a member, deciding a join request, changing instance settings, making another token — needs a signed-in browser. No access token can do it, over REST or anywhere else. That is why those endpoints appear in the reference but refuse a bearer token.

Clients that are not scripts

A client holding a person's password rather than a token signs in for a pair of tokens: a refresh token that only ever moves in an HttpOnly cookie, and a short-lived access token returned in the body. POST /api/v1/auth/refresh exchanges the first for a fresh second. A browser app uses this; a script should use an access token instead and skip it.

When something goes wrong

Errors come back as JSON with the status on the response:

{
  "code": 7,
  "message": "only an admin can do that",
  "details": []
}

The message is written to be read by a person: the same sentence the app shows.

StatusMeans
400A field is missing or malformed, or the instance is in a state where this cannot be done yet
401No token, or one that has expired or been revoked
403A valid token that is not allowed to do this: the wrong ability, or a list it was not given
404No such thing, or none this token is allowed to see
409It already exists
500Nooks failed. This is a bug, and the message says what it was doing

A 403 and a 404 can both mean "not yours". Which one you get depends on whether the thing would be visible at all: a list outside a token's scope answers 404, because telling you it exists is itself something the token is not allowed to know.

What Nooks does not do

Worth knowing before you write against it:

  • No pagination. A household's lists fit in one response, and inventing cursors for a hundred rows would be a protocol nobody needs.
  • No rate limiting. It is your server. If you want limits, your reverse proxy is a better place for them than the application.
  • No webhooks. Changes stream to the app over server-sent events; there is no outbound delivery to a URL you register.

Pointing an assistant at it

An assistant does not need any of this. Nooks speaks the Model Context Protocol at /mcp, authenticated with the same access token, reaching exactly what the token reaches. See the MCP page.

On this page