Skip to main content

Secret Management

Endpoints for managing client secrets. Each OAuth client can hold multiple secrets to support rotation without downtime.

All five routes require the token API license feature and resolve the client by a lookup. The write routes (POST, PUT, DELETE) additionally require Superuser. The plaintext secret is excluded by the model's default scope and ignored in HAL output, so it is returned exactly once: in the create response.

GET /api/oauth-clients/{id}/secrets

List a client's secrets.

Authentication: Superuser + token API feature

Path Parameters:

ParameterTypeDescription
idstringClient UUID or client_id

Response:

A HAL collection (rel inf:oauth-client-secrets). Each row carries id, hint (***** plus the last 8 characters), lastUsedAt (null until a token issued with the secret is used), oauthClientId, createdAt, and updatedAt. The plaintext secret is never present.

List a client’s secretsGET /api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets
GET /api/oauth-clients/{id}/secrets returns the client’s `secrets` association (HAL api inf:oauth-client-secrets). The plaintext `secret` is never present — the column is excluded by the model’s default scope and ignored in toHal. Each row carries id, hint (*****<last 8 chars>), lastUsedAt (null until used), oauthClientId, createdAt, updatedAt. {id} accepts the client UUID or client_id.
Response · 200
[
{
"id": "00000000-0000-4000-8000-000000000002",
"hint": "*****a880a7d3",
"lastUsedAt": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"oauthClientId": "00000000-0000-4000-8000-000000000001"
}
]
Captured from the API examples test suite; ids and timestamps are normalized.

POST /api/oauth-clients/{id}/secrets

Generate a new client secret.

Authentication: Superuser + token API feature

Path Parameters:

ParameterTypeDescription
idstringClient UUID or client_id

Payload: empty

Response:

Responds 201 Created with a Location header. The server generates the secret (a 96-character hex string from crypto.randomBytes(48)), bcrypt-hashes it for storage, and returns the plaintext once. hint is ***** plus the last 8 characters of the plaintext.

Generate a client secretPOST /api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets
POST /api/oauth-clients/{id}/secrets takes an EMPTY payload. The server generates the secret (a 96-char hex string from crypto.randomBytes(48), NOT a cs_-prefixed token), bcrypt-hashes it for storage, and responds 201 with a Location header. This response is the ONLY place the plaintext `secret` is returned — store it now, it cannot be retrieved later. `hint` is *****<last 8 chars of the plaintext>. Requires superuser + the token/api license feature.
Request body
{}
Response · 201
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets/00000000-0000-4000-8000-000000000002"
}
},
"id": "00000000-0000-4000-8000-000000000002",
"secret": "example-secret-shown-once-on-create",
"tenant": "acme",
"oauthClientId": "00000000-0000-4000-8000-000000000001",
"updatedAt": "2026-01-15T16:20:00.000Z",
"createdAt": "2026-01-15T16:20:00.000Z",
"hint": "*****a880a7d3",
"lastUsedAt": null
}
Captured from the API examples test suite; ids and timestamps are normalized.
One-time display

The plaintext secret is returned only in this response. It is bcrypt-hashed before storage and cannot be retrieved later. Store it securely now.


GET /api/oauth-clients/{oauthClientId}/secrets/{id}

Get a single secret's metadata.

Authentication: Superuser + token API feature

Path Parameters:

ParameterTypeDescription
oauthClientIdstringClient UUID or client_id
idstringSecret UUID

Response:

Returns id, hint, lastUsedAt, oauthClientId, createdAt, and updatedAt. The plaintext secret is never returned.

Get a secretGET /api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets/00000000-0000-4000-8000-000000000002
GET /api/oauth-clients/{oauthClientId}/secrets/{id} returns one secret’s metadata (id, hint, lastUsedAt, oauthClientId, createdAt, updatedAt). The plaintext `secret` is ignored in toHal and never returned here.
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets/00000000-0000-4000-8000-000000000002"
}
},
"id": "00000000-0000-4000-8000-000000000002",
"hint": "*****a880a7d3",
"lastUsedAt": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"oauthClientId": "00000000-0000-4000-8000-000000000001"
}
Captured from the API examples test suite; ids and timestamps are normalized.

PUT /api/oauth-clients/{oauthClientId}/secrets/{id}

Update a secret's metadata.

Authentication: Superuser + token API feature

Path Parameters:

ParameterTypeDescription
oauthClientIdstringClient UUID or client_id
idstringSecret UUID

Request Body:

There is no Joi payload schema; the payload is set directly onto the instance. The mutable columns are hint and lastUsedAt.

{ "hint": "*****rotated1" }

Response:

Responds 200 with the updated secret; the plaintext secret is never returned.

Update a secretPUT /api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets/00000000-0000-4000-8000-000000000002
PUT /api/oauth-clients/{oauthClientId}/secrets/{id} updates a secret’s metadata via db.update (no joi payload schema; the payload is set directly onto the instance). The mutable columns are `hint` and `lastUsedAt`. Returns the updated secret; the plaintext `secret` is never returned.
Request body
{
"hint": "*****rotated1"
}
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets/00000000-0000-4000-8000-000000000002"
}
},
"id": "00000000-0000-4000-8000-000000000002",
"hint": "*****rotated1",
"lastUsedAt": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"oauthClientId": "00000000-0000-4000-8000-000000000001"
}
Captured from the API examples test suite; ids and timestamps are normalized.

DELETE /api/oauth-clients/{oauthClientId}/secrets/{id}

Delete a client secret.

Authentication: Superuser + token API feature

Path Parameters:

ParameterTypeDescription
oauthClientIdstringClient UUID or client_id
idstringSecret UUID

Response:

Responds 200 with an empty body (Informer's db.remove convention), not 204.

Delete a secretDELETE /api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets/00000000-0000-4000-8000-000000000002
DELETE /api/oauth-clients/{oauthClientId}/secrets/{id} removes the secret (db.remove). Returns 200 with an EMPTY body (Informer convention), NOT 204 as some clients expect. Deleting a secret does not revoke tokens already issued with it — use POST /api/oauth-clients/{id}/_revoke for that.
Response · 200 · no body
Captured from the API examples test suite; ids and timestamps are normalized.
Active tokens

Deleting a secret does not revoke tokens already issued with it. Use the revoke endpoint to invalidate active tokens.