Profiles
Profiles let you provision and govern users at scale.
Profiles let you provision and govern users at scale. A profile is a reusable template of settings (license type, permissions, queues, interaction spaces, themes, dialing options, integration bindings) that you apply to users. Each user assigned to a profile inherits the profile's values; the user can then override individual fields, and the API tracks which fields have been overridden. When you update a profile, the platform runs a background job that propagates the updated values to the profile's users while preserving each user's overrides.
This page walks through the full profile lifecycle: designing a profile, finding and reading profiles, updating profiles and understanding the sync that follows, creating and updating users in relation to a profile, inspecting which users have drifted from their profile, and force-syncing users back to profile defaults.
All examples use cURL. All endpoints are hosted at:
https://core.{customerId}.ec.avayacloud.com/api/config/v1
where {customerId} is your organization identifier.
Contents
- Overview
- Authentication
- License Types
- Creating a Profile
- Listing and Searching Profiles
- Retrieving a Profile
- Updating a Profile
- Profile Sync Jobs
- Inspecting Profile Users and Overrides
- Creating a User from a Profile
- Reassigning a User to a Different Profile
- Editing User Fields and How Overrides Work
- Force-Syncing Users to a Profile
- Deleting a Profile
- Errors and Conflicts
Overview
A profile sits between your account's licensing and your users. You create a profile with a license type and a baseline configuration; then every user you create from that profile inherits its values. Profiles let you keep hundreds of agents consistent without copying configuration field-by-field.
Three concepts are essential to using these APIs correctly:
-
License-type defaults. When you create a profile, the license type you pick (for example
omniChannelAgent) determines the starting permissions, default interaction-space counts, and queue configuration. If you omit a configuration block, the platform applies the license-type defaults for that block. You can override any of them in the same request. -
User overrides. Once a user has been created from a profile, anything you change on the user is tracked as an override. The API exposes both an aggregate (
numUsersWithOverrideson the profile) and a per-user list (overriddenFieldsfor each user). Overrides are how policy meets reality: agents legitimately diverge from the template (different timezone, different queue access, different theme), and the platform remembers what was customized. -
Sync jobs. Two background jobs propagate profile changes to users:
PRFUPD: created automatically when youPATCH /profiles/{profileId}. It pushes the updated fields to assigned users while preserving each user's overrides. Only fields the user has not personally overridden are touched.FSYNC: created explicitly when you call the force-sync endpoints. It clears all overrides for the targeted users and copies the profile's current values back onto them.
The rest of this page treats these three concepts as they come up.
User limit per profile. A profile supports at most 500 assigned users. Attempting to assign a 501st user via
POST /usersorPATCH /users/USERID(withprofileId) is rejected with422. Profile updates viaPATCH /profiles/{profileId}are also blocked while a profile is over the limit. ThenumUsersfield on the profile reflects the current count.
Required role. All profile and user endpoints require an administrator-level token. Profile endpoints require the Account Administrator role. User endpoints require Admin Portal or Admin API Consumer.
Authentication
Every request to the API must include a Bearer access token in the Authorization header. Tokens are obtained through the OAuth 2.0 client credentials grant using the credentials issued during your account's onboarding.
Request an access token
curl -X POST 'https://auth.{customerId}.ec.avayacloud.com/realms/{realm}/protocol/openid-connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials' \
-d 'client_id=YOUR_CLIENT_ID' \
-d 'client_secret=YOUR_CLIENT_SECRET'The response contains an access_token:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR...",
"expires_in": 1800,
"token_type": "Bearer",
"scope": "openid profile"
}Use the token
Pass the token as a Bearer credential on every API request:
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles' \
-H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR...'Note. Access tokens expire (commonly after 30 minutes; check
expires_inin the token response). When a request returns401 Unauthorizedwithdetail: "Bearer token expired...", request a new token using the same client credentials.
The token URL and realm are issued to you during account onboarding. The customerId is the same value you use in the API base URL.
License Types
The license type assigned to a profile (and inherited by its users) determines the default permission set, the starting interaction-space allocation, and which features are enabled out of the box. You can always override individual fields after the profile is created, but the license type controls the baseline.
| License Type | Intended For | Default Spaces | Notable Defaults |
|---|---|---|---|
nonAgent | Read-only users, supervisors who don't take interactions | 1 task, 1 email, 1 messaging | Minimal permissions |
voiceOnlyAgent | Phone-only agents | 2 task, 1 phone | Voice-focused permissions |
digitalOnlyAgent | Email + messaging agents (no phone) | 3 task, 2 email, 2 messaging | Digital channels enabled, phone disabled |
omniChannelAgent | All-channel agents except video | 3 task, 2 email, 1 phone, 2 messaging | All non-video channels enabled |
omniChannelAgentEnhanced | Senior all-channel agents | Same as omniChannelAgent | Enhanced features and session statistics enabled |
hybridVoiceAgent | Agents bridging Avaya Infinity and on-premises Aura voice | Balanced voice + digital | Adds Elite/Aura-specific configuration fields |
When you create a profile, you can omit any of permissions, queues, spaces, and attributes. The platform fills in the license-type defaults for whichever you omit. Anything you provide takes precedence and is used as the profile's value.
Creating a Profile
Create a profile with POST /profiles. The only required fields are name (unique within the account) and licType.
Minimal create
curl -X POST 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Observer Profile",
"description": "Profile for users who need read-only access",
"licType": "nonAgent"
}'The platform applies the nonAgent license-type defaults (minimal permissions; 1 task, 1 email, 1 messaging space), the platform-wide defaults (appTheme: light, consoleTheme: light, timeZone: the account's configured default timezone, interactionViewsType: all, modifyInteractionViews: true), and returns the fully realized profile:
{
"id": "16a7490f-86a6-4a14-8ce2-11682230adb6",
"accountId": "001d01022054849399088a81ad",
"name": "Observer Profile",
"description": "Profile for users who need read-only access",
"licType": "nonAgent",
"permissions": { /* license-type defaults */ },
"queues": { "access": [], "performance": [], "autoLogin": [], "proficiency": [], "logins": [], "defaultOutboundQueue": null, "outboundQueueId": null },
"spaces": { "task": [], "email": [], "phone": [], "video": [], "messaging": [] },
"tags": [],
"attributes": {
"time": { "tz": "America/New_York" },
"taskSpaces": 1,
"emailSpaces": 1,
"messagingSpaces": 1,
"phoneSpaces": 0,
"videoSpaces": 0
},
"groups": [],
"appTheme": "light",
"consoleTheme": "light",
"timeZone": "America/New_York",
"interactionViewsType": "all",
"modifyInteractionViews": true,
"syncStatus": "SYNCED",
"numUsers": 0,
"numUsersWithOverrides": 0,
"createdAt": "2026-05-15T10:04:24.181Z",
"createdBy": "002d010826307dd6630992437b"
}Richer create
You can override license-type defaults and platform defaults in the same call, place the profile in a folder, and bind it to a location:
curl -X POST 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Senior Agent Profile",
"description": "Profile for experienced agents with all features",
"licType": "omniChannelAgentEnhanced",
"profileFolderId": "073d010813b941cf7da111d147",
"locationId": "022d01091776cc88fe6866b7ce",
"appTheme": "dark",
"timeZone": "America/Los_Angeles",
"commTypeChangeDefaultValue": "callback",
"infinityElements": ["elem_a1b2c3", "elem_d4e5f6"]
}'infinityElements can be set at creation, but only for agent license types. Setting it on a nonAgent profile returns a 422 ("Cannot set fields (infinityElements) for non-agent license type").
Validation rules
namemust be unique within the account.licTypemust be one of the values in the License Types table.profileFolderId, if provided, must reference an existing folder.locationId, if provided, must reference an existing location. Location IDs are system-generated and always begin with022.
Common errors
| Status | Condition |
|---|---|
400 | Required field missing or malformed |
409 | A profile with the same name already exists in this account |
422 | Validation failed; see violations[] array in the response body |
Listing and Searching Profiles
Use GET /profiles to list profiles. The endpoint supports pagination, filtering, sorting, folder scoping, and date-range filtering.
List all profiles
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles' \
-H 'Authorization: Bearer ACCESS_TOKEN'{
"pagination": { "pageNumber": 1, "pageSize": 10, "total": 2 },
"links": { "prev": "", "next": "" },
"profiles": [
{
"id": "6d45f30d-dd0e-4546-b932-b6b1f223c9f3",
"name": "Admin Profile",
"description": "Profile for customer admin representatives",
"licType": "hybridVoiceAgent",
"profileFolderId": "073d01090149abae69f6305afe",
"createdBy": "002d010826307dd6630992437b",
"updatedAt": "2026-05-09T10:03:45.883Z"
},
{
"id": "d5cfccf4-0507-49f8-98d9-34fdaeefca5d",
"name": "Customer Support Profile",
"description": "Profile for customer support representatives",
"licType": "hybridVoiceAgent",
"createdBy": "002d010826307dd6630992437b",
"updatedAt": "2026-05-09T10:02:53.596Z"
}
]
}Pagination
| Parameter | Default | Range | Notes |
|---|---|---|---|
pageNumber | 1 | ≥ 1 | The page to return |
pageSize | 10 | 5–100 | Profiles per page |
The response links.prev and links.next are blank strings when you are on the first or last page respectively.
Folder filtering
The folderId parameter has three modes:
| Parameter | Behavior |
|---|---|
folderId omitted | Returns profiles from all folders in the account |
folderId= (empty string) | Returns only root-folder profiles (profiles not assigned to any folder) |
folderId=073d01090149abae69f6305afe | Returns profiles in that folder only (does not include subfolders by default) |
folderId=...&includeSubfolders=true | Returns profiles in that folder and all its subfolders recursively |
Examples:
# Profiles in a specific folder, not including subfolders
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?folderId=073d01090149abae69f6305afe' \
-H 'Authorization: Bearer ACCESS_TOKEN'
# Profiles in a specific folder and every subfolder
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?folderId=073d01090149abae69f6305afe&includeSubfolders=true' \
-H 'Authorization: Bearer ACCESS_TOKEN'
# Root-folder profiles only
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?folderId=' \
-H 'Authorization: Bearer ACCESS_TOKEN'Filter syntax
The filter query parameter applies a single-field filter. The syntax distinguishes exact match (=) from pattern match (:):
| Form | Behavior | Example |
|---|---|---|
field=value | Exact match | licType=hybridVoiceAgent |
field:value | Substring contains | name:Customer |
field:value* | Starts with | name:Support* |
field:*value | Ends with | name:*Agent |
Filterable fields: name, description, licType, syncStatus, createdBy, updatedBy, createdAt, updatedAt. Field names are case-sensitive.
# Profiles whose name starts with "Support"
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?filter=name:Support*' \
-H 'Authorization: Bearer ACCESS_TOKEN'
# Profiles for a specific license type
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?filter=licType=hybridVoiceAgent' \
-H 'Authorization: Bearer ACCESS_TOKEN'Sort order
orderBy accepts a field name plus an optional desc suffix. Default is updatedAt desc (most recently updated first).
Sortable fields: name, description, licType, syncStatus, numUsers, createdBy, updatedBy, createdAt, updatedAt.
# Sort alphabetically by name
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?orderBy=name' \
-H 'Authorization: Bearer ACCESS_TOKEN'
# Profiles with the most users first
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?orderBy=numUsers%20desc' \
-H 'Authorization: Bearer ACCESS_TOKEN'Date-range filtering
updatedSince and updatedUntil filter by the profile's updatedAt timestamp. Both accept ISO 8601 with timezone offset. They may be used independently or combined; when combined, updatedSince must be less than updatedUntil.
# Profiles updated in the last 24 hours
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?updatedSince=2026-05-14T00:00:00Z' \
-H 'Authorization: Bearer ACCESS_TOKEN'
# Profiles updated in Q1 2026
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles?updatedSince=2026-01-01T00:00:00Z&updatedUntil=2026-03-31T23:59:59Z' \
-H 'Authorization: Bearer ACCESS_TOKEN'Retrieving a Profile
GET /profiles/{profileId} returns the full profile, including its permissions, queues, spaces, attributes, sync metadata, and resolved CRM configuration.
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/1ac75384-6099-424c-a179-9038a7a44a54' \
-H 'Authorization: Bearer ACCESS_TOKEN'{
"id": "1ac75384-6099-424c-a179-9038a7a44a54",
"accountId": "001d01022054849399088a81ad",
"name": "Customer Support Profile",
"description": "Profile for customer support representatives",
"licType": "hybridVoiceAgent",
"locationId": null,
"permissions": { /* ... */ },
"queues": {
"access": [],
"performance": [],
"autoLogin": [],
"proficiency": [],
"logins": [],
"defaultOutboundQueue": null,
"outboundQueueId": null
},
"spaces": { "task": [], "email": [], "phone": [], "video": [], "messaging": [] },
"attributes": {
"time": { "tz": "America/New_York" },
"taskSpaces": 3,
"emailSpaces": 3,
"phoneSpaces": 1,
"videoSpaces": 0,
"messagingSpaces": 3
},
"tags": [],
"groups": ["007d01090301ad8db0f0d4c370"],
"appTheme": "light",
"consoleTheme": "light",
"timeZone": "America/New_York",
"syncStatus": "SYNCED",
"numUsers": 12,
"numUsersWithOverrides": 4,
"createdAt": "2026-04-08T06:19:21.561Z",
"createdBy": "002d010826307dd6630992437b",
"updatedAt": "2026-05-09T10:02:53.596Z",
"updatedBy": "002d010826307dd6630992437b"
}The crmConfigId query parameter
crmConfigId query parameterWhen crmConfigId=true (the default), the response inlines the full CRM configuration object under crmConfigurations. Set crmConfigId=false to return just the raw CRM config ID instead, useful for callers that only need the reference:
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/1ac75384-6099-424c-a179-9038a7a44a54?crmConfigId=false' \
-H 'Authorization: Bearer ACCESS_TOKEN'Reading the response
The response is grouped logically:
- Identity:
id,accountId,name,description,licType,profileFolderId,locationId. - Access control:
permissions(nested app/console structure),queues,tags,groups. - Interaction surface:
spaces(task/email/phone/video/messaging),attributes(timezone, space counts, queue settings, WebRTC/WebHID). The same space counts (taskSpaces,emailSpaces,phoneSpaces,videoSpaces,messagingSpaces) also appear at the top level of the response, alongsidetaskPickupOverMultiplicity,emailPickupOverMultiplicity,phonePickupOverMultiplicity, andmessagingPickupOverMultiplicity. - UI and locale:
appTheme,consoleTheme,timeZone,interactionViewsType,definedInteractionViews,modifyInteractionViews,commTypeChangeDefaultValue. - Voice / UC:
defaultOutboundCallerId,dialPlanProfileId,enableWebHID,enableErrorTones,allowInternalCalls,previewOutbound,predictiveOutbound,persistentMedia,ucPhoneSpaces,useUCPhoneSpaceOnCCCall,useCCPhoneSpaceOnUCCall,externalUCProviderConnections. - Integrations:
crmConfigurations(shape depends on thecrmConfigIdquery parameter),infinityElements. - Sync metadata:
syncStatus,syncJobId(present when a sync is active),numUsers,numUsersWithOverrides. - Audit metadata:
createdAt,createdBy,updatedAt,updatedBy.
Updating a Profile
PATCH /profiles/{profileId} performs a partial update: only fields included in the request body are modified. Omitted fields keep their current values.
Rename and re-describe
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Updated Observer Profile",
"description": "Updated profile for users who need read-only access"
}'Change the license type
Changing the license type applies that license's new baseline to fields you have not explicitly configured.
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"licType": "voiceOnlyAgent",
"name": "Voice Agent Profile"
}'Move a profile into (or out of) a folder
# Move to a folder
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "profileFolderId": "073d01090149abae69f6305afe" }'
# Remove from current folder
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "profileFolderId": null }'What happens to assigned users
Every successful
PATCH /profiles/{profileId}queues a background sync job. The job propagates the updated values to all users assigned to this profile while preserving each user's overrides: only fields the user has not personally overridden are touched. The next section explains the sync lifecycle.
The PATCH response includes the new syncJobId and syncStatus:
{
"id": "16a7490f-86a6-4a14-8ce2-11682230adb6",
"name": "Voice Agent Profile",
"licType": "voiceOnlyAgent",
"syncStatus": "SYNC_QUEUED",
"syncJobId": "c8c2909d-75e9-484a-94c0-b7e8d30771fe",
"numUsers": 12,
"numUsersWithOverrides": 4,
"updatedAt": "2026-05-15T14:45:00Z",
"updatedBy": "002d010826307dd6630992437b"
}Validation rules
name, if changed, must remain unique within the account.licType, if changed, must be a valid license type for the account.profileFolderId, if provided, must reference an existing folder. Sendnullto detach.locationId, if provided, must reference an existing location.
Common errors
| Status | Condition |
|---|---|
400 | Request body malformed |
404 | profileId does not exist |
409 | The new name conflicts with an existing profile, or a sync job is already in progress on this profile |
422 | Validation failed (violations[]), or the profile has more than 500 assigned users |
The "active sync job" 409 looks like this:
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#conflict",
"title": "Conflict",
"status": 409,
"detail": "Profile cannot be updated while a sync job is in progress (jobId: c8c2909d-75e9-484a-94c0-b7e8d30771fe). Please wait for it to complete."
}When you see it, wait for the current sync to clear (see the next section), then retry the PATCH.
Profile user limit (422)
A profile supports at most 500 assigned users. When numUsers exceeds 500, PATCH /profiles/{profileId} is rejected (updates remain allowed at exactly 500):
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#validation-failed",
"title": "Validation Failed",
"status": 422,
"detail": "Profile User limit of 500 reached. Cannot update profile",
"violations": [
{
"field": "profileId",
"message": "Profile User limit of 500 reached. Cannot update profile",
"code": 20005
}
]
}To clear this state, reassign the excess users to a different profile (or detach them) until numUsers is back at or below 500, then retry the PATCH.
Profile Sync Jobs
Two background jobs propagate profile changes to users. Understanding the difference is essential before you write automation against these APIs.
PRFUPD: preserves overrides
A PRFUPD job is created automatically by every successful PATCH /profiles/{profileId}. It walks every user assigned to the profile and copies each updated field onto the user only if the user has not personally overridden that field. Overrides are preserved.
FSYNC: clears overrides
An FSYNC job is created when you explicitly call one of the force-sync endpoints:
POST /users/USERID:force-sync-profile(single user)POST /users:bulk-force-sync-profile(bulk)
FSYNC is the opposite of PRFUPD: it copies the profile's current values onto the user regardless of overrides, then clears all override tracking for that user. After an FSYNC, the user is, by definition, fully in sync with the profile.
The syncStatus lifecycle
syncStatus lifecycleEach profile exposes a syncStatus field that reflects the state of its most recent (or active) sync job:
PATCH /profiles/{id}
or force-sync request
│
▼
SYNC_QUEUED ──────────► SYNC_IN_PROGRESS
│
┌─────────────┴─────────────┐
▼ ▼
SYNCED SYNC_FAILED
(all users updated) (job aborted before
all users updated)
| Status | Meaning |
|---|---|
SYNCED | The profile and its users are in agreement. Default starting state. |
SYNC_QUEUED | A change has been received; the worker has not yet started processing. |
SYNC_IN_PROGRESS | The sync worker is currently updating users. |
SYNC_FAILED | The job ended in failure or was aborted before all users could be updated. |
Checking sync status
PATCH /profiles/{profileId} returns immediately; the update itself finishes asynchronously as a background sync job. To confirm it's done, poll the profile and check syncStatus:
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6' \
-H 'Authorization: Bearer ACCESS_TOKEN'syncStatus moves from SYNC_QUEUED to SYNC_IN_PROGRESS and then to SYNCED once every assigned user has been updated (or SYNC_FAILED if the sync didn't complete). Once it reaches SYNCED, it's safe to issue another PATCH or FSYNC against the same profile.
Tip. A second
PATCHor force-sync against a profile while a sync is still in progress returns409 Conflict. Either poll untilsyncStatusclears, or design your automation to coalesce changes into a single PATCH.
Inspecting Profile Users and Overrides
GET /profiles/{profileId}/users lists the users assigned to a profile, with a per-user breakdown of which fields have been overridden.
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6/users?hasOverrides=true&pageNumber=1&pageSize=10' \
-H 'Authorization: Bearer ACCESS_TOKEN'{
"pagination": { "pageNumber": 1, "pageSize": 10, "total": 4 },
"links": { "prev": "", "next": "" },
"users": [
{
"userId": "002d011003cf7c9d1b469ddc7e",
"email": "[email protected]",
"firstName": "Hiten",
"lastName": "Agent",
"fullName": "Hiten Agent",
"hasOverrides": true,
"overriddenFields": [
"appTheme",
"queues.access",
"permissions.app.agent.read"
],
"folderId": "073d010813b941cf7da111d147"
}
]
}Query parameters
| Parameter | Type | Notes |
|---|---|---|
pageNumber | int | Optional. When omitted with pageSize, the response has no pagination metadata. |
pageSize | int | Optional, 5–100. |
hasOverrides | boolean | true returns only users with at least one override; false returns only fully synced users; omitted returns all. |
search | string | Case-insensitive substring match on first name, last name, or email (max 100 chars). |
What gets tracked as an override
Override tracking covers profile-managed fields. When an admin (or the user themselves) changes one of these fields on a user, the field path is recorded in overriddenFields:
- Permissions (nested, e.g.,
permissions.app.agent.read) - Queues (
queues.access,queues.performance,queues.autoLogin,queues.proficiency,queues.logins,queues.defaultOutboundQueue,queues.outboundQueueId) - Spaces (
spaces.task,spaces.email,spaces.phone,spaces.video,spaces.messaging) tags,attributes,groupsappTheme,consoleTheme,timeZoneinteractionViewsType,definedInteractionViews,modifyInteractionViewscommTypeChangeDefaultValue,defaultOutboundCallerId,locationId,dialPlanProfileId- Feature flags:
deferEnabled,enableWebHID,enableErrorTones,allowInternalCalls,allowAgentEditAutoAnswer,allowAgentEditWebHIDHeadsetControl,rejectInteractions,previewOutbound,predictiveOutbound,persistentMedia
User-identity fields (email, firstName, lastName, mobile, extension, title) are not profile-managed and are never tracked as overrides.
What you can do with this data
- Audit drift. Filter
hasOverrides=trueto find users who have diverged from policy. - Plan a force-sync. Identify high-override users, decide whether to keep their overrides (do nothing;
PRFUPDwill continue to preserve them) or reset them (force-sync, which clears overrides). - Reconcile after a license change. Read the list before and after a
PATCHthat changeslicTypeto see which users absorbed the change cleanly and which need follow-up.
Creating a User from a Profile
POST /users creates a user. The minimum required fields are email, firstName, lastName, and either licType or profileId. When you provide profileId, the license type is taken from the profile.
Minimal create with a profile
curl -X POST 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"profileId": "16a7490f-86a6-4a14-8ce2-11682230adb6"
}'The platform copies every profile-managed field from the profile onto the new user. The user starts life fully in sync with the profile (hasOverrides: false, empty overriddenFields).
Richer create
You can add user-specific fields that don't live on a profile (mobile, extension, title), assign the user to a folder, and override profile-managed fields at creation time:
curl -X POST 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"title": "Senior Support Agent",
"mobile": "+16479308804",
"extension": "1001",
"profileId": "16a7490f-86a6-4a14-8ce2-11682230adb6",
"folderId": "073d010813b941cf7da111d147",
"locationId": "022d01091776cc88fe6866b7ce",
"appTheme": "dark",
"timeZone": "America/Los_Angeles",
"queues": {
"access": ["00301090301ad8db0f0d4c370"]
}
}'Important. Any profile-managed field included in the create request becomes an override on the user from day one. In the example above,
appTheme,timeZone, andqueues.accesswill appear in the user'soverriddenFields. LaterPRFUPDjobs will preserve them; anFSYNCwill clear them.
What gets pulled from the profile
When you create a user with a profileId and omit a field, the profile's value is used:
licType(always inherited)permissions,queues,spaces,attributes,tags,groupsappTheme,consoleTheme,timeZoneinteractionViewsType,definedInteractionViews,modifyInteractionViewscommTypeChangeDefaultValue,defaultOutboundCallerId,locationId,dialPlanProfileId- Feature flags from the profile (
enableWebHID,allowInternalCalls,rejectInteractions,previewOutbound,predictiveOutbound,persistentMedia, etc.) crmConfigId,externalUCProviderConnections,infinityElements
Validation rules
emailmust be unique within the account.licTypemust be valid for the account (resolved via the profile whenprofileIdis provided).profileIdmust reference an existing profile.folderIdmust reference an existing folder.locationIdmust reference an existing location.- The target profile must have fewer than 500 assigned users. Assigning to a profile already at the cap is rejected with
422.
Common errors
| Status | Condition |
|---|---|
400 | Request body malformed or required field missing |
409 | A user with the same email already exists in this account |
422 | Validation failed (violations[]), or the target profile is already at the 500-user cap |
The duplicate-email 409 response:
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#conflict",
"title": "Conflict",
"status": 409,
"detail": "A resource with the same unique constraint values already exists.",
"violations": [
{ "field": "email", "message": "A user with this email already exists" }
]
}The profile-user-limit 422 response (when assigning to a profile that already has 500 users):
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#validation-failed",
"title": "Validation Failed",
"status": 422,
"detail": "Profile User limit of 500 reached. Cannot add user to the profile",
"violations": [
{
"field": "profileId",
"message": "Profile User limit of 500 reached. Cannot add user to the profile",
"code": 20005
}
]
}Reassigning a User to a Different Profile
You reassign a user by PATCH /users/USERID with a new profileId.
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "profileId": "d5cfccf4-0507-49f8-98d9-34fdaeefca5d" }'Important: reassignment does not re-apply the new profile's defaults. The user's existing field values are preserved as-is. The association on the user record is updated, but the values on the user are not. If you want the user to actually pick up the new profile's settings, call
POST /users/USERID:force-sync-profileimmediately after reassigning.
500-user cap on the target profile. Reassigning to a profile that already has 500 assigned users returns
422withdetail: "Profile User limit of 500 reached. Cannot add user to the profile"(violation code20005). Move existing users off the target profile first, or pick a different profile.
Detaching a user from any profile
Send "profileId": null to clear the association. The user keeps its current field values, but override tracking against the previous profile is dropped.
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "profileId": null }'Common recipe: reassign and immediately re-sync
# 1. Reassign
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "profileId": "d5cfccf4-0507-49f8-98d9-34fdaeefca5d" }'
# 2. Force-sync the user to the new profile's values
curl -X POST 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e:force-sync-profile' \
-H 'Authorization: Bearer ACCESS_TOKEN'Editing User Fields and How Overrides Work
PATCH /users/USERID updates one or more user fields. All fields are optional; at least one must be present.
The merge behavior depends on the field type:
| Field | Merge Behavior |
|---|---|
| Scalar fields | Replaced with the provided value |
attributes | Deep-merged. Nested keys queue, time, webRTC, recording, signatures, sessionStats are deep-merged; other top-level keys are replaced |
permissions | Merged per section (app, console). Keys within each section are replaced with what's sent; keys not included are preserved |
queues | Only sub-properties included in the request are updated; omitted sub-properties are left unchanged. The user's personal queue is always preserved in access and autoLogin |
tags | Replaced with the provided array (empty array clears all tags) |
groups | Replaced with the provided array (empty array clears all memberships) |
spaces | Replaced |
Override a single field
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "appTheme": "dark" }'Result: appTheme is added to the user's overriddenFields. The profile's appTheme value no longer applies to this user.
Update a queue assignment without disturbing others
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"queues": {
"access": ["00301090301ad8db0f0d4c370", "00301090301ad8db0f0d4c371"]
}
}'Only queues.access is replaced. queues.performance, queues.autoLogin, queues.proficiency, etc. are left as they were.
Deep-merge into attributes
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"attributes": {
"time": { "tz": "Europe/London" }
}
}'Only attributes.time.tz is changed. The rest of attributes (including the other keys inside attributes.time) is preserved.
Clear a field
For fields that accept null, send null to revert to the default or detach the value:
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"extension": null,
"mobile": null,
"commTypeChangeDefaultValue": null
}'Agent self-edit restrictions
When an agent edits their own user record (the caller and the target are the same user, and the caller is not an administrator), the server blocks changes to administrator-managed identity fields:
firstName, lastName, namePrefix, nameSuffix, title, email, mobile.
Any self-edit that attempts to change one or more of these fields to a different value returns 403 Forbidden:
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "You are not permitted to modify firstName, email. These fields are managed by your administrator."
}The detail lists the specific fields that were rejected. Sending one of these fields with its current value (e.g. a UI that submits the whole user object on save) is allowed; only attempted changes are blocked.
Administrators (users with console account access) editing other users are not subject to this restriction.
Note on the
allowAgentEditAutoAnswerandallowAgentEditWebHIDHeadsetControlflags. These flags exist on both users and profiles. They control whether the Admin Console exposes the Auto Answer and WebHID Headset Control settings as editable in the agent's own profile UI. They do not gate the API: administrators (and the agent themselves) can changeattributes.webRTC.autoAnswer.interactionandattributes.webHID.statusdirectly via the API regardless of the flag values.
Agents can freely edit unrestricted fields on themselves: appTheme, consoleTheme, timeZone, queue selections, defined interaction views, attribute settings, and so on.
Force-Syncing Users to a Profile
Force-syncing copies the profile's current values onto a user (or set of users) and clears all overrides for them. After force-sync, the user is fully in sync with their profile.
Feature gate. The force-sync endpoints return
403 Forbiddenif the Profile Sync feature is not available for your account. Contact your Avaya representative if you need it enabled.
Single user: synchronous
POST /users/USERID:force-sync-profile performs an immediate, synchronous sync and returns the updated user.
curl -X POST 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e:force-sync-profile' \
-H 'Authorization: Bearer ACCESS_TOKEN'The response is the full UserDetail after the sync has been applied. The user's overriddenFields list will be empty.
| Status | Condition |
|---|---|
200 | Success; body is the updated user |
400 | The user has no associated profile |
403 | The Profile Sync feature is not available for this account |
404 | The user does not exist |
Bulk: asynchronous
POST /users:bulk-force-sync-profile operates over many users. It returns immediately with 202 Accepted and a jobId for internal tracking.
The request body uses a oneOf between two modes:
Mode A: explicit user list. Pass up to 50 user IDs. Each user is synced to its own profile (the users may belong to different profiles).
curl -X POST 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users:bulk-force-sync-profile?jobName=Quarterly%20Sync' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"userIds": [
"0024ffcec98220644b194e3e25",
"0024a83190db2884efeb3bf96d"
]
}'Mode B: by profile. Pass a profileId. The platform auto-resolves all users that currently have overrides on that profile and force-syncs them. Use this to mass-reset drift after a policy change.
curl -X POST 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users:bulk-force-sync-profile?jobName=Reset%20Overrides' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"profileId": "16a7490f-86a6-4a14-8ce2-11682230adb6"
}'Response (202 Accepted):
{
"jobId": "c8c2909d-75e9-484a-94c0-b7e8d30771fe",
"url": "/api/config/v1/jobs/c8c2909d-75e9-484a-94c0-b7e8d30771fe"
}jobId identifies the background job for internal tracking, but polling it directly isn't available in this release. To confirm the sync completed, check back after a short delay with GET /profiles/{profileId}/users?hasOverrides=false; the users you targeted should no longer appear in the overrides list once the force-sync has finished. The job records a per-user error against any user that does not have an associated profile, but those errors do not fail the job as a whole.
| Status | Condition |
|---|---|
202 | Accepted; body contains the jobId |
400 | Malformed request |
403 | The Profile Sync feature is not enabled for this account |
409 | A sync job is already pending or running for one of the targeted profiles |
Deleting a Profile
DELETE /profiles/{profileId} permanently removes a profile. There is no soft-delete and no undo.
curl -X DELETE 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6' \
-H 'Authorization: Bearer ACCESS_TOKEN'| Status | Body |
|---|---|
204 | Success, no body |
404 | Profile does not exist |
409 | The profile has users assigned to it (see below) |
You cannot delete a profile that has users assigned to it. Reassign or detach those users first.
The 409 response:
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#conflict",
"title": "Conflict",
"status": 409,
"detail": "Cannot delete profile that is assigned to users"
}Recipe: delete a profile cleanly
# 1. Find users on this profile
curl -X GET 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6/users' \
-H 'Authorization: Bearer ACCESS_TOKEN'
# 2. Move each user to a different profile (or detach)
curl -X PATCH 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/users/002d011003cf7c9d1b469ddc7e' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "profileId": "d5cfccf4-0507-49f8-98d9-34fdaeefca5d" }'
# 3. Delete the now-empty profile
curl -X DELETE 'https://core.{customerId}.ec.avayacloud.com/api/config/v1/profiles/16a7490f-86a6-4a14-8ce2-11682230adb6' \
-H 'Authorization: Bearer ACCESS_TOKEN'Errors and Conflicts
All error responses use the application/problem+json content type and follow RFC 7807:
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#constraint-violation",
"title": "Constraint Violation",
"status": 400,
"detail": "Request contains invalid or missing fields",
"violations": [
{ "field": "name", "message": "must not be null", "code": 20002 }
]
}Status codes used by these endpoints
| Status | Meaning |
|---|---|
400 Bad Request | Request is malformed or required fields are missing |
401 Unauthorized | Bearer token is missing, malformed, or expired |
403 Forbidden | The token lacks a required scope, or an agent self-edit hit a restriction, or a feature gate is closed |
404 Not Found | The targeted profile, user, folder, or location does not exist |
409 Conflict | A uniqueness or state invariant was violated; see the dedicated subsections below |
422 Unprocessable Entity | The request is syntactically correct but semantically invalid (violations[] enumerates the offending fields) |
429 Too Many Requests | Rate limit exceeded; see Retry-After header |
500 Internal Server Error | Unexpected server error; requestId in the body can be quoted to support |
Profile-side 409 conflicts
| Operation | Condition | detail |
|---|---|---|
POST /profiles | Profile name already exists in the account | Profile name already exists in this account |
PATCH /profiles/{id} | New name conflicts with another profile | Profile name already exists in this account |
PATCH /profiles/{id} | A sync job (PRFUPD or FSYNC) is already running for this profile | Profile cannot be updated while a sync job is in progress (jobId: ...). Please wait for it to complete. |
DELETE /profiles/{id} | The profile has users assigned to it | Cannot delete profile that is assigned to users |
User-side 409 conflicts
| Operation | Condition | detail |
|---|---|---|
POST /users | Email already in use by another user | A resource with the same unique constraint values already exists (with violations[].field = "email") |
POST /users:bulk-force-sync-profile | A sync job is already pending or running for one of the targeted profiles | Profile cannot be updated while a sync job is in progress (jobId: ...). Please wait for it to complete. |
Profile-user-limit 422
A profile supports at most 500 assigned users. Two operations enforce this limit:
| Operation | Condition | detail |
|---|---|---|
PATCH /profiles/{profileId} | Profile already has more than 500 users; updates are blocked until the count drops to 500 or below | Profile User limit of 500 reached. Cannot update profile |
POST /users or PATCH /users/USERID (with profileId) | Target profile is already at the 500-user cap | Profile User limit of 500 reached. Cannot add user to the profile |
Both responses carry violations[].code: 20005. Example:
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#validation-failed",
"title": "Validation Failed",
"status": 422,
"detail": "Profile User limit of 500 reached. Cannot add user to the profile",
"violations": [
{
"field": "profileId",
"message": "Profile User limit of 500 reached. Cannot add user to the profile",
"code": 20005
}
]
}Agent self-edit 403
Returned when an agent attempts to change one of the administrator-managed identity fields (firstName, lastName, namePrefix, nameSuffix, title, email, mobile) on their own user record:
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "You are not permitted to modify firstName, email. These fields are managed by your administrator."
}The detail lists the specific fields the request attempted to change.
Feature-not-enabled 403
Returned by POST /users/USERID:force-sync-profile and POST /users:bulk-force-sync-profile when the Profile Sync feature is not enabled for the account:
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Profile sync is not enabled for this account."
}Token expired 401
{
"type": "https://developers.avayacloud.com/avaya-infinity/docs/errors#unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Bearer token expired at 2026-05-15T10:15:00Z. Request a new token."
}Re-request a token using your client credentials (see Authentication) and retry the request.
Updated 5 days ago
