Client Management
Endpoints for creating and managing OAuth client applications, plus the client-builder catalog, bulk token revocation, and icon management.
Every /api/oauth-clients route except the flat list and the template catalog
runs oauthClient.ensureOauth, which asserts the token API license feature.
When the license lacks it the route answers 400 (not 403). The write routes
(POST, PUT, DELETE, _revoke) additionally require Superuser.
GET /api/oauth-clients
List the tenant's OAuth clients, with optional search.
Authentication: Superuser + token API feature
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | - | Search query (matches name and description) |
Response:
A HAL collection under _embedded["inf:oauth-client"].
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients"
}
},
"start": 0,
"count": 4,
"total": 4,
"_embedded": {
"inf:oauth-client": [
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001"
},
"inf:secrets": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets"
},
"inf:oauth-client-revoke": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/_revoke"
},
"inf:icon": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/icon"
},
"oauth:authorize": {
"href": "https://informer.example.com/oauth/authorize"
},
"oauth:access_token": {
"href": "https://informer.example.com/api/oauth/access_token"
}
},
"isInformerCli": false,
"isInformerGo": false,
"permissions": {},
"id": "00000000-0000-4000-8000-000000000001",
"name": "Analytics Dashboard",
"description": "External analytics dashboard for Order Desk",
"url": "https://analytics.example.com",
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"redirect_uri": [
"https://analytics.example.com/callback"
],
"pkce": false,
"enableRefreshTokens": true,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"icon": null,
"_embedded": {
"inf:secret": []
}
},
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000002"
},
"inf:secrets": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000002/secrets"
},
"inf:oauth-client-revoke": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000002/_revoke"
},
"inf:icon": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000002/icon"
},
"oauth:authorize": {
"href": "https://informer.example.com/oauth/authorize"
},
"oauth:access_token": {
"href": "https://informer.example.com/api/oauth/access_token"
}
},
"isInformerCli": false,
"isInformerGo": false,
"permissions": {},
"id": "00000000-0000-4000-8000-000000000002",
"name": "Scratch Client",
"description": null,
"url": null,
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"redirect_uri": [],
"pkce": false,
"enableRefreshTokens": false,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"icon": null,
"_embedded": {
"inf:secret": []
}
},
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000003"
},
"inf:secrets": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000003/secrets"
},
"inf:oauth-client-revoke": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000003/_revoke"
},
"inf:icon": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000003/icon"
},
"oauth:authorize": {
"href": "https://informer.example.com/oauth/authorize"
},
"oauth:access_token": {
"href": "https://informer.example.com/api/oauth/access_token"
}
},
"isInformerCli": false,
"isInformerGo": true,
"permissions": {},
"id": "00000000-0000-4000-8000-000000000003",
"name": "Informer GO",
"description": "This enables support for the Informer GO desktop and mobile applications, allowing you to access your Informer account from your devices.",
"url": "",
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"redirect_uri": [],
"pkce": true,
"enableRefreshTokens": true,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"icon": null,
"_embedded": {
"inf:secret": []
}
},
"… 1 more items (4 total) — omitted from docs"
]
}
}
GET /api/oauth-clients-list
Get a flat array of every client, each decorated with a resolved icon URL.
Authentication: Required (no special permission)
Response:
A plain JSON array (not a HAL collection envelope). Each entry carries an
iconUrl, which is an empty string when the client has no icon. The endpoint
supports ETags for efficient caching.
[
{
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000001",
"name": "Analytics Dashboard",
"description": "External analytics dashboard for Order Desk",
"url": "https://analytics.example.com",
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"redirect_uri": [
"https://analytics.example.com/callback"
],
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"pkce": false,
"enableRefreshTokens": true,
"hasIcon": false,
"iconUrl": ""
},
{
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000002",
"name": "Scratch Client",
"description": null,
"url": null,
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"redirect_uri": [],
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"pkce": false,
"enableRefreshTokens": false,
"hasIcon": false,
"iconUrl": ""
},
{
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000003",
"name": "Informer GO",
"description": "This enables support for the Informer GO desktop and mobile applications, allowing you to access your Informer account from your devices.",
"url": "",
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"redirect_uri": [],
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"pkce": true,
"enableRefreshTokens": true,
"hasIcon": false,
"iconUrl": ""
},
"… 1 more items (4 total) — omitted from docs"
]
GET /api/oauth-client-templates
The client-builder catalog: a HAL collection of detective-discovered client templates used to pre-fill the create form.
Authentication: Required (no permission or token feature needed)
Response:
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-client-templates"
}
},
"items": [
{
"detective": "00000000-0000-4000-8000-000000000001",
"id": "00000000-0000-4000-8000-000000000001:0",
"value": {
"group": "__top",
"name": "New OAuth Client",
"oauthClient": {
"enableRefreshTokens": true
}
}
},
{
"detective": "00000000-0000-4000-8000-000000000002",
"id": "00000000-0000-4000-8000-000000000002:0",
"value": {
"group": "__top",
"name": "Informer Command Line Interface",
"oauthClient": {
"name": "Informer Command Line Interface",
"description": "The Informer CLI is a command line tool that allows you to interact with your Informer account from the command line.",
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"isInformerCli": true,
"enableRefreshTokens": true
}
}
}
],
"start": 0,
"count": 2,
"total": 2
}
The Informer CLI and Informer GO templates appear only when those clients are not already installed.
POST /api/oauth-clients
Create an OAuth client application.
Authentication: Superuser + token API feature
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Client application name |
description | string | No | Description |
url | string | No | Application URL |
redirect_uri | string | string[] | No | Allowed redirect URIs (no URL fragments). Defaults to [] |
client_id | string | No | Custom client id (auto-generated 20-char hex when omitted) |
pkce | boolean | No | Enable PKCE (default false) |
enableRefreshTokens | boolean | No | Issue refresh tokens (default false) |
svg | string | No | Inline SVG icon. Written to a File row and NOT echoed back |
The payload is stripUnknown, so unrecognized fields are dropped.
Example Request:
{
"name": "Mobile App",
"description": "Companion mobile client",
"url": "https://mobile.example.com",
"redirect_uri": ["https://mobile.example.com/callback"],
"pkce": true,
"enableRefreshTokens": true
}
Response:
Responds 201 Created with the client and a Location header.
{
"name": "Mobile App",
"description": "Companion mobile client",
"url": "https://mobile.example.com",
"redirect_uri": [
"https://mobile.example.com/callback"
],
"pkce": true,
"enableRefreshTokens": true
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001"
},
"inf:secrets": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets"
},
"inf:oauth-client-revoke": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/_revoke"
},
"inf:icon": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/icon"
},
"oauth:authorize": {
"href": "https://informer.example.com/oauth/authorize"
},
"oauth:access_token": {
"href": "https://informer.example.com/api/oauth/access_token"
}
},
"isInformerCli": false,
"isInformerGo": false,
"permissions": {},
"id": "00000000-0000-4000-8000-000000000001",
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"tenant": "acme",
"name": "Mobile App",
"description": "Companion mobile client",
"url": "https://mobile.example.com",
"redirect_uri": [
"https://mobile.example.com/callback"
],
"pkce": true,
"enableRefreshTokens": true,
"updatedAt": "2026-01-15T16:20:00.000Z",
"createdAt": "2026-01-15T16:20:00.000Z"
}
GET /api/oauth-clients/{id}
Retrieve a single client, decorated with its active token count.
Authentication: Superuser + token API feature
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Client UUID or client_id |
Response:
The body adds a computed tokenCount (active tokens for this client). HAL links
include inf:oauth-client-secrets, inf:oauth-client-revoke, inf:oauth-client-icon,
and the oauth:authorize / oauth:access_token grant rels.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001"
},
"inf:secrets": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets"
},
"inf:oauth-client-revoke": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/_revoke"
},
"inf:icon": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/icon"
},
"oauth:authorize": {
"href": "https://informer.example.com/oauth/authorize"
},
"oauth:access_token": {
"href": "https://informer.example.com/api/oauth/access_token"
}
},
"isInformerCli": false,
"isInformerGo": false,
"permissions": {},
"id": "00000000-0000-4000-8000-000000000001",
"name": "Mobile App",
"description": "Companion mobile client",
"url": "https://mobile.example.com",
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"redirect_uri": [
"https://mobile.example.com/callback"
],
"pkce": true,
"enableRefreshTokens": true,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"icon": null,
"tokenCount": 0,
"_embedded": {
"inf:secret": []
}
}
PUT /api/oauth-clients/{id}
Update a client's properties.
Authentication: Superuser + token API feature
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Client UUID or client_id |
Request Body (partial):
| Field | Type | Description |
|---|---|---|
name | string | Client name |
description | string | Description |
url | string | Application URL |
redirect_uri | string | string[] | Allowed redirect URIs (defaults to [] when sent) |
pkce | boolean | PKCE support |
enableRefreshTokens | boolean | Refresh token support |
Example Request:
{ "name": "Mobile App (Production)", "enableRefreshTokens": false }
Response:
Responds 200 with the updated client.
{
"name": "Mobile App (Production)",
"enableRefreshTokens": false
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001"
},
"inf:secrets": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/secrets"
},
"inf:oauth-client-revoke": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/_revoke"
},
"inf:icon": {
"href": "https://informer.example.com/api/oauth-clients/00000000-0000-4000-8000-000000000001/icon"
},
"oauth:authorize": {
"href": "https://informer.example.com/oauth/authorize"
},
"oauth:access_token": {
"href": "https://informer.example.com/api/oauth/access_token"
}
},
"isInformerCli": false,
"isInformerGo": false,
"permissions": {},
"id": "00000000-0000-4000-8000-000000000001",
"name": "Mobile App (Production)",
"description": "Companion mobile client",
"url": "https://mobile.example.com",
"client_id": "1a2b3c4d5e6f7a8b9c0d",
"redirect_uri": [],
"pkce": true,
"enableRefreshTokens": false,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"icon": null,
"secrets": []
}
POST /api/oauth-clients/{id}/_revoke
Delete every active token for a client, without deleting the client itself.
Authentication: Superuser + token API feature
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Client UUID or client_id |
Payload: empty
Response:
Responds 200 with an empty body. The tokens are deleted in a transaction; the
client row is left intact.
DELETE /api/oauth-clients/{id}
Delete a client and cascade-delete its secrets, icon, and tokens.
Authentication: Superuser (this route has no token-feature gate)
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Client UUID or client_id |
Response:
Responds 200 with an empty body (Informer's db.remove convention), not 204.
Deleting a client permanently removes all of its secrets, tokens, and active sessions.
Icon endpoints
The icon routes move image bytes rather than JSON, so they are documented here without captured examples.
GET /api/oauth-clients/{id}/icon
Stream the client's icon image (SVG, PNG, etc.). Superuser + token API
feature. Answers 404 when the client has no icon.
PUT /api/oauth-clients/{id}/icon
Upload an icon. Superuser + token API feature.
| Field | Type | Required | Description |
|---|---|---|---|
upload | string | Yes | Temp upload id from the storage upload endpoint |
progress | string | No | Upload progress tracking id |
Responds 201 Created with the file record.
DELETE /api/oauth-clients/{id}/icon
Remove the client's icon. Superuser + token API feature.