OpenPoly logo
Operator Api

Staffs

Manage human Operator Dashboard staff accounts through staff-session APIs.

Staffs

Staff endpoints manage human Operator Dashboard accounts.

These endpoints require a staff-session bearer token. Operator API keys cannot call them even if the API key has broad scopes.

Auth paths

POST /api/operator/auth/staff-login
POST /api/operator/auth/staff-change-password
POST /api/operator/auth/logout

staff-login returns a bearer token with prefix pmost. and a 12-hour expiry.

staff-login does not require an existing bearer token. Its JSON body is:

FieldTypeRequirementNotes
emailstringRequiredValid email address.
passwordstringRequiredNon-empty password.

Login is limited to 5 failed attempts per normalized email and source identifier in a 15-minute window. A blocked attempt returns 429 RATE_LIMIT_EXCEEDED; wait for the window instead of retrying unchanged credentials.

staff-change-password is available only to staff sessions. newPassword is required and must contain at least 8 characters. oldPassword is conditionally required when must_change_password is false; it is optional for a forced first change. Successful change returns a replacement staff token and expiry because all previous sessions are revoked.

logout requires a valid bearer token and has no body. It revokes the current staff session when the bearer token is a staff token. An API-key call returns ok: true without revoking the key.

Staff management paths

GET /api/operator/staff
POST /api/operator/staff
PATCH /api/operator/staff/{membership_id}
POST /api/operator/staff/{membership_id}/reset-password

Required scopes:

  • staffs:read for list
  • staffs:write for create, patch, and reset password

All staff management paths also require auth_type = staff.

List query params

Both list query parameters are optional:

ParameterTypeRequirementNotes
searchstringOptionalCase-insensitive match against email or display name.
statusstringOptionalactive or disabled; an omitted or unrecognized value returns all.

Staff fields

  • membership_id
  • admin_user_id
  • email
  • display_name
  • role
  • status
  • account_status
  • scopes
  • must_change_password
  • last_login_at
  • created_at
  • updated_at

Create body

{
  "email": "ops@example.com",
  "display_name": "Ops User",
  "scopes": ["users:read", "trades:read"]
}
FieldTypeRequirementNotes
emailstringRequiredValid, globally unused email.
scopesstringRequiredNon-empty assignable scope list; * is forbidden.
display_namestringOptionalStored display name.

Rules:

  • email must be valid and globally unused
  • scopes must be non-empty
  • * is not assignable in staff create/update
  • write scopes normalize to include the matching read scope when available
  • staff can assign only scopes they already hold, unless they have *

Patch body

All fields are optional, but at least one update is required.

{
  "display_name": "Ops Lead",
  "status": "disabled",
  "scopes": ["users:read", "trades:read", "webhooks:read"]
}

A staff member cannot update their own access status or scopes. The implemented error is SELF_ACCESS_UPDATE_FORBIDDEN. A staff member also cannot reset their own password through the management endpoint; that returns SELF_PASSWORD_RESET_FORBIDDEN.

Patch path membership_id is required and must be a positive integer. display_name, status, and scopes are individually optional, but at least one must be supplied. Reset-password also requires the positive membership_id path parameter and has no body. Validation failures include INVALID_STAFF_ID, INVALID_STATUS, NO_UPDATES, and CANNOT_ASSIGN_SCOPE. Access or password mutations revoke active sessions for the target staff account; changing only the display name does not.

Password reset response

Create and reset responses include onboarding metadata:

{
  "ok": true,
  "item": {},
  "onboarding": {
    "email_sent": false,
    "email_error": "provider error",
    "temp_password": "returned-only-when-email-fails"
  }
}

If email sends successfully, temp_password is null.

Copyright © 2026