curl https://api.liddie.io/api/v1/api-keys \
-H "Authorization: Bearer <dashboard JWT>"
// Dashboard-session endpoint: send the JWT as a Bearer token.
const response = await fetch('https://api.liddie.io/api/v1/api-keys', {
headers: { 'Authorization': 'Bearer <dashboard JWT>' },
});
const keys = await response.json();
[
{
"id": "665f...",
"label": "backend-prod",
"keyPrefix": "3f9a1c07",
"permissions": ["payments:create", "payments:read"],
"ipWhitelist": ["203.0.113.10"],
"isActive": true,
"lastUsedAt": "2026-07-12T18:00:00.000Z",
"createdAt": "2026-06-01T09:00:00.000Z"
}
]
API keys
List API keys
List your active Liddie API keys with their labels, scopes, IP whitelists, and last-used timestamps — key material is never returned.
GET
/
api
/
v1
/
api-keys
curl https://api.liddie.io/api/v1/api-keys \
-H "Authorization: Bearer <dashboard JWT>"
// Dashboard-session endpoint: send the JWT as a Bearer token.
const response = await fetch('https://api.liddie.io/api/v1/api-keys', {
headers: { 'Authorization': 'Bearer <dashboard JWT>' },
});
const keys = await response.json();
[
{
"id": "665f...",
"label": "backend-prod",
"keyPrefix": "3f9a1c07",
"permissions": ["payments:create", "payments:read"],
"ipWhitelist": ["203.0.113.10"],
"isActive": true,
"lastUsedAt": "2026-07-12T18:00:00.000Z",
"createdAt": "2026-06-01T09:00:00.000Z"
}
]
See which API keys exist on your account, what each one can do, and when it was last used. You get metadata only — the raw key material is never returned.
This endpoint takes no parameters — it always lists the active keys of the merchant in your session.
API-key callers are rejected with
Authorization
This endpoint is dashboard-only. An API key can never create, list, or revoke API keys — a leaked key must not be able to clone itself or mint a more powerful one. Call it with a dashboard JWT with rolemerchant_admin, merchant_member (with team permission api-keys:view) or super_admin.
A
super_admin passes the role guard, but platform accounts carry no merchant context, so the handler
short-circuits with 400 {"ok":false,"error":{"code":"NO_MERCHANT_CONTEXT","message":"No merchant context"}}.
In practice this endpoint is for merchant accounts.401 {"error":"Invalid or expired token"} — the JWT guard runs first and an API key is not a session token, so the call never reaches the role check. The key is not revoked; it simply cannot authenticate a dashboard-only route. Authentication explains how scopes and dashboard sessions differ.
curl https://api.liddie.io/api/v1/api-keys \
-H "Authorization: Bearer <dashboard JWT>"
// Dashboard-session endpoint: send the JWT as a Bearer token.
const response = await fetch('https://api.liddie.io/api/v1/api-keys', {
headers: { 'Authorization': 'Bearer <dashboard JWT>' },
});
const keys = await response.json();
[
{
"id": "665f...",
"label": "backend-prod",
"keyPrefix": "3f9a1c07",
"permissions": ["payments:create", "payments:read"],
"ipWhitelist": ["203.0.113.10"],
"isActive": true,
"lastUsedAt": "2026-07-12T18:00:00.000Z",
"createdAt": "2026-06-01T09:00:00.000Z"
}
]
The raw key is unrecoverable — only its SHA-256 hash is stored. Use
keyPrefix to match a secret you hold to its row here.Response fields
string
The key’s ID — used for Update key IP binding and Revoke an API key.
string
The label given at creation, unique among your active keys.
string
How you match a stored secret to a row (the raw key is unrecoverable — only its SHA-256 hash is stored).
string[]
The merchant scopes granted to this key.
string[]
IPs the key is bound to. Empty means any IP.
boolean
Whether the key is not revoked — not whether it currently authenticates. A key created with an expiry whose expiry has since passed is still returned here with
isActive: true, yet it no longer authenticates (verification rejects it as expired). This response does not include expiresAt, so use the value you recorded at creation to know whether a key has expired.string
Approximate ISO timestamp of the key’s last use — treat it as best-effort, not exact. It is bumped at most once per minute, the write is fire-and-forget (a database hiccup drops it silently), and it is updated only after a fully successful authentication. Rejected attempts (non-whitelisted IP, missing scope, expired or revoked key) never move it, so it cannot prove a leaked key was never tried. Absent until the key is first used — a freshly created key has no such field, so treat it as optional.
string
ISO timestamp of key creation.
What you can't do here
What you can't do here
- Mint a key holding system-level scopes — merchant keys can only hold merchant scopes.
- Retrieve a raw key again after creation.
- Manage keys with an API key (JWT + MFA only).
- Extend a key’s expiry — mint a new key instead.
See also
- Create an API key: mint a new secret key (MFA required;
rawKeyshown once). - Update key IP binding: bind a key from this list to a single IP.
- Revoke an API key: kill a key by the
idreturned here.