Node

Get started with the Nookara Node SDK

Install nookara from npm and call any Nookara route from your server, with your registered app's sign-in in front of it.

1. Install it

Needs Node 18 or newer. No dependencies, and it works with both import and require. Types are included.

npm install nookara
import { Client, scope_mask } from 'nookara';
// or: const { Client } = require('nookara');

The package is nookara on npm. It covers REST. Sign-in helpers, websockets, the bot gateway, message signing and encrypted DMs are only in the Python SDK for now.

2. Create an app

  1. Go to My Account > Apps and press Create app.
  2. Add the address your site runs on to its authorized URLs, like https://mygame.example.com. While you're building, add http://localhost too (any port).
  3. Choose its scopes, then copy its ID. It looks like app_ followed by 20 letters and numbers.

A new app is in development: only you and up to 5 testers can sign in with it. Create a Nookara app explains verification and the scope choices.

3. Sign people in

An app's token only works from the app's authorized URLs. In a browser that's the page's own address. From Node you say it yourself with the origin option, and the SDK sends it as the Origin header on every request.

const APP_ID = 'app_0123456789abcdef0123';
const ORIGIN = 'https://mygame.example.com';
const nookara = new Client(null, { origin: ORIGIN });

// a) start: get a code and send the person to Nookara's sign-in screen
const { code } = await nookara.post_auth_ext_code({
  json: { app_id: APP_ID, redirect_uri: ORIGIN + '/signed-in' },
});
// redirect the browser to:
const loginUrl = 'https://nookara.cc/login?code=' + encodeURIComponent(code);

After the person approves, the browser goes to /signed-in#nookara_code=CODE&nookara_grant=GRANT. The part after # never reaches your server, so the /signed-in page passes it on:

<script>
  fetch('/nookara/finish', { method: 'POST', body: location.hash.slice(1) })
    .then(() => { history.replaceState(null, '', '/'); });
</script>
// b) finish: swap the one-time grant for the token
const form = new URLSearchParams(body);           // body of POST /nookara/finish
const { token, scopes } = await nookara.post_auth_ext_code_exchange({
  json: { code: form.get('nookara_code'), grant: form.get('nookara_grant') },
});
const user = new Client(token, { origin: ORIGIN });
const me = await user.get_account_me();
console.log(me.account.username);

Check that nookara_code is the code you started with. A grant works once, and a code expires after five minutes. Keep the token on your server like a password: never put it in a URL or send it anywhere but Nookara.

People can turn scopes off. Your app asks for its scopes, but the person can switch any of them off on the sign-in screen. scopes is what they allowed, and has_scope(scopes, 'CHAT') checks one. A route they didn't allow throws ScopeError.

4. Call the API

Every route is one method, with the same name as in the Python SDK. Path parameters go in the same object as query, json, data and files.

await user.post_friends_request({ json: { username: 'someone' } });
await user.put_storage_by_storageid_by_key({ storageId: 'save', key: 'level', json: { value: '4' } });
const { value } = await user.get_storage_by_storageid_by_key({ storageId: 'save', key: 'level' });

// or any path
await user.request('GET', '/currency/balance');

Storage IDs are your app's own: whatever ID you pick, it lives in your app's folder on that person's account, and nothing else can change it.

Taking payments

// send someone to checkout. No credits permission needed
const { checkout_url } = await user.add_to_cart('prod_123');

// or, if they gave your app Transfer Credits: up to 100 credits a day per app per person
const { total } = await user.quote_directly([{ product_id: 'prod_123' }]);
await user.pay_directly([{ product_id: 'prod_123' }], total);

Take payments covers products, memberships and checkout.

Errors

import { APIError, ScopeError, TransportError } from 'nookara';

try {
  await user.post_friends_request({ json: { username: 'someone' } });
} catch (err) {
  if (err instanceof ScopeError) console.log('Not allowed, sign in again to ask for it');
  else if (err instanceof APIError) console.log(err.status, err.error, err.retry_after);
  else if (err instanceof TransportError) console.log('Network problem. It may still have gone through.');
  else throw err;
}

Nothing is retried for you and redirects are refused, so a token can't follow one somewhere else.

Bots

const bot = new Client(process.env.BOT_TOKEN, { authScheme: 'Bot' });

Bot tokens don't go through an app.

The old sign-in stops on December 3rd. Starting a sign-in with project_name and permissions_integer is the legacy login. It and the tokens it made stop working on 3 December 2026. Send app_id instead.

Questions

Why does my token give origin_not_authorized?

An app's token only works from its authorized URLs. Make the client with the origin option set to one of them.

Can I use it in the browser?

It's made for Node. In a browser, the page's own address is the origin, and the sign-in can use a popup: see Create a Nookara app.

Where is every route listed?

The Nookara API guide has every route with its method name, scopes and a raw request. The Node method has the same name as the Python one.