Skip to main content

Provision User

API Endpoint: POST /admin/law-firms/{lawFirmId}/users Priority: P1 User Story: As an admin, I want to provision a user with identity + firm profile + roles and optional credentials.

Overview

Create a new user with Logto authentication identity, firm-specific profile, functional roles, and optional professional credentials in a single atomic operation.

Scenarios

Scenario 1: Provision lawyer with bar license

Given:

  • Admin is authenticated with scope users:create
  • Law firm firm_abc exists with Logto org org_xyz
  • No existing user with email john.doe@acme.com

When:

  • Admin POSTs to /admin/law-firms/firm_abc/users with payload:
    {
    "email": "john.doe@acme.com",
    "givenName": "John",
    "familyName": "Doe",
    "profile": {
    "title": "Senior Partner",
    "functionalRoles": ["LAWYER"]
    },
    "credentials": [
    {
    "type": "BAR_LICENSE",
    "jurisdictionCode": "CA",
    "number": "123456",
    "issuedAt": "2010-06-15"
    }
    ],
    "orgRoles": ["attorney", "admin"],
    "sendInvite": true
    }

Then:

  • Response status is 201 Created
  • Response body contains:
    • authUser: Created Logto user with logtoUserId
    • firmProfile: Firm profile with functional roles
    • credentials: Array with created bar license
    • orgMembership: Logto org membership with roles
    • inviteSent: true
  • Logto user account is created
  • Firm user profile is created
  • Credential is stored
  • User is added to Logto org with specified roles
  • Invitation email is sent

Scenario 2: Provision paralegal without credentials

Given:

  • Admin is authenticated with scope users:create
  • Law firm firm_abc exists

When:

  • Admin POSTs to /admin/law-firms/firm_abc/users with payload:
    {
    "email": "jane.smith@acme.com",
    "givenName": "Jane",
    "familyName": "Smith",
    "profile": {
    "title": "Paralegal",
    "functionalRoles": ["PARALEGAL"]
    },
    "sendInvite": false
    }

Then:

  • Response status is 201 Created
  • User is created without credentials
  • No invitation email is sent
  • User can log in when they set up their account

Given:

  • Admin is authenticated with scope users:create
  • Existing Logto user with ID user_existing789
  • User not yet in law firm firm_abc

When:

  • Admin POSTs to /admin/law-firms/firm_abc/users with payload:
    {
    "logtoUserId": "user_existing789",
    "profile": {
    "title": "Associate",
    "functionalRoles": ["LAWYER"]
    }
    }

Then:

  • Response status is 201 Created
  • No new Logto user is created
  • Firm profile is created for existing user
  • Existing user is added to law firm's Logto org

Scenario 4: Duplicate email rejection

Given:

  • Admin is authenticated with scope users:create
  • Existing user with email john.doe@acme.com in law firm firm_abc

When:

  • Admin POSTs to /admin/law-firms/firm_abc/users with:
    {
    "email": "john.doe@acme.com",
    "givenName": "John",
    "familyName": "Doe"
    }

Then:

  • Response status is 409 Conflict
  • Response body contains:
    {
    "error": "DUPLICATE_USER",
    "message": "User with email 'john.doe@acme.com' already exists in this law firm"
    }

Scenario 5: Multiple functional roles

Given:

  • Admin is authenticated with scope users:create
  • Law firm exists

When:

  • Admin provisions user with multiple functional roles:
    {
    "email": "admin@acme.com",
    "givenName": "Admin",
    "familyName": "User",
    "profile": {
    "functionalRoles": ["IT_ADMIN", "BILLING_ADMIN"]
    }
    }

Then:

  • Response status is 201 Created
  • User profile contains both functional roles
  • User has permissions associated with both roles

Request Specification

Path Parameters

ParameterTypeRequiredDescription
lawFirmIdstringYesTarget law firm identifier

Request Body

FieldTypeRequiredConstraintsDescription
emailstringConditional*Valid email formatUser's email address
givenNamestringConditional*1-100 charsUser's first name
familyNamestringConditional*1-100 charsUser's last name
logtoUserIdstringConditional*Must exist in LogtoLink to existing Logto user
profileobjectYes-Firm-specific profile
profile.titlestringNoMax 200 charsJob title
profile.functionalRolesstring[]YesValid rolesUser's functional roles
credentialsarrayNo-Professional credentials
orgRolesstring[]NoValid Logto role IDsLogto organization roles
sendInvitebooleanNodefault: falseSend invitation email

* Either provide logtoUserId OR (email, givenName, familyName)

Functional Roles

RoleDescription
LAWYERLicensed attorney
PARALEGALParalegal staff
RECEPTIONISTFront desk staff
BILLING_ADMINBilling administrator
IT_ADMINIT administrator
INTERNLegal intern
OTHEROther staff

Credential Object

FieldTypeRequiredDescription
typestringYesBAR_LICENSE, NOTARY, OTHER
jurisdictionCodestringYesState/country code (e.g., "CA", "NY")
numberstringNoLicense/credential number
issuedAtstringNoISO 8601 date
expiresAtstringNoISO 8601 date
statusstringNoACTIVE, SUSPENDED, EXPIRED

Response Specification

Success Response (201 Created)

{
"authUser": {
"id": "usr_abc123",
"logtoUserId": "user_xyz789",
"email": "john.doe@acme.com",
"givenName": "John",
"familyName": "Doe"
},
"firmProfile": {
"id": "profile_def456",
"lawFirmId": "firm_abc",
"userId": "usr_abc123",
"title": "Senior Partner",
"functionalRoles": ["LAWYER"],
"isActive": true
},
"credentials": [
{
"id": "cred_ghi789",
"type": "BAR_LICENSE",
"jurisdictionCode": "CA",
"number": "123456",
"issuedAt": "2010-06-15",
"status": "ACTIVE"
}
],
"orgMembership": {
"logtoOrgId": "org_xyz",
"logtoUserId": "user_xyz789",
"roles": ["attorney", "admin"]
},
"inviteSent": true
}

Error Responses

StatusError CodeDescription
400VALIDATION_ERRORInvalid input format
401UNAUTHORIZEDMissing or invalid auth token
403FORBIDDENMissing users:create scope
404LAW_FIRM_NOT_FOUNDLaw firm does not exist
409DUPLICATE_USERUser already exists in firm
409LOGTO_USER_NOT_FOUNDProvided logtoUserId not found

Requirements Mapping

  • FR-001: Accept POST with user creation data
  • FR-002: Create or link Logto user identity
  • FR-003: Create firm-specific user profile
  • FR-004: Assign functional roles to profile
  • FR-005: Create professional credentials
  • FR-006: Add user to Logto organization
  • FR-007: Assign Logto organization roles
  • FR-008: Send invitation email when requested
  • FR-009: Validate email uniqueness within firm
  • FR-010: Support multiple functional roles per user
  • FR-011: Return complete user details in response
  • FR-012: Perform all operations atomically (rollback on failure)