Mint a personal access token
const url = 'https://api.flotera.com/api/v1/tokens';const options = { method: 'POST', headers: { cookie: '__Host-erm_session=<__Host-erm_session>', 'Content-Type': 'application/json' }, body: '{"name":"example","scopes":["servers:read"],"expires_at":"2026-07-25T10:15:30.123456Z","server_allowlist":["2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.flotera.com/api/v1/tokens \ --header 'Content-Type: application/json' \ --cookie __Host-erm_session=<__Host-erm_session> \ --data '{ "name": "example", "scopes": [ "servers:read" ], "expires_at": "2026-07-25T10:15:30.123456Z", "server_allowlist": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ] }'Plaintext is returned exactly once. Default scopes are minimal
read-only; default expiry 90 days, maximum 1 year — non-expiring PATs
are rejected in production. Effective permissions are
role ∩ scopes ∩ caveats ∩ resource policy; scopes never expand the
membership role.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Idempotency key, 1–128 ASCII, unique per (tenant_id, operation, key) for at least 24 hours. Retrying with the same body replays the stored response; a different body returns 409 idempotency_conflict.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Defaults to minimal read-only scopes when omitted.
Default 90 days, maximum 1 year from now.
Optional caveat restricting the token to specific servers.
Responses
Section titled “Responses”PAT minted; plaintext shown once.
object
UUID (v7 for new entities; v4 accepted during migration).
Plaintext PAT (erm_pat_...) — shown exactly once, never retrievable again.
RFC 3339 UTC with microsecond precision.
Example
{ "scopes": [ "servers:read" ], "expires_at": "2026-07-25T10:15:30.123456Z"}Missing/invalid credentials (code=unauthorized).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Authenticated but not permitted. code=forbidden — role/scope mismatch; code=feature_not_entitled — the plan does not include the capability; code=account_frozen — the account is frozen and this operation is declared x-ermeon-frozen: deny. The three are deliberately distinct: only the last one is fixed by a top-up (13 §5.6).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}The tenant has no plan assignment, so the capability cannot be evaluated (code=plan_required).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Request failed validation (code=validation_failed), with per-field errors.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}