KDB knowledge

API tokens

Named, revocable secrets for apps - each acts as one user, and DROP TOKEN stops it at once.

An API token is a long secret an app sends with every request, like the server's --token. The difference: you can have many, each has a name, each acts as one user (with that user's rights), and you can remove one without touching the others.

--token of kdb serveAPI token
How manyoneas many as you like
Rightseverythingthe rights of its user
Change or revokerestart the server with another oneDROP TOKEN name, at once
Kepton the command linein the data folder (only its hash)

Give each app its own token. When one app is retired or its secret leaks, drop that token; the other apps go on.

Example: A token for the chart app, a read-only user

Setup:

CREATE USER admin WITH PASSWORD 'Long-Admin-Passw0rd' ROLE admin;
CREATE USER charts WITH PASSWORD 'Chart-app-secret-11' ROLE read;
CREATE TOKEN chart_app FOR USER charts EXPIRES IN 90 DAYS;
SHOW TOKENS;

Result:

CREATE TOKEN chart_app FOR USER charts EXPIRES IN 90 DAYS

name (STRING)user (STRING)token (STRING)expires (TIMESTAMP)
chart_appchartskdbt_kUp9nunNEhbrCOeojEFj6CzKw4NXzO9QwTbS_N6JogM2027-01-20T05:43:29.306Z

(1 row)

token 'chart_app' for user 'charts' created: copy it now, it is shown only this once. Send it as Authorization: Bearer <token>

SHOW TOKENS

name (STRING)user (STRING)prefix (STRING)created (TIMESTAMP)expires (TIMESTAMP)expired (BOOL)created_by (STRING)last_used (TIMESTAMP)
chart_appchartskdbt_kUp9...2026-10-22T05:43:29.311Z2027-01-20T05:43:29.306ZfalseNULLNULL

(1 row)

CREATE TOKEN

Syntax:

CREATE TOKEN name [FOR USER user] [EXPIRES IN n DAYS]

Makes a new token and shows its secret once.

PartMeaning
nameletters, digits, _ and -, 1 to 63 characters; unique (case does not matter). Say which app uses it.
FOR USER userthe user it acts as. Without it: the user who runs the statement.
EXPIRES IN n DAYSit stops working after that many days (1 to 99999). Without it: never.

Example: Two apps, two tokens for one user

Setup:

CREATE USER admin WITH PASSWORD 'Long-Admin-Passw0rd' ROLE admin;
CREATE USER loader WITH PASSWORD 'Loader-secret-long-5' ROLE write;
CREATE TOKEN price_feed FOR USER loader;
CREATE TOKEN backfill FOR USER loader EXPIRES IN 7 DAYS;

Result:

CREATE TOKEN price_feed FOR USER loader

name (STRING)user (STRING)token (STRING)expires (TIMESTAMP)
price_feedloaderkdbt_sBAa0yQr3ugYZgxKJaH3I_sUuw3XGGQT1njwV0bRBFANULL

(1 row)

token 'price_feed' for user 'loader' created: copy it now, it is shown only this once. Send it as Authorization: Bearer <token>

CREATE TOKEN backfill FOR USER loader EXPIRES IN 7 DAYS

name (STRING)user (STRING)token (STRING)expires (TIMESTAMP)
backfillloaderkdbt_v0iut_osA-e4LN4hmCIbK3KKnEtlFnuniuYEBTHxkWM2026-10-29T05:43:29.419Z

(1 row)

token 'backfill' for user 'loader' created: copy it now, it is shown only this once. Send it as Authorization: Bearer <token>

Example: The name is taken (shows an error)

Setup:

CREATE USER admin WITH PASSWORD 'Long-Admin-Passw0rd' ROLE admin;
CREATE TOKEN price_feed FOR USER admin;
CREATE TOKEN price_feed FOR USER admin;

Result:

Error: token 'price_feed' already exists

Example: A token acts as a user (shows an error)

Setup:

CREATE USER admin WITH PASSWORD 'Long-Admin-Passw0rd' ROLE admin;
CREATE TOKEN price_feed;

Result:

Error: CREATE TOKEN needs FOR USER <name> here: this session has no user (the server's --token, or a local tool), and a token always acts as one user

DROP TOKEN

Syntax:

DROP TOKEN [IF EXISTS] name

Revokes a token. Every request with it gets 401 from then on: the API token is wrong, has expired or was dropped (SHOW TOKENS).

Example

Setup:

CREATE USER admin WITH PASSWORD 'Long-Admin-Passw0rd' ROLE admin;
CREATE TOKEN price_feed FOR USER admin;
DROP TOKEN price_feed;
DROP TOKEN IF EXISTS price_feed;

Result:

DROP TOKEN price_feed

token 'price_feed' dropped: it stops working at once

DROP TOKEN IF EXISTS price_feed

token 'price_feed' does not exist

SHOW TOKENS

Syntax:

SHOW TOKENS

Lists the tokens. Never the secrets: only the first letters, so you can tell which one an app has.

ColumnMeaning
name, userthe token and the user it acts as
prefixits first letters, like kdbt_Ab3x...
created, expireswhen it was made; when it stops (NULL = never)
expiredtrue once expires has passed
created_bywho made it (NULL: the --token or a local tool)
last_usedits last request since the server started (NULL: none yet)

Example

Setup:

CREATE USER admin WITH PASSWORD 'Long-Admin-Passw0rd' ROLE admin;
CREATE TOKEN price_feed FOR USER admin EXPIRES IN 30 DAYS;
SHOW TOKENS;

Result:

name (STRING)user (STRING)prefix (STRING)created (TIMESTAMP)expires (TIMESTAMP)expired (BOOL)created_by (STRING)last_used (TIMESTAMP)
price_feedadminkdbt_J9vW...2026-10-22T05:43:29.638Z2026-11-21T05:43:29.632ZfalseNULLNULL

(1 row)

Where tokens and logins are kept

Both live in the hidden _system database of the data folder, as hashes only:

TableHolds
api_tokensname, user, the SHA-256 of the secret, its first letters, times
login_sessionsthe SHA-256 of each login token of POST /api/login and the console, its user and when it ends

So a server restart logs nobody out, and apps with a token go on. A login still ends after 12 hours, at logout, or when the user gets a new password or is dropped. An older KDB program does not know these tables: there, tokens do not work and everyone logs in again.