Skip to content
engage-ai

Sign in as an administrator

POST/admin/auth/login

Returns a token for the /admin endpoints. expiresAt is authoritative — the lifetime is ADMIN_SESSION_TTL_HOURS (12 by default), because how long a control-plane token may sit in a terminal is a deployment decision, not ours.

Expiry is a backstop, not the control: these are opaque handles resolved on every request, so revoking a session or disabling an operator takes effect on the next call.

Failures are indistinguishable: unknown account, wrong password and disabled account all return the same 401.

Auth
None
Body
application/json

Request body

  • emailstring (email)required

    Max 320 characters

  • passwordstringrequired

    Max 512 characters

Response fields 200
  • accessTokenstringrequired

    Send as Authorization: Bearer <token> on every /admin endpoint.

  • expiresAtstring (date-time)required

    Four hours out — shorter than a tenant session.

  • mustChangePasswordbooleanrequired
  • adminobjectrequired
  • admin.idstring (uuid)required
  • admin.emailstring (email)required
  • admin.namestring | nullrequired

AdminLoginResult

  • accessTokenstringrequired

    Send as Authorization: Bearer <token> on every /admin endpoint.

  • expiresAtstring (date-time)required

    Four hours out — shorter than a tenant session.

  • mustChangePasswordbooleanrequired
  • adminobjectrequired
  • admin.idstring (uuid)required
  • admin.emailstring (email)required
  • admin.namestring | nullrequired

Responses

  • 200Signed in.
  • 401Invalid email or password.
Request
curl -X POST "https://api.getengageai.app/admin/auth/login" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@ops.example",
    "password": "h7TN5737-LD9FH2hW-mJ9uu6oj"
  }'
Response · 200
{
  "accessToken": "eng_sess_76bc0bae.2DrK9vYw…",
  "expiresAt": "2026-10-16T09:30:00.000Z",
  "mustChangePassword": true,
  "admin": {
    "id": "3f6c2a1e-8b4d-4e7a-9c15-2d0b7e6f4a91",
    "email": "owner@acme.example",
    "name": "Trailhead Mid GTX Boot"
  }
}

End the current admin session

POST/admin/auth/logout
Response fields 200
  • loggedOuttruerequired

Responses

  • 200Signed out.
  • 401Missing or invalid admin credential.
  • 409The bootstrap key has no session to end.
Request
curl -X POST "https://api.getengageai.app/admin/auth/logout" \
  -H "Authorization: Bearer $ADMIN_TOKEN"
Response · 200
{
  "loggedOut": true
}

Describe the current admin credential

GET/admin/auth/me

Tells you whether you are acting as a named operator or as the shared key.

Response fields 200
  • kindenumrequired

    bootstrap_key is anonymous — actions taken with it have no named actor.

    One of admin_session, bootstrap_key

  • adminUserIdstring (uuid) | nullrequired
  • emailstring (email) | nullrequired
  • mustChangePasswordbooleanrequired

AdminPrincipal

  • kindenumrequired

    bootstrap_key is anonymous — actions taken with it have no named actor.

    One of admin_session, bootstrap_key

  • adminUserIdstring (uuid) | nullrequired
  • emailstring (email) | nullrequired
  • mustChangePasswordbooleanrequired

Responses

  • 200The authenticated administrator.
  • 401Missing or invalid admin credential.
Request
curl "https://api.getengageai.app/admin/auth/me" \
  -H "Authorization: Bearer $ADMIN_TOKEN"
Response · 200
{
  "kind": "admin_session",
  "adminUserId": "3f6c2a1e-8b4d-4e7a-9c15-2d0b7e6f4a91",
  "email": "owner@acme.example",
  "mustChangePassword": true
}

Change your admin password

POST/admin/auth/password

Revokes every admin session you hold, including this one.

Body
application/json

Request body

  • currentPasswordstringrequired

    Max 512 characters

  • newPasswordstringrequired

    Min 12 characters · Max 512 characters

Response fields 200
  • changedtruerequired
  • sessionsRevokedintegerrequired

    Min -9007199254740991

Responses

  • 200Changed. Sign in again.
  • 401The current password did not match.
  • 409The bootstrap key has no password.
Request
curl -X POST "https://api.getengageai.app/admin/auth/password" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "currentPassword": "h7TN5737-LD9FH2hW-mJ9uu6oj",
    "newPassword": "a-long-passphrase-you-chose"
  }'
Response · 200
{
  "changed": true,
  "sessionsRevoked": 0
}

List administrators

GET/admin/users

Responses

  • 200Every administrator, disabled ones included.
  • 401Missing or invalid admin credential.
Request
curl "https://api.getengageai.app/admin/users" \
  -H "Authorization: Bearer $ADMIN_TOKEN"
Response · 200
[
  {
    "id": "3f6c2a1e-8b4d-4e7a-9c15-2d0b7e6f4a91",
    "email": "alice@ops.example",
    "name": "Alice",
    "mustChangePassword": true,
    "lastLoginAt": "2026-10-16T09:30:00.000Z",
    "disabledAt": "2026-10-16T09:30:00.000Z",
    "createdAt": "2026-10-16T09:30:00.000Z"
  }
]

Create an administrator

POST/admin/users

Returns a temporary password, shown once.

The bootstrap key can only do this while no administrator exists. Once the first account is in place, creating operators requires signing in as one — otherwise the shared key would remain a permanent way to mint access, and disabling someone would not actually remove their route in.

Body
application/json

Request body

  • emailstring (email)required

    Max 320 characters

  • namestring

    Max 255 characters

Response fields 201
  • idstring (uuid)required
  • emailstring (email)required
  • namestring | nullrequired
  • mustChangePasswordbooleanrequired
  • lastLoginAtstring (date-time) | nullrequired
  • disabledAtstring (date-time) | nullrequired

    Non-null means they cannot sign in.

  • createdAtstring (date-time)required
  • temporaryPasswordstringrequired

    Shown once. Hand it to them; they must replace it.

Responses

  • 201Created. Hand the password over once.
  • 401Missing or invalid admin credential.
  • 409Email taken, or the bootstrap key used too late.
Request
curl -X POST "https://api.getengageai.app/admin/users" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "bob@ops.example",
    "name": "Bob"
  }'
Response · 201
{
  "id": "3f6c2a1e-8b4d-4e7a-9c15-2d0b7e6f4a91",
  "email": "owner@acme.example",
  "name": "Trailhead Mid GTX Boot",
  "mustChangePassword": true,
  "lastLoginAt": "2026-10-16T09:30:00.000Z",
  "disabledAt": "2026-10-16T09:30:00.000Z",
  "createdAt": "2026-10-16T09:30:00.000Z",
  "temporaryPassword": "h7TN5737-LD9FH2hW-mJ9uu6oj"
}

Disable or re-enable an administrator

POST/admin/users/{id}/disabled

Disabling revokes their sessions immediately — leaving them live would mean an operator keeps full control-plane access until their token expires. Accounts are never deleted, so their audit trail keeps resolving to a name.

Body
application/json

Path parameters

  • idstring (uuid)required

Request body

  • disabledbooleanrequired
Response fields 200
  • disabledbooleanrequired
  • sessionsRevokedintegerrequired

    Min -9007199254740991

Responses

  • 200Updated.
  • 401Missing or invalid admin credential.
  • 404No such administrator.
  • 409You cannot disable your own account.
Request
curl -X POST "https://api.getengageai.app/admin/users/$ID/disabled" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "disabled": true
  }'
Response · 200
{
  "disabled": true,
  "sessionsRevoked": 0
}