API reference
NanakoHome exposes its application API under /api/v1 and a separate OAuth provider surface under /oauth. Examples on this page use the public-facing configuration address https://api.nanako.org/api/v1; replace the origin with the address of the deployment you are calling. When VITE_API_URL is unset, the checked frontend source falls back to http://localhost:8080/api/v1.
These route prefixes and client behavior were checked against frontend/src/services/api.ts and backend/internal/api/router.go on 2026-09-10. The public address is a configuration target, not proof that a deployment is online. Nanako does not currently include a checked-in OpenAPI contract, so request and response types may evolve with the application.
Browser-session authentication
Protected /api/v1 requests carry a short-lived access token:
Authorization: Bearer <access_token>
The NanakoHome browser client stores this token in memory and the current tab's sessionStorage. It sends requests with credentials so the server can rotate the refresh token in an HttpOnly cookie. When a protected request returns 401, the client makes one coalesced POST /api/v1/auth/refresh attempt and retries the original request after success.
Do not persist a NanakoHome session refresh token in application JavaScript. This browser-session mechanism is separate from the OAuth access and refresh tokens issued to approved third-party clients.
Most JSON errors use an error field. Upload endpoints use multipart form data, OAuth token endpoints use form-encoded data, and task/notification streams return text/event-stream.
Building a third-party integration that signs users in with their Nanako account is a different mechanism with its own reference: see OAuth 2.0.
Public application routes
The router mounts the following routes without a Nanako browser session. Authentication, verification and pickup endpoints are rate-limited and may also depend on deployment configuration.
| Method and route | Purpose |
|---|---|
GET /health | Process health response |
GET /api/v1/auth/methods | Configured sign-in methods and optional Geetest ID |
GET /api/v1/auth/pubkey | Public key used by the browser's password encryption helper |
POST /api/v1/auth/check | Check whether a phone/email account exists and has a password |
POST /api/v1/auth/sms/send | Request an SMS verification code |
POST /api/v1/auth/email/send | Request an email verification code |
POST /api/v1/auth/register/phone | Register with a phone code and password |
POST /api/v1/auth/register/email | Register with an email code and password |
POST /api/v1/auth/login/phone | Password login by phone |
POST /api/v1/auth/login/email | Password login by email |
POST /api/v1/auth/sms/login | Verification-code login by phone |
POST /api/v1/auth/email/login | Verification-code login by email |
POST /api/v1/auth/password/reset/phone | Reset a password with a phone code |
POST /api/v1/auth/password/reset/email | Reset a password with an email code |
GET /api/v1/auth/{google,github,apple}/url | Start a configured external identity flow |
GET /api/v1/auth/{google,github}/callback | Google or GitHub callback |
POST /api/v1/auth/apple/callback | Apple form-post callback |
POST /api/v1/auth/exchange | Exchange the one-time frontend callback code for a browser session |
POST /api/v1/auth/refresh | Rotate the HttpOnly refresh cookie and issue an access token |
POST /api/v1/auth/2fa/verify | Complete login with TOTP or a recovery code |
GET /api/v1/config/features | Public application visibility/maintenance map |
GET /api/v1/todo/public/:uuid | Read a shared public Todo board |
GET /api/v1/showcase/apps | Read the public application showcase |
POST /api/v1/honeycomb/pickup | Redeem a Honeycomb pickup code |
GET /api/v1/honeycomb/download/:token | Download a redeemed Honeycomb file |
GET /s/:slug | Fetch a public hosted script |
An authentication response may instead return {requires_2fa: true, pending_token: "..."}. In that case, no access token has been issued; complete /api/v1/auth/2fa/verify first.
Feature-gated application routes can return HTTP 503 with error: "feature_disabled". Clients should show a maintenance state and must not infer availability from a home-page card alone.
Protected route groups
The current browser client uses these authenticated groups. This table is an inventory, not a promise that every route is intended for third-party use.
| Prefix | Operations in the checked router |
|---|---|
/api/v1/user | Current profile, setup, profile update, linked identities, login sessions and TOTP; the account-deletion route is registered but blocked by the UUID/integer defect noted below |
/api/v1/auth | Logout and external-identity binding URLs |
/api/v1/user/password | Set or change a password (POST /set, POST /change) |
/api/v1/preferences | Favorites, recent use and per-application settings |
/api/v1/pomodoro | Record sessions and read statistics |
/api/v1/todo | Boards, items, sharing and user lookup |
/api/v1/honeycomb | Deposit and manage files |
/api/v1/scripts | Create, list, read, update and delete hosted scripts |
/api/v1/translate | Upload, list, inspect, stream, cancel and download translation tasks; list providers |
/api/v1/mineru | Upload, list, inspect, stream, cancel and download parsing tasks |
/api/v1/images | Upload, list and delete images |
/api/v1/ghspeed | Manage download keys and read usage, logs and edge information |
/api/v1/oauth | Developer application, client, grant and authorization-log management |
/api/v1/apps/uptime/launch | Create a one-time SSO redirect into the external NanoUptime application |
/api/v1/notifications | Inbox, unread count, SSE stream, read/archive actions, preferences and per-client mute settings |
/api/v1/admin | Administrator-only users, email, feature, translation, showcase and OAuth management |
Browser Web Push and APNs are not active API surfaces in this router. The notification preference matrix reserves these channel names, but there are no device-subscription registration routes in the checked implementation.
DELETE /api/v1/user/account is registered, but the checked handler type-asserts the authenticated UUID user ID as uint. A normal authenticated request therefore fails before its deletion transaction. Do not offer this route as a working operation until the handler is corrected and tested.
OAuth 2.0 / OpenID Connect provider
Approved developers create clients in the Nanako Developer Center. Register every redirect URI exactly; authorization rejects unregistered values. The checked provider supports the authorization-code flow, confidential clients using client_secret, and PKCE using plain or S256.
| Method and route | Purpose |
|---|---|
GET /oauth/authorize | Validate an authorization request and send the browser to Nanako's consent UI |
POST /oauth/token | Exchange an authorization code or rotate an OAuth refresh token |
GET /oauth/userinfo | Return claims allowed by the granted scopes |
POST /oauth/revoke | Revoke an access or refresh token; confidential client authentication is required |
GET /.well-known/openid-configuration | Provider discovery metadata |
Authorization parameters are client_id, redirect_uri, response_type=code, scope, optional state, optional code_challenge and code_challenge_method, and optional prompt=none. Supported scopes in the implementation are:
| Scope | Returned user information |
|---|---|
openid | Stable sub identifier |
profile | name and picture |
email | email and email_verified when present |
phone | phone_number and phone_number_verified when present |
The token endpoint accepts application/x-www-form-urlencoded data. For an authorization-code exchange, send grant_type=authorization_code, the code, client_id, the exact redirect_uri, and either the matching code_verifier for a PKCE-issued code or client_secret for a confidential flow. The implementation returns bearer access tokens with a two-hour lifetime and rotates OAuth refresh tokens.
The checked router mounts token, user-info and revocation handlers at /oauth/*, while the current discovery handler constructs those three URLs under /api/v1/oauth/*. Validate the target deployment before relying on automatic discovery. This documentation uses the paths actually mounted by backend/internal/api/router.go.
The current token responses do not contain an id_token, even though discovery advertises RS256 ID-token signing. Discovery and user-info support therefore do not establish a complete OpenID Connect ID-token flow.
PKCE permits an authorization-code exchange without a client secret. The refresh-token and revocation handlers still require client_secret unconditionally; a public browser client cannot use PKCE alone to refresh or revoke tokens through these handlers.
Never expose a confidential client secret in browser code. The Developer Center displays a newly created or regenerated secret once; store it in the server-side component of your application.