Onboard an operator and manage roles
List existing operators, create one (setup token out-of-band), grant a time-bounded role with step-up, confirm, review grants, and later revoke. Requires iam-platform-admin throughout — so the VERY FIRST operator cannot be created here: it is seeded once, out of band (scenario 52).
- GET /v1/admin/operators → review existing operators before creating another
- POST /v1/admin/operators → 201 (operator created; setup/MFA-enrolment token out-of-band)
- PUT /v1/admin/operators/{operatorId}/roles/{role} → grant a time-bounded role (step-up)
- GET /v1/admin/operators/{operatorId} → confirm the operator and their active roles
- GET /v1/admin/operators/{operatorId}/roles → review active role grants
- DELETE /v1/admin/operators/{operatorId}/roles/{role} → revoke a role (step-up)
/v1/admin/operatorsadminList operatorsReview existing operators (cursor-paginated) before creating another — avoids duplicating an account.
Field guide — what each value means & where it comes from2 fields
Lists operator accounts (cursor-paginated). No request body. Requires platform-admin auth (Authorization / x-gateway-context handled by the tester+gateway); caller must hold the iam-platform-admin role. Only two optional query params.
limitqueryintegeroptionalyou choosecursorquerystringoptionalfrom a responseGET https://api.kerja.team/v1/admin/operators?limit=20Response guide — what comes back & what each value means10 fields
200 OK. Body is the standard { data, meta } envelope: data is an array of OperatorListItem objects, meta carries the page count and cursor-pagination token. No special response headers (no Set-Cookie, no Cache-Control: no-store).
dataarrayalwaysdata[].idUUIDalwaysdata[].emailstringalwaysdata[].displayNamestringalwaysdata[].statusenumalwaysactive— Account is enabled and may authenticate.
data[].createdAtISO-8601alwaysdata[].activeRoleCountintegeralwaysmetaobjectalwaysmeta.countintegeralwaysmeta.nextCursorstringalways/v1/admin/operatorsadminCreate operator (admin)Needs Idempotency-Key: <uuid>. Always returns meta.mfaEnrollmentRequired = true; the setup/account token is delivered out-of-band. The operator brings the account online via scenario 33. Same-key retry replays the original 201.
Field guide — what each value means & where it comes from3 fields
Creates an operator account (requires iam-platform-admin via gateway context, handled by the tester). Idempotent: you must set a fresh Idempotency-Key UUID header yourself. A setup/MFA-enrolment token is generated and delivered out-of-band; it is never returned.
Idempotency-KeyheaderUUIDrequiredclient-generatedemailbodystringrequiredyou choosedisplayNamebodystringoptionalyou choosePOST https://api.kerja.team/v1/admin/operatorsResponse guide — what comes back & what each value means6 fields
Success is 201 Created returning the standard { data } envelope (no special response headers). data is the newly created operator record; meta carries the MFA-enrolment flag. The MFA-enrolment / account-setup token is delivered out-of-band and is never present in the body.
data.idUUIDalwaysdata.emailstringalwaysdata.displayNamestringconditionaldata.statusenumalwaysactive— The account is created in the active state and ready for use (MFA enrolment still pending per meta.mfaEnrollmentRequired).
data.createdAtISO-8601alwaysmeta.mfaEnrollmentRequiredbooleanalwaystrue— MFA enrolment is required before the operator can fully authenticate; an out-of-band setup token was generated and delivered.
/v1/admin/operators/{operatorId}/roles/{role}adminGrant / extend a role (step-up)Step-up required. expiresInDays is 1–365 (default 90). The unqualified platform_admin is never grantable via this API — it always returns 422 IAM-ROLE-02 (break-glass / out-of-band seed only). You cannot grant a role to yourself (422 IAM-ROLE-03).
Field guide — what each value means & where it comes from6 fields
Grants or extends a time-bounded operator role (upsert). Requires the iam-platform-admin operator role plus a step-up factor in the body (stepUp.password or stepUp.recoveryCode); the tester/gateway supply Authorization / x-gateway-context. No Idempotency-Key required.
operatorIdpathUUIDrequiredfrom a responserolepathenumrequiredyou chooseiam-platform-admin— Administer operator accounts & role grants and set the global sign-up policy.tenant-lifecycle-operator— Provision and manage tenant lifecycle.support-acting-in-tenant— Mint tenant-scoped act-as tokens.security-investigator— Cross-tenant forensic audit read.support-read-only— Read-only support; grantable but backs no endpoint in this surface today (no-op access).billing-admin— Billing administration; grantable but backs no endpoint in this surface today (no-op access).platform_admin— Accepted by the router but ALWAYS rejected by the service with 422 (IAM-ROLE-02) regardless of any other field — the unqualified platform_admin is never grantable via this API (break-glass / out-of-band seed only).
stepUpbodyobjectrequiredyou choosestepUp.passwordbodystringconditionalyou choosestepUp.recoveryCodebodystringconditionalauthenticatorexpiresInDaysbodyintegeroptionalyou choosePUT https://api.kerja.team/v1/admin/operators/2a1c0000-0000-7000-8000-000000000001/roles/security-investigatorResponse guide — what comes back & what each value means5 fields
200 OK with a JSON { data } envelope wrapping a GrantResult object (no special response headers; no Set-Cookie or Cache-Control noted). The grant is an upsert: an existing active grant of this role has its expiry extended, otherwise a new grant is inserted; either way the response shape is identical.
dataobjectalwaysdata.operatorIdUUIDalwaysdata.roleenumalwaysiam-platform-admin— Administer operator accounts & role grants; set the global sign-up policy.tenant-lifecycle-operator— Provision and manage tenant lifecycle.support-acting-in-tenant— Mint tenant-scoped act-as tokens.security-investigator— Cross-tenant forensic audit read.support-read-only— Read-only support role (grantable but backs no endpoint in this surface today).billing-admin— Billing administration role (grantable but backs no endpoint in this surface today).
data.expiresAtISO-8601alwaysdata.grantedByUUIDalways/v1/admin/operators/{operatorId}adminGet one operator + rolesConfirms the operator and their active role grants (OperatorDetail).
Field guide — what each value means & where it comes from1 field
No request body. Read-only fetch of one operator and their active roles; requires a platform-admin gateway context (Authorization / x-gateway-context handled by the tester + gateway). The only caller input is the operatorId in the path.
operatorIdpathUUIDrequiredfrom a responseGET https://api.kerja.team/v1/admin/operators/2a1c0000-0000-7000-8000-000000000001Response guide — what comes back & what each value means9 fields
200 OK returning the standard { data } envelope with a single OperatorDetail object (no special response headers; not paginated). The data object carries the operator's identity, status, creation time, and an array of their active role grants.
dataobjectalwaysdata.idUUIDalwaysdata.emailstringalwaysdata.displayNamestringalwaysdata.statusenumalwaysactive— Operator account is enabled and may authenticate and hold roles.
data.createdAtISO-8601alwaysdata.rolesarrayalwaysdata.roles[].roleenumalwaysiam-platform-admin— Full platform administration over operators, tenants, and roles.security-investigator— Read/investigation access to security and audit data.
data.roles[].expiresAtISO-8601always/v1/admin/operators/{operatorId}/rolesadminList an operator's role grantsActive role grants with each grant's expiry window.
Field guide — what each value means & where it comes from1 field
No request body and no query params. Authenticated via gateway context (handled by the tester); caller must hold iam-platform-admin. Supply only the operatorId path param.
operatorIdpathUUIDrequiredfrom a responseGET https://api.kerja.team/v1/admin/operators/2a1c0000-0000-7000-8000-000000000001/rolesResponse guide — what comes back & what each value means8 fields
200 OK with the standard { data, meta } envelope; data is an array of the operator's active RoleGrant items, returned as a single page (meta.nextCursor is always null here). No special response headers (no Set-Cookie/Cache-Control noted).
data[]arrayalwaysdata[].roleenumalwaysiam-platform-admin— Administer operator accounts & role grants; set the global sign-up policy (§3.50-3.55, §3.65-3.66).tenant-lifecycle-operator— Provision and manage tenant lifecycle (§3.56-3.60).support-acting-in-tenant— Mint tenant-scoped act-as tokens (§3.61-3.63).security-investigator— Cross-tenant forensic audit read (§3.64).support-read-only— Read-only support role; grantable but backs no endpoint in this surface (reserved).billing-admin— Billing administration role; grantable but backs no endpoint in this surface (reserved).
data[].expiresAtISO-8601alwaysdata[].grantedByUUIDalwaysdata[].createdAtISO-8601alwaysmetaobjectalwaysmeta.countintegeralwaysmeta.nextCursorstringalwaysnull— No further pages; this endpoint always returns a single page so the value is always null.
/v1/admin/operators/{operatorId}/roles/{role}adminRevoke a role (step-up)Step-up required. Revoking a role the operator doesn't actively hold is NOT a no-op — it rolls back with no audit row and returns 404 NOT_FOUND. Revoking your own last iam-platform-admin grant returns 422 (IAM-ROLE-LAST-ADMIN).
Field guide — what each value means & where it comes from5 fields
Revokes one operator role grant. Requires an operator session (x-gateway-context, handled by the tester/gateway) with the iam-platform-admin role, plus step-up re-auth: the body must carry a stepUp object with at least one factor (current password or a recovery code). No Idempotency-Key is required.
operatorIdpathUUIDrequiredfrom a responserolepathenumrequiredyou chooseiam-platform-admin— Revokes administration rights over operator accounts, role grants, and the global sign-up policy. Blocked with 422 (IAM-ROLE-LAST-ADMIN) if it would remove your own last iam-platform-admin grant.tenant-lifecycle-operator— Revokes the ability to provision and manage tenant lifecycle.support-acting-in-tenant— Revokes the ability to mint tenant-scoped act-as tokens.security-investigator— Revokes cross-tenant forensic audit read access.support-read-only— Revokes the read-only support role (grantable but currently backs no endpoint in this surface).billing-admin— Revokes the billing administration role (grantable but currently backs no endpoint in this surface).
stepUpbodyobjectrequiredyou choosestepUp.passwordbodystringconditionalyou choosestepUp.recoveryCodebodystringconditionalauthenticatorDELETE https://api.kerja.team/v1/admin/operators/2a1c0000-0000-7000-8000-000000000001/roles/security-investigatorResponse guide — what comes back & what each value means4 fields
200 OK with the standard { data } envelope wrapping a RevokeResult object; no notable response headers (no Set-Cookie, no Cache-Control: no-store). A no-op revoke (no active grant) does not reach this success shape — it rolls back and returns 404.
dataobjectalwaysdata.operatorIdUUIDalwaysdata.roleenumalwayssecurity-investigator— The security-investigator operator role grant was revoked (example value shown in the doc).<operator role>— Any one of the six operator roles defined in Appendix A — Operator Roles, excluding platform_admin which is rejected with 400.
data.revokedbooleanalwaystrue— The active role grant was found and revoked, and an operator_role_revoked audit row was written.