Skip to main content

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.

Configuration is not availability

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 routePurpose
GET /healthProcess health response
GET /api/v1/auth/methodsConfigured sign-in methods and optional Geetest ID
GET /api/v1/auth/pubkeyPublic key used by the browser's password encryption helper
POST /api/v1/auth/checkCheck whether a phone/email account exists and has a password
POST /api/v1/auth/sms/sendRequest an SMS verification code
POST /api/v1/auth/email/sendRequest an email verification code
POST /api/v1/auth/register/phoneRegister with a phone code and password
POST /api/v1/auth/register/emailRegister with an email code and password
POST /api/v1/auth/login/phonePassword login by phone
POST /api/v1/auth/login/emailPassword login by email
POST /api/v1/auth/sms/loginVerification-code login by phone
POST /api/v1/auth/email/loginVerification-code login by email
POST /api/v1/auth/password/reset/phoneReset a password with a phone code
POST /api/v1/auth/password/reset/emailReset a password with an email code
GET /api/v1/auth/{google,github,apple}/urlStart a configured external identity flow
GET /api/v1/auth/{google,github}/callbackGoogle or GitHub callback
POST /api/v1/auth/apple/callbackApple form-post callback
POST /api/v1/auth/exchangeExchange the one-time frontend callback code for a browser session
POST /api/v1/auth/refreshRotate the HttpOnly refresh cookie and issue an access token
POST /api/v1/auth/2fa/verifyComplete login with TOTP or a recovery code
GET /api/v1/config/featuresPublic application visibility/maintenance map
GET /api/v1/todo/public/:uuidRead a shared public Todo board
GET /api/v1/showcase/appsRead the public application showcase
POST /api/v1/honeycomb/pickupRedeem a Honeycomb pickup code
GET /api/v1/honeycomb/download/:tokenDownload a redeemed Honeycomb file
GET /s/:slugFetch 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.

PrefixOperations in the checked router
/api/v1/userCurrent 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/authLogout and external-identity binding URLs
/api/v1/user/passwordSet or change a password (POST /set, POST /change)
/api/v1/preferencesFavorites, recent use and per-application settings
/api/v1/pomodoroRecord sessions and read statistics
/api/v1/todoBoards, items, sharing and user lookup
/api/v1/honeycombDeposit and manage files
/api/v1/scriptsCreate, list, read, update and delete hosted scripts
/api/v1/translateUpload, list, inspect, stream, cancel and download translation tasks; list providers
/api/v1/mineruUpload, list, inspect, stream, cancel and download parsing tasks
/api/v1/imagesUpload, list and delete images
/api/v1/ghspeedManage download keys and read usage, logs and edge information
/api/v1/oauthDeveloper application, client, grant and authorization-log management
/api/v1/apps/uptime/launchCreate a one-time SSO redirect into the external NanoUptime application
/api/v1/notificationsInbox, unread count, SSE stream, read/archive actions, preferences and per-client mute settings
/api/v1/adminAdministrator-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.

Known account-deletion defect

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 routePurpose
GET /oauth/authorizeValidate an authorization request and send the browser to Nanako's consent UI
POST /oauth/tokenExchange an authorization code or rotate an OAuth refresh token
GET /oauth/userinfoReturn claims allowed by the granted scopes
POST /oauth/revokeRevoke an access or refresh token; confidential client authentication is required
GET /.well-known/openid-configurationProvider 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:

ScopeReturned user information
openidStable sub identifier
profilename and picture
emailemail and email_verified when present
phonephone_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.

Discovery metadata mismatch

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.

Partial OIDC and public-client limitations

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.