Sandbox test operators — headless login tokens for CI

When you write automated acceptance tests for an operator-facing flow (mobile operator app, warehouse terminal, any PDP-gated resource access), your CI needs a real end-user token that carries the account_id claim — the same shape a human operator gets after logging in. You cannot script a human login (it is gated by email OTP + CAPTCHA on purpose), and a bare admin-created user does not carry account_id.

The sandbox test-operator API solves this: one AK/SK-authenticated call provisions a workforce operator in your own account and returns a real, Keycloak-issued operator token your CI can use immediately.

TL;DR. POST https://api.flexgalaxy.ai/developer/v1/test-users, signed with your account’s access key (FGAI-HMAC). You get back { user_id, email, access_token, expires_in }. The access_token is a real operator token (aud=flexgalaxy-api, carries account_id + user_type=workforce), valid for 5 minutes, accepted by every FlexGalaxy.AI resource server and the PDP. Delete the operator with DELETE /developer/v1/test-users/{user_id} when the suite finishes.

Prerequisites — one-time account setup

Forward this to your Account root or an authorized account admin:

  1. A sandbox account inside an organization. The test operator is created as a workforce user in your organization’s Identity Center, so the account you provision into must belong to an organization (not a standalone account).

  2. An access key for a principal in that account (Profile → Credentials → Access keys, or the developer credential API).

  3. Grant the iam:CreateTestUser capability to that principal — an IAM policy statement scoped to the account:

    {
      "Effect": "Allow",
      "Action": "iam:CreateTestUser",
      "Resource": "frn:<accountId>:iam:account/<accountId>"
    }
    

    This capability is what makes an account a “sandbox”: only accounts an admin deliberately grants it to can mint test operators, and a caller can only ever provision into its own account (the account is taken from the AK/SK token, never from the request body).

Create an operator

Sign the request with FGAI-HMAC-SHA256 the same way you sign any other /developer/v1/* or /identity/v1/* call (see Integrate with access keys).

POST /developer/v1/test-users
Authorization: FGAI-HMAC-SHA256 Credential=AKIA.../.../identity/fgai4_request, ...
Content-Type: application/json

{ "user_type": "workforce" }

user_type is optional (only workforce is supported today) and email is optional (a @sandbox.flexgalaxy.test address is generated when omitted).

201 response:

{
  "user_id": "b3a0de58-318f-41f9-bba5-dfe8fdbaa17d",
  "email": "op-2124a427b3@sandbox.flexgalaxy.test",
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUI...",
  "expires_in": 300
}

The access_token decodes to a genuine operator token:

{
  "iss": "https://auth.flexgalaxy.ai/auth/realms/idc-<orgId>",
  "aud": "flexgalaxy-api",
  "sub": "b3a0de58-318f-41f9-bba5-dfe8fdbaa17d",
  "account_id": "<your sandbox account UUID>",
  "user_type": "workforce",
  "exp": "<iat + 300>"
}

Present it to any FlexGalaxy.AI API as Authorization: Bearer <access_token>, or to POST /identity/v1/authorize to check a permission. It validates against the realm JWKS like a real login, resolves the correct account_id, and is denied on cross-account access — exactly what your acceptance test asserts.

Short TTL, no refresh. The token lives 5 minutes. For a longer suite, call POST /developer/v1/test-users again for a fresh token (or re-use the same operator user_id — it persists until you delete it).

List and delete

GET    /developer/v1/test-users            → [{ "user_id", "email" }, ...]
DELETE /developer/v1/test-users/{user_id}  → 204

DELETE removes the operator and its account assignment. Clean up at the end of your test run so sandbox operators do not accumulate.

Scope and safety

  • The operator is a real workforce user, entitled to your sandbox account by a real Identity Center assignment — the platform enforces that gate, so the token can only ever carry an account_id you actually own.

  • It is confined to your own account; it cannot touch another tenant.

  • Every create and delete is audited (DeveloperTestUserCreated / DeveloperTestUserDeleted).

  • This is a sandbox/testing facility. Do not use test operators as production identities.