Metadata
Metadata returns a snapshot for one API token and a summary of the owning user's token counts. The response combines token-level details, such as usage and timestamps, with user-wide totals for valid, invalid, and total tokens.
The IAM service builds this response in two steps. It first verifies the target token without consuming usage counters, then it queries the database again to count every token owned by the same user.
You can fetch metadata in 3 ways:
- Directly calling
getUserApiKeysMetaData. - Using the
privateActionManagerto validate ownership before fetching. - Calling the
POST /api/manage/metadataendpoint from an authenticated client.
Fetching Metadata
You can fetch metadata either directly in the library or through the manager-backed route. The direct helper resolves one token and the owning user's counts, while the route adds ownership validation and authenticated request protections.
Using the library
To fetch metadata directly, you call getUserApiKeysMetaData. This function
verifies the token, skips IP checks, skips usage counter updates, and then
fetches the user's token counts.
import { getUserApiKeysMetaData } from '@riavzon/auth'
const results = await getUserApiKeysMetaData(token, 'restricted')
if (results.ok) {
console.log(results.data.tokenMeta.name)
console.log(results.data.counts.totalValidTokens)
}
On success you get back an object with:
{
ok: true,
date: new Date().toISOString(),
data: {
tokenMeta: {
name: 'server token',
tokenId: 12,
userId: 42,
createdAt: '2026-05-01T10:00:00.000Z',
expiresAt: '2026-05-01T11:00:00.000Z',
lastUsed: '2026-05-01T10:30:00.000Z',
usageCount: 19,
providedPrivilege: 'restricted'
},
counts: {
totalInvalidTokens: 2,
totalValidTokens: 4,
total: 6
}
}
}
The counts object is user-wide. It does not only describe the selected
token. It includes every token row owned by the same user.
The helper forwards the stored token metadata from verifyApiKey with
skipCountUpdates = true. Because of that, usageCount and lastUsed are
read-only snapshots and are not incremented by the metadata request.
On error, getUserApiKeysMetaData returns the branch that failed.
If verifyApiKey cannot validate the token, the helper forwards that reason:
{
ok: false,
date: new Date().toISOString(),
reason: 'Invalid key'
}
This happens when the token is missing, revoked, malformed, or does not match
the provided privilege. Because the helper calls verifyApiKey with
byPassIpCheck = true, it does not return Invalid Host.
If the verification step finds an expired token, it invalidates it and returns:
{
ok: false,
date: new Date().toISOString(),
reason: 'Token expired'
}
If the verification query fails, the helper can return:
{
ok: false,
date: new Date().toISOString(),
reason: 'Server error validating token.'
}
If the metadata helper fails after verification, such as when the count query throws, the catch block returns:
{
ok: false,
date: new Date().toISOString(),
reason: 'Error getting metadata'
}
If verifyApiKey fails without a reason, the helper falls back to
Cant get metadata about invalid token.
Signature
The direct helper exposes the following signature:
export async function getUserApiKeysMetaData(
rawApiKey: string,
providedPrivilege: 'demo' | 'restricted' | 'protected' | 'full' | 'custom',
): Promise<Results<SingleTokenMeta>>
Parameters
The metadata helper accepts the following parameters:
| Field | Type | Description |
|---|---|---|
rawApiKey | string | The token to inspect. It can be hashed or Raw. |
providedPrivilege | 'demo' | 'restricted' | 'protected' | 'full' | 'custom' | The privilege that must match the stored token privilege. |
Return type
The metadata helper returns Results<SingleTokenMeta>.
SingleTokenMeta contains the following fields:
| Field | Type | Description |
|---|---|---|
tokenMeta | TokenMeta | Metadata for the selected token. |
counts | { totalInvalidTokens: number; totalValidTokens: number; total: number } | User-wide token counts for the token owner. |
TokenMeta contains the following fields on successful responses:
| Field | Type | Description |
|---|---|---|
name | string | The token name. |
tokenId | number | The internal database id of the token. |
userId | number | The owner of the token. |
createdAt | string | The stored creation timestamp. |
expiresAt | string | null | The stored expiration timestamp, or null when the token does not expire. |
lastUsed | string | null | The last stored successful usage timestamp. |
usageCount | number | The stored usage count. |
providedPrivilege | 'demo' | 'restricted' | 'protected' | 'full' | 'custom' | The privilege used for metadata verification. |
With the privateActionManager
The safest internal method is using the privateActionManager. This function
validates the publicIdentifier, token id, token name, user id, and current
valid status before it dispatches the metadata lookup.
const metaDataRes = await privateActionManager(
userId,
tokenId,
publicIdentifier,
tokenName,
{ action: 'metadata' }
)
The privateActionManager returns the response of getUserApiKeysMetaData
directly. Learn more at the
introduction page.
valid = 1. Because of that,
manager-backed metadata cannot target an already revoked token, and the manager
returns Bad Request before it reaches getUserApiKeysMetaData.Using the route
Let's say you want to fetch metadata for a token from your authenticated client or BFF.
POST /api/manage/metadata body:
{
"tokenId": 12,
"publicIdentifier": "public_identifier",
"name": "the token name"
}
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": {
"tokenMeta": {
"name": "server token",
"tokenId": 12,
"userId": 42,
"createdAt": "2026-05-01T10:00:00.000Z",
"expiresAt": "2026-05-01T11:00:00.000Z",
"lastUsed": "2026-05-01T10:30:00.000Z",
"usageCount": 19,
"providedPrivilege": "restricted"
},
"counts": {
"totalInvalidTokens": 2,
"totalValidTokens": 4,
"total": 6
}
}
}
Standard authentication, body validation, and other shared management-route errors are documented on the introduction page.
The route-specific failures come from the manager and the metadata helper.
Unlike rotation and IP updates, the metadata controller returns these failures
as 401 Unauthorized.
If the publicIdentifier checksum is invalid, the route returns
Invalid identity.
If the manager cannot match a currently valid token for the given tokenId,
publicIdentifier, name, and userId, it returns Bad Request. That means
the token is already revoked, belongs to a different user, or the request body
does not point to an active row.
If the manager finds the token but getUserApiKeysMetaData cannot verify it,
the route forwards the helper reason. That can be Invalid key,
Token expired, Server error validating token.,
Cant get metadata about invalid token, or Error getting metadata.
If privateActionManager itself fails unexpectedly, the route can also forward
Server Error.
All of these route-specific failures are returned as 401 Unauthorized by the
controller:
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
{
"ok": false,
"date": "current date",
"reason": "reason from privateActionManager or getUserApiKeysMetaData"
}
Rate Limits
The endpoint also enforces rate limits controlled under the following configuration options:
rate_limiters.apiTokensLimiters.operationRateLimits.getMetadataTokenLimiter- The main limiter for the metadata endpoint. The default allows 20 requests in a window of 2 seconds and will trigger a block for 30 minutes if this limit is met. Consecutive triggers in this period will block the client permanently.
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. The limiter is restarted on successful metadata requests.burstLimiter- Will block the client for 15 minutes.slowLimiter- Will block for 1 hour.
Metadata Process
Metadata collection reads the current token state without consuming the token.
Validate and resolve the target token
When you use the manager or route, the system validates the
publicIdentifier checksum and confirms that the token belongs to the current
user and is still valid. This check happens before getUserApiKeysMetaData
runs.
Verify without consuming usage
The helper calls verifyApiKey with skipCountUpdates = true,
byPassIpCheck = true, and isInternalHash = true. That means it can inspect
the stored token without incrementing usageCount, without refreshing
lastUsed, and without enforcing the token's IP whitelist.
Count the owner's tokens
After verification succeeds, the helper calls totalUserTokensCount for the
resolved userId. This returns the number of valid tokens, invalid tokens, and
the total token count for that user.
Return the combined snapshot
The final payload returns tokenMeta for the selected token and counts for
the owner. This lets you inspect one token while also understanding the user's
overall token inventory.
Configuration Reference
These configuration keys control metadata throttling in the service.
Rate limiters
The metadata flow relies on the following limiter configuration:
| Limiter | Description |
|---|---|
rate_limiters.apiTokensLimiters.operationRateLimits.getMetadataTokenLimiter | The main rate limiter for the metadata endpoint |
rate_limiters.apiTokensLimiters.generalUnionLimiter | General burst limiter |