> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.itential.com/itential-platform/2023-2/control-access/users-groups-roles/reference-user-accounts/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.itential.com/_mcp/server. # Reference user accounts > Best practices for referencing, returning, querying, and sorting user accounts in Itential Platform database documents and APIs. User accounts are uniquely identified in Itential Platform by a database ID, or by a username and provenance pair where provenance is the name of the AAA adapter from which the account originated. This page covers best practices for user account representation, including how to reference accounts in documents, return account data from APIs, and query and sort documents with referenced accounts. ## Best practices ### Account references in database documents Reference user accounts via database ID. In MongoDB, accounts are keyed with `ObjectId`, and references should use that type as well. This allows the application to use `$lookup` in the MongoDB aggregation pipeline for sorting, filtering, and efficient querying when account data needs to be retrieved. ### Accounts in the UI Do not present users with a list of account IDs. Display user lists and references using the username and provenance fields. Username alone is no longer sufficient — users may need to distinguish between similarly named accounts in different systems. ### Account references in APIs Based on how existing APIs and documents are structured, APIs should accept and return both account IDs and username/provenance pairs. Where account IDs are exposed, they should appear as strings in JSON. APIs must take on the burden of validating IDs, converting them to `ObjectId` where appropriate, and testing for equality using the appropriate methods. ## Query, filter, and sort account documents ### Example account document The examples below use the following account document: ```json { "_id": ObjectId("5aebd2fae2c5b5614927362b"), "provenance": "Local AAA", "username": "admin@pronghorn", "firstname": "admin", "memberOf": [...], "assignedRoles": [...], "lastLogin": ISODate("2018-05-30T16:29:39.944Z") } ``` ### Query documents with referenced accounts Denormalizing user account data — for example, storing a copy of the username alongside the account ID — creates a maintenance problem when the account data changes but the copy does not. Instead, load account data at query time to include it in the API response. #### Example workflow document ```json { "_id": "b6517ac9-a8fc-4621-902b-174458005c90", "name": "Example Workflow", "tasks": {}, "transitions": {}, "created": "5/18/2018, 9:32:50 AM", "created_by": { "id": ObjectId("5aebd2fae2c5b5614927362b") }, "last_updated": "5/18/2018, 9:33:31 AM", "last_updated_by": { "id": ObjectId("5aebd2fae2c5b5614927362b") }, "groups": [ ObjectId("5aebd2ffe2c5b5614927362d") ] } ``` #### Example API response with inline account data This response includes the human-readable username and provenance fields alongside the account ID: ```json [ { "id": "b6517ac9-a8fc-4621-902b-174458005c90", "name": "Example Workflow", "created": "5/18/2018, 9:32:50 AM", "created_by": { "id": "5aebd2fae2c5b5614927362b", "username": "admin@pronghorn", "provenance": "Local AAA" }, "last_updated": "5/18/2018, 9:33:31 AM", "last_updated_by": { "id": "5aebd2fae2c5b5614927362b", "username": "admin@pronghorn", "provenance": "Local AAA" } } ] ``` #### Aggregation pipeline query This query produces the desired data set in a single request to MongoDB: ```javascript const workflowListWithInlineAccountsPipeline = [ { $lookup: { from: 'accounts', localField: 'created_by.id', foreignField: '_id', as: 'created_by_accounts' } }, { $lookup: { from: 'accounts', localField: 'last_updated_by.id', foreignField: '_id', as: 'last_updated_by_accounts' } }, { $project: { name: 1, created: 1, created_by_account: { $arrayElemAt: ['$created_by_accounts', 0] }, last_updated: 1, last_updated_by_account: { $arrayElemAt: ['$created_by_accounts', 0] } } } ]; const workflowList = await workflowsCollection.aggregate(workflowListWithInlineAccountsPipeline).toArray(); ``` ### Filter and sort documents by referenced account fields You can extend the pipeline above to filter and sort by account fields: ```javascript const filteredAndSortedByCreatorPipeline = [ { $match: { name: /^Exa/ } }, ...workflowListWithInlineAccountsPipeline, { $sort: { 'created_by_account.username': 1 } }, ]; const workflowList = await workflowsCollection.aggregate(filteredAndSortedByCreatorPipeline).toArray(); ``` > Best practices for referencing, returning, querying, and sorting user accounts in Itential Platform database documents and APIs.