Clients and Audit API¶
The Clients and Audit API (/fss/v1/clients, /fss/v1/audit) creates, changes, rotates and revokes API clients and reads the API audit trail from a script.
API clients cover the whole MetaMiner Server (MMS) API, not only the Flow Scheduler. What clients are, their access levels and how to create them in the MetaMiner Administrator (MMA) are on Manage API Clients.
Rules for every call¶
| Rule | Detail |
|---|---|
| Who may call | An admin API client without environment or site limits (403 FORBIDDEN otherwise). Exception: POST /fss/v1/clients/me/rotate, which any client may call for itself. |
| Flow Scheduler switched on | Clients live in the shared Flow Scheduler database. Changes (create, change, rotate, revoke) are served by the leader node; on the standby they answer 409 NOT_LEADER with leader. |
| Flow Scheduler switched off | MMS keeps the clients itself. The same calls work, with no leader check. The audit call returns an empty list and a note. |
| Effect | No MMS restart. A rotation, revocation or expiry takes effect at once on every node. A new client works at once, except on a node that refused its token in the last 30 seconds; there it works when those 30 seconds have passed. |
| Tokens | Returned once, in the answer to create and rotate. Never listed. MetaMiner stores only a SHA-256 hash. |
Base URL: https://<mms-host>:<port> (default port 49714; http:// only when SSL is not enabled on MMS).
List clients¶
GET /fss/v1/clients
The answer is {"clients": [...]}. With the Flow Scheduler switched on, each client has:
| Field | Meaning |
|---|---|
name |
Client name |
admin |
true = admin client |
envIds, siteIds |
Environment and site limits; null = all |
tableauUsername |
Bound Tableau user, if any |
expiresAt |
Expiry (ISO-8601 UTC), absent = never |
createdAt, createdBy |
When and by whom it was made |
rotatedAt |
Last token rotation |
revokedAt, revokedBy |
Set when revoked |
lastUsedAt |
Last call the leader answered for it (written at most once a minute) |
active |
true unless revoked or expired |
Create a client¶
POST /fss/v1/clients
| Field | Required | Meaning |
|---|---|---|
name |
Yes | 1 to 128 letters, digits, ., _ or -, starting with a letter or digit. api, local and me are reserved (any case). |
admin |
No | true = admin client. Default false. |
envIds |
No | Environment ids the client may use. Absent = all; an empty list is refused. |
siteIds |
No | Tableau site LUIDs the client may use. Absent = all; an empty list is refused. |
tableauUsername |
No | The Tableau user whose run permission a non-admin client is checked against |
expiresAt |
No | ISO-8601 UTC, for example 2027-01-01T00:00:00Z. Absent = never expires. |
The answer is 201 with {"name", "token", "note": "Store this token now: it is shown only once."}.
curl -sS -X POST "https://<mms-host>:<port>/fss/v1/clients" \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"name": "etl-nightly", "envIds": [<envId>], "siteIds": ["<site-luid>"],
"tableauUsername": "<tableau-user>", "expiresAt": "2027-06-30T00:00:00Z"}'
$body = @{ name = "etl-nightly"; envIds = @(<envId>); siteIds = @("<site-luid>")
tableauUsername = "<tableau-user>"; expiresAt = "2027-06-30T00:00:00Z" } | ConvertTo-Json
$c = Invoke-RestMethod -Method Post -Uri "https://<mms-host>:<port>/fss/v1/clients" `
-Headers @{ Authorization = "Bearer <token>" } -ContentType "application/json" -Body $body
$c.token # store it now in your secret store
Change a client¶
PUT /fss/v1/clients/{name}
Body: any of admin, envIds, siteIds, tableauUsername, expiresAt. A field sent as null is cleared (all environments, all sites, no Tableau user, never expires); a field left out is kept. The token does not change. Extending the expiry of an expired client brings the same token back. The answer is 200 with {"name"}.
curl -sS -X PUT "https://<mms-host>:<port>/fss/v1/clients/etl-nightly" \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"expiresAt": "2027-12-31T00:00:00Z", "envIds": null}'
Invoke-RestMethod -Method Put -Uri "https://<mms-host>:<port>/fss/v1/clients/etl-nightly" `
-Headers @{ Authorization = "Bearer <token>" } -ContentType "application/json" `
-Body '{"expiresAt": "2027-12-31T00:00:00Z", "envIds": null}'
Rotate a token¶
POST /fss/v1/clients/{name}/rotate gives another client a new token. POST /fss/v1/clients/me/rotate gives the calling client a new token (any client).
The answer is 200 with {"name", "token", "note": "The previous token no longer works. Store this one now: it is shown only once."}. The old token stops at once on every node. Store the new token before you discard the old one. Under Local only, me/rotate answers 400 because the call carries no client. Details: Rotate, Expire, Revoke.
curl -sS -X POST "https://<mms-host>:<port>/fss/v1/clients/me/rotate" -H "Authorization: Bearer <token>"
$r = Invoke-RestMethod -Method Post -Uri "https://<mms-host>:<port>/fss/v1/clients/me/rotate" `
-Headers @{ Authorization = "Bearer <token>" }
$r.token # the new token; the old one no longer works
Revoke a client¶
DELETE /fss/v1/clients/{name}
The answer is 200 with {"name", "revoked": true}. The token stops at once on every node. The client stays listed as revoked, and its name can be used again for a new client.
curl -sS -X DELETE "https://<mms-host>:<port>/fss/v1/clients/etl-nightly" -H "Authorization: Bearer <token>"
Invoke-RestMethod -Method Delete -Uri "https://<mms-host>:<port>/fss/v1/clients/etl-nightly" `
-Headers @{ Authorization = "Bearer <token>" }
Client responses¶
| Status | Meaning |
|---|---|
200 / 201 |
Done |
400 |
Body not a JSON object; invalid or reserved name; empty envIds or siteIds; expiresAt not ISO-8601 UTC; me/rotate under Local only |
401 / 503 |
See Status Codes and Errors |
403 |
FORBIDDEN: not an admin client without environment or site limits |
404 |
No live client of that name (unknown or revoked); unknown path |
409 |
A live client already has the name, or the token is in use; NOT_LEADER on the standby |
413 |
Body over 64 KiB |
Read the audit trail¶
GET /fss/v1/audit?client=<name>&limit=<n> - an admin API client without environment or site limits.
Both parameters are optional. limit is 1 to 1000 (clamped), default 100. Rows come newest first. What is recorded, and where it goes with the Flow Scheduler switched off, is on Audit Trail.
| Field | Meaning |
|---|---|
id, at |
Row id and time (UTC) |
client |
API client name; local for a Local only caller; MetaMiner Admin (<Windows user>) for a change made in MMA |
method, endpoint |
The call |
objectType, objectId |
What it touched |
envId |
Environment, when there is one |
status |
The HTTP status answered |
remote |
The caller's address as MMS saw it; behind a load balancer, the balancer's address |
With the Flow Scheduler switched off the answer is {"audit": [], "note": "..."}.
| Status | Meaning |
|---|---|
200 |
Rows returned |
401 / 503 |
See Status Codes and Errors |
403 |
FORBIDDEN |
curl -sS "https://<mms-host>:<port>/fss/v1/audit?client=etl-nightly&limit=20" -H "Authorization: Bearer <token>"
(Invoke-RestMethod -Uri "https://<mms-host>:<port>/fss/v1/audit?limit=50" `
-Headers @{ Authorization = "Bearer <token>" }).audit | Format-Table at, client, method, endpoint, status