Skip to main content

List Profiles

API Endpoint: GET /admin/law-firms/{lawFirmId}/profiles

Priority: P1

User Story: As an admin, I want to list all user profiles within a law firm with pagination and filtering.

Overview

Retrieve a paginated list of all user profiles within a specific law firm, including their Logto user ID, functional roles, and profile metadata. Supports filtering by role and search by name/email.

Scenarios

Scenario 1: List first page of profiles

Given:

  • Admin is authenticated with scope profiles:read
  • Law firm firm_abc123 exists with 75 user profiles

When:

  • Admin GETs /admin/law-firms/firm_abc123/profiles?page[number]=1&page[size]=25

Then:

  • Response status is 200 OK
  • Response body contains:
    • data: Array of 25 profile objects
    • meta.pagination.page: 1
    • meta.pagination.pageSize: 25
    • meta.pagination.totalItems: 75
    • meta.pagination.totalPages: 3

Scenario 2: Filter by functional role

Given:

  • Admin is authenticated with scope profiles:read
  • Law firm has 50 total profiles (20 LAWYER, 15 PARALEGAL, 10 RECEPTIONIST, 5 OTHER)

When:

  • Admin GETs /admin/law-firms/firm_abc123/profiles?functionalRole=LAWYER

Then:

  • Response status is 200 OK
  • Response contains only profiles with LAWYER role
  • meta.pagination.totalItems: 20

Scenario 3: Search by name or email

Given:

  • Admin is authenticated with scope profiles:read
  • Law firm has multiple profiles

When:

  • Admin GETs /admin/law-firms/firm_abc123/profiles?search=john

Then:

  • Response status is 200 OK
  • Response contains profiles where:
    • First name contains "john" (case-insensitive) OR
    • Last name contains "john" OR
    • Email contains "john"
  • Profiles like "John Smith", "Johnson", "john@example.com" are included

Scenario 4: Multiple functional roles filter

Given:

  • Admin is authenticated with scope profiles:read

When:

  • Admin GETs /admin/law-firms/firm_abc123/profiles?functionalRole=LAWYER,PARALEGAL

Then:

  • Response status is 200 OK
  • Response contains profiles with either LAWYER or PARALEGAL roles
  • Other roles are excluded

Scenario 5: Empty result set

Given:

  • Admin is authenticated with scope profiles:read
  • Law firm firm_abc123 has no user profiles

When:

  • Admin GETs /admin/law-firms/firm_abc123/profiles

Then:

  • Response status is 200 OK
  • Response body contains:
    {
    "data": [],
    "meta": {
    "pagination": {
    "page": 1,
    "pageSize": 50,
    "totalItems": 0,
    "totalPages": 0
    }
    }
    }

Scenario 6: Law firm not found

Given:

  • Admin is authenticated with scope profiles:read
  • No law firm with ID firm_nonexistent

When:

  • Admin GETs /admin/law-firms/firm_nonexistent/profiles

Then:

  • Response status is 404 Not Found
  • Response body contains:
    {
    "error": "NOT_FOUND",
    "message": "Law firm with ID 'firm_nonexistent' not found"
    }

Scenario 7: Invalid page number

Given:

  • Admin is authenticated with scope profiles:read

When:

  • Admin GETs /admin/law-firms/firm_abc123/profiles?page[number]=0

Then:

  • Response status is 400 Bad Request
  • Response contains validation error:
    {
    "error": "VALIDATION_ERROR",
    "message": "Page number must be >= 1"
    }

Request Specification

Path Parameters

ParameterTypeRequiredDescription
lawFirmIdstringYesLaw firm identifier

Query Parameters

ParameterTypeRequiredDefaultConstraintsDescription
page[number]integerNo1Min: 1Page number to retrieve
page[size]integerNo50Min: 1, Max: 200Items per page
functionalRolestringNo(all)CSV or single valueFilter by role(s)
searchstringNo(none)Min: 2 charsSearch by name or email
includeInactivebooleanNofalse-Include inactive profiles

Functional Role Values

ValueDescription
LAWYERLicensed attorney
PARALEGALParalegal or legal assistant
RECEPTIONISTFront desk or administrative
BILLING_ADMINBilling and accounting
IT_ADMINIT and systems administration
INTERNStudent or intern
OTHEROther roles

Response Specification

Success Response (200 OK)

{
"data": [
{
"id": "user_12345",
"lawFirmId": "firm_abc123",
"logtoUserId": "logto_xyz789",
"email": "jane.doe@acme-legal.com",
"firstName": "Jane",
"lastName": "Doe",
"functionalRoles": ["LAWYER", "BILLING_ADMIN"],
"title": "Senior Partner",
"department": "Corporate Law",
"phoneNumber": "+1-555-0100",
"isActive": true,
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-06-20T14:30:00Z"
},
{
"id": "user_67890",
"lawFirmId": "firm_abc123",
"logtoUserId": "logto_abc456",
"email": "john.smith@acme-legal.com",
"firstName": "John",
"lastName": "Smith",
"functionalRoles": ["PARALEGAL"],
"title": "Senior Paralegal",
"department": "Litigation",
"phoneNumber": "+1-555-0101",
"isActive": true,
"createdAt": "2024-03-10T09:15:00Z",
"updatedAt": "2024-03-10T09:15:00Z"
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 50,
"totalItems": 75,
"totalPages": 2
}
}
}

Response Fields

FieldTypeDescription
dataarrayArray of user profile objects
data[].idstringUser profile identifier
data[].lawFirmIdstringLaw firm identifier
data[].logtoUserIdstring | nullLogto user ID (if linked)
data[].emailstringUser email address
data[].firstNamestringFirst name
data[].lastNamestringLast name
data[].functionalRolesarrayArray of functional role enums
data[].titlestring | nullJob title
data[].departmentstring | nullDepartment name
data[].phoneNumberstring | nullPhone number
data[].isActivebooleanWhether profile is active
data[].createdAtstringCreation timestamp
data[].updatedAtstringLast update timestamp
meta.paginationobjectPagination metadata
meta.pagination.pageintegerCurrent page number
meta.pagination.pageSizeintegerItems per page
meta.pagination.totalItemsintegerTotal matching profiles
meta.pagination.totalPagesintegerTotal number of pages

Error Responses

StatusError CodeDescription
400VALIDATION_ERRORInvalid query parameters
401UNAUTHORIZEDMissing or invalid auth token
403FORBIDDENMissing profiles:read scope
404NOT_FOUNDLaw firm not found

Requirements Mapping

  • FR-057: Accept GET with lawFirmId path parameter
  • FR-058: Support pagination with page[number] and page[size]
  • FR-059: Default page size to 50, max 200
  • FR-060: Return paginated array of user profiles
  • FR-061: Include pagination metadata (page, pageSize, totalItems, totalPages)
  • FR-062: Support filtering by functionalRole (single or comma-separated)
  • FR-063: Support search query across firstName, lastName, email
  • FR-064: Default to excluding inactive profiles
  • FR-065: Support includeInactive parameter
  • FR-066: Return empty array when no profiles exist
  • FR-067: Include logtoUserId in response (may be null)
  • FR-068: Validate page number >= 1
  • FR-069: Validate page size between 1 and 200

Notes

Performance Considerations

For law firms with thousands of profiles:

  • Use pagination to limit response size
  • Consider adding indexes on functionalRoles and email fields
  • Search queries may require full-text search optimization

Profile vs User

This endpoint returns profiles (law firm-specific user records), not Logto users. A single Logto user may have profiles in multiple law firms.

Sorting

Results are sorted by createdAt descending (newest first) by default. Future versions may support custom sorting via query parameters.