Token Listing
Token listing returns a high-level overview of the tokens a user can still use. The response includes user-wide totals and, when valid tokens exist, a list of active token records with their public identifiers and usage metadata.
The IAM service builds this response in two steps. It first counts every token
owned by the user, then it queries only the rows where valid = 1 to build
the returned list.
public_identifier so authenticated clients can perform later management
actions without exposing the raw secret.You can fetch the token list in 2 ways:
- Directly calling
getAllValidTokensList. - Calling the
GET /api/manage/list-metadataendpoint from an authenticated client.
Listing Tokens
You can list tokens either directly in the library or through the authenticated
route. Unlike the other management actions, token listing does not use
privateActionManager.
Using the library
To fetch the current valid token list directly, you call
getAllValidTokensList. This function counts all user tokens and then returns
the metadata for the subset that is still valid.
import { getAllValidTokensList } from '@riavzon/auth'
const results = await getAllValidTokensList(1234)
if (results.ok) {
console.log(results.data.totalValidTokens)
console.log(results.data.tokenList)
}
On success you get back an object with:
{
ok: true,
date: new Date().toISOString(),
data: {
total: 6,
totalInvalidTokens: 2,
totalValidTokens: 4,
tokenList: [
{
id: 12,
name: 'server token',
created_at: '2026-05-01T10:00:00.000Z',
expires_at: '2026-05-01T11:00:00.000Z',
restricted_to_ip_address: ['203.0.113.10'],
public_identifier: 'public_identifier',
last_used: '2026-05-01T10:30:00.000Z',
usage_count: 19,
privilege_type: 'restricted'
}
]
}
}
The total, totalInvalidTokens, and totalValidTokens fields are user-wide.
They describe all token rows for the user, not only the tokenList array.
If the user has no valid tokens, the helper still returns ok: true with the
count fields. In that case tokenList is omitted.
On error, getAllValidTokensList returns the catch branch:
{
ok: false,
date: new Date().toISOString(),
reason: 'Server error'
}
This happens when the count query or the valid-token query throws.
Signature
The direct helper exposes the following signature:
export async function getAllValidTokensList(
userId: number
): Promise<Results<AllValidTokensList>>
Parameters
The listing helper accepts the following parameter:
| Field | Type | Description |
|---|---|---|
userId | number | The user id whose tokens should be listed. |
Return type
The listing helper returns Results<AllValidTokensList>.
AllValidTokensList contains the following fields:
| Field | Type | Description |
|---|---|---|
total | number | The total number of token rows owned by the user. |
totalInvalidTokens | number | The number of invalid token rows owned by the user. |
totalValidTokens | number | The number of valid token rows owned by the user. |
tokenList | TokenList[] | undefined | The current list of valid tokens, omitted when no valid rows exist. |
TokenList contains the following fields on successful responses:
| Field | Type | Description |
|---|---|---|
id | number | The internal database id of the token. |
name | string | The token name. |
created_at | string | The creation timestamp. |
expires_at | string | null | The expiration timestamp, or null when the token does not expire. |
restricted_to_ip_address | string[] | null | The current IP restriction list, or null when unrestricted. |
public_identifier | string | The public identifier used for later management actions. |
last_used | string | null | The last successful usage timestamp. |
usage_count | number | The current usage count. |
privilege_type | 'demo' | 'restricted' | 'protected' | 'full' | 'custom' | The stored privilege type. |
userId. It does not verify a token,
publicIdentifier, or caller session for you. Only call it directly in
trusted server-side code.privateActionManager support
Token listing does not have a privateActionManager action. The manager action
type only supports revoke, rotate, metadata, ip-restriction-update, and
privilege-update.
That is why the authenticated route calls getAllValidTokensList directly
after the session checks succeed.
Using the route
Let's say you want to fetch the current valid token list from your authenticated client or BFF.
The listing route is available at:
GET /api/manage/list-metadata HTTP/1.1
This action is GET only. It does not use a request body.
On success you will get the following response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"ok": true,
"date": "current date",
"data": {
"total": 6,
"totalInvalidTokens": 2,
"totalValidTokens": 4,
"tokenList": [
{
"id": 12,
"name": "server token",
"created_at": "2026-05-01T10:00:00.000Z",
"expires_at": "2026-05-01T11:00:00.000Z",
"restricted_to_ip_address": ["203.0.113.10"],
"public_identifier": "public_identifier",
"last_used": "2026-05-01T10:30:00.000Z",
"usage_count": 19,
"privilege_type": "restricted"
}
]
}
}
Standard authentication, shared validation, and common management-route errors are documented on the introduction page.
The route-specific failures for listing are the following:
If you call the action through POST /api/manage/list-metadata, the controller
returns Bad Request because the list-metadata branch explicitly rejects any
method other than GET.
If getAllValidTokensList fails, the controller returns 500 Internal Server Error
and forwards the helper reason. In the current implementation that reason is
Server error.
Those route-specific failure responses look like this:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"ok": false,
"date": "current date",
"reason": "Bad Request"
}
HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
{
"ok": false,
"date": "current date",
"reason": "Server error"
}
Rate Limits
The listing endpoint does not have a dedicated operation limiter. It only uses the following configuration:
rate_limiters.apiTokensLimiters.generalUnionLimiter- AburstLimiterand aslowLimiterunion limiter. It enforces no more than one request per second, and only 50 per minute. No consecutive triggers in this limiter are provided, and triggering it again will result in a permanent ban.burstLimiter- Will block the client for 15 minutes.slowLimiter- Will block for 1 hour.
list-metadata branch does not call
resetApiUnionLimiters on success. The general union limiter is not restarted
after a successful token listing request.Listing Process
Token listing reads the current valid tokens for one user without touching any individual token state.
Count the user's token inventory
The helper starts by calling totalUserTokensCount(userId). That returns the
number of valid tokens, invalid tokens, and the total token count for the user.
Query the valid token rows
After counting, the helper queries api_tokens for rows where user_id = ?
and valid = 1. The result includes only metadata fields needed for listing
and later dashboard actions.
Normalize the IP restriction field
If valid rows exist, the helper maps each row and parses
restricted_to_ip_address from its stored JSON value. That means the response
returns string[] for restricted tokens and null for unrestricted tokens.
Return the combined overview
The final payload returns the user-wide counts plus the tokenList array when
valid rows exist. This gives the client a single response that can power a
dashboard overview and later management actions.
Configuration Reference
This configuration key controls token listing throttling in the service.
Rate limiters
The listing flow relies on the following limiter configuration:
| Limiter | Description |
|---|---|
rate_limiters.apiTokensLimiters.generalUnionLimiter | General burst limiter for token listing requests |