Skip to content

Mint a personal access token

POST
/tokens
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.

Idempotency-Key
string
>= 1 characters <= 128 characters /^[\x21-\x7E]{1,128}$/

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.

Media typeapplication/json
object
name
string
>= 1 characters <= 80 characters
scopes

Defaults to minimal read-only scopes when omitted.

Array<string>
>= 1 items <= 32 items unique items
Allowed values: servers:read servers:write servers:delete commands:read commands:create commands:cancel commands:destructive telemetry:read events:read alerts:read alerts:write notifications:read notifications:write notifications:test billing:read billing:settings billing:topup subscription:write tokens:read tokens:create tokens:revoke audit:read marketplaces:read marketplaces:write strategy:read strategy:write
expires_at

Default 90 days, maximum 1 year from now.

string format: date-time
server_allowlist

Optional caveat restricting the token to specific servers.

Array<string>
>= 1 items <= 200 items unique items

PAT minted; plaintext shown once.

Media typeapplication/json
object
id
required

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
token
required

Plaintext PAT (erm_pat_...) — shown exactly once, never retrievable again.

string
<= 256 characters
name
string | null
<= 80 characters
token_prefix
required
string
<= 64 characters
scopes
required
Array<string>
<= 32 items
Allowed values: servers:read servers:write servers:delete commands:read commands:create commands:cancel commands:destructive telemetry:read events:read alerts:read alerts:write notifications:read notifications:write notifications:test billing:read billing:settings billing:topup subscription:write tokens:read tokens:create tokens:revoke audit:read marketplaces:read marketplaces:write strategy:read strategy:write
expires_at
required

RFC 3339 UTC with microsecond precision.

string format: date-time
Example
{
"scopes": [
"servers:read"
],
"expires_at": "2026-07-25T10:15:30.123456Z"
}

Missing/invalid credentials (code=unauthorized).

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
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).

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
Example
{
"type": "https://ermeon.com/problems/validation",
"code": "unauthorized"
}

The tenant has no plan assignment, so the capability cannot be evaluated (code=plan_required).

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
Example
{
"type": "https://ermeon.com/problems/validation",
"code": "unauthorized"
}

Request failed validation (code=validation_failed), with per-field errors.

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
Example
{
"type": "https://ermeon.com/problems/validation",
"code": "unauthorized"
}