Summary and recommendation
The Workfront REST API exposes full user lifecycle operations - create, read, update, deactivate, delete, and batch - under a versioned base URL (`/attask/api/v{version}`).
Authentication supports two paths: legacy session-based auth via `POST /login` returning a `sessionID`, and the recommended Adobe IMS OAuth 2.0 Server-to-Server flow using credentials registered in the Adobe Developer Console.
For any new integration, use OAuth 2.0;
the `sessionID` approach is legacy and Adobe's post-acquisition direction is firmly toward IMS.
The API does not expose a SCIM 2.0 endpoint.
Okta and Microsoft Entra ID connectors for Workfront call the Workfront REST API internally rather than a SCIM interface, which means identity graph synchronization must be handled explicitly
field mappings, access level GUIDs, and group GUIDs must all be resolved and maintained by the integration layer, not delegated to a standards-based protocol.
This places the burden of schema translation and lifecycle state management squarely on the consuming system.
API quick reference
| Has user API | Yes |
| Auth method | API Key (sessionID) or OAuth 2.0 (Adobe IMS) |
| Base URL | Official docs |
| SCIM available | No |
| SCIM plan required | Enterprise |
Authentication
Auth method: API Key (sessionID) or OAuth 2.0 (Adobe IMS)
Setup steps
- Option A – API Key: POST to /attask/api/v{version}/login with username and password to receive a sessionID; include sessionID as a query parameter or header on subsequent requests.
- Option B – OAuth 2.0 via Adobe IMS: Register an integration in the Adobe Developer Console, obtain a client_id and client_secret, request an access token from Adobe IMS (https://ims-na1.adobelogin.com/ims/token/v3), then pass the Bearer token in the Authorization header.
- For server-to-server integrations, use the OAuth Server-to-Server credential type in Adobe Developer Console (replaces deprecated Service Account/JWT).
- Ensure the Workfront integration in Adobe Developer Console has the correct product profile assigned to grant API access.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| openid | Required base scope for Adobe IMS OAuth flows. | Authentication via Adobe IMS |
| workfront.full_access | Full access to Workfront API resources on behalf of the authenticated user or service account. | All Workfront API operations including user management |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| ID | string | Workfront-generated unique identifier (GUID). | auto-generated | immutable | Used as the primary key in all API references. |
| username | string | Login username; must be unique within the instance. | required | optional | Typically matches email for SSO environments. |
| emailAddr | string | Primary email address of the user. | required | optional | Used for notifications and SSO matching. |
| firstName | string | User's first name. | required | optional | |
| lastName | string | User's last name. | required | optional | |
| title | string | Job title. | optional | optional | |
| accessLevelID | string (GUID) | Reference to the Access Level object controlling permissions. | required | optional | Must be a valid Access Level ID from the instance. |
| homeGroupID | string (GUID) | Primary group (Home Group) for the user. | optional | optional | |
| companyID | string (GUID) | Associated company object. | optional | optional | |
| isActive | boolean | Whether the user account is active. | optional (defaults true) | optional | Set to false to deactivate without deleting. |
| password | string | Password for non-SSO accounts. | required if not SSO | optional | Not returned in GET responses. |
| phoneNumber | string | Primary phone number. | optional | optional | |
| mobilePhoneNumber | string | Mobile phone number. | optional | optional | |
| timeZone | string | User's time zone (e.g., America/New_York). | optional | optional | |
| locale | string | UI locale/language preference. | optional | optional | |
| costPerHour | double | User's billing/cost rate per hour. | optional | optional | Requires financial data access level. |
| scheduleID | string (GUID) | Work schedule assigned to the user. | optional | optional | |
| roleID | string (GUID) | Primary job role. | optional | optional | Use roles endpoint to list valid IDs. |
| ssoUsername | string | SSO-mapped username used for SAML authentication. | optional | optional | Required when SSO is enabled and username differs from SSO identity. |
| lastLoginDate | datetime | Timestamp of last login. | auto | auto | Read-only; set by the system. |
Core endpoints
List Users
- Method: GET
- URL:
https://{domain}.my.workfront.com/attask/api/v{version}/user/search - Watch out for: Only fields listed in the 'fields' parameter are returned; omitting 'fields' returns a minimal default set. Use 'fields=*' cautiously as it increases payload size significantly.
Request example
GET /attask/api/v18.0/user/search?$$LIMIT=100&$$FIRST=0&fields=ID,username,emailAddr,firstName,lastName,isActive
Authorization: Bearer {access_token}
Response example
{
"data": [
{"ID":"abc123","username":"jdoe","emailAddr":"jdoe@example.com","firstName":"Jane","lastName":"Doe","isActive":true}
]
}
Get User by ID
- Method: GET
- URL:
https://{domain}.my.workfront.com/attask/api/v{version}/user/{userID} - Watch out for: Returns 404 if the user ID does not exist or the API caller lacks permission to view that user.
Request example
GET /attask/api/v18.0/user/abc123?fields=ID,username,emailAddr,accessLevelID,isActive
Authorization: Bearer {access_token}
Response example
{
"data": {
"ID":"abc123",
"username":"jdoe",
"emailAddr":"jdoe@example.com",
"isActive":true
}
}
Create User
- Method: POST
- URL:
https://{domain}.my.workfront.com/attask/api/v{version}/user - Watch out for: accessLevelID is required; creating a user without a valid Access Level ID returns a validation error. For SSO environments, set ssoUsername to match the IdP identity.
Request example
POST /attask/api/v18.0/user
Authorization: Bearer {access_token}
Content-Type: application/json
{"username":"jsmith","emailAddr":"jsmith@example.com","firstName":"John","lastName":"Smith","accessLevelID":"lvl456","password":"Temp@1234"}
Response example
{
"data": {
"ID":"newuser789",
"username":"jsmith",
"emailAddr":"jsmith@example.com",
"isActive":true
}
}
Update User
- Method: PUT
- URL:
https://{domain}.my.workfront.com/attask/api/v{version}/user/{userID} - Watch out for: Workfront uses PUT for updates (not PATCH). Only fields included in the body are updated; omitted fields retain their current values.
Request example
PUT /attask/api/v18.0/user/abc123
Authorization: Bearer {access_token}
Content-Type: application/json
{"title":"Senior Manager","homeGroupID":"grp001"}
Response example
{
"data": {
"ID":"abc123",
"title":"Senior Manager",
"homeGroupID":"grp001"
}
}
Deactivate User
- Method: PUT
- URL:
https://{domain}.my.workfront.com/attask/api/v{version}/user/{userID} - Watch out for: Workfront recommends deactivating rather than deleting users to preserve historical data integrity. Deleted users cannot be restored.
Request example
PUT /attask/api/v18.0/user/abc123
Authorization: Bearer {access_token}
Content-Type: application/json
{"isActive":false}
Response example
{
"data": {
"ID":"abc123",
"isActive":false
}
}
Delete User
- Method: DELETE
- URL:
https://{domain}.my.workfront.com/attask/api/v{version}/user/{userID} - Watch out for: Deletion is permanent and removes the user from all historical records. Workfront strongly recommends deactivation instead.
Request example
DELETE /attask/api/v18.0/user/abc123
Authorization: Bearer {access_token}
Response example
{
"data": {
"success": true
}
}
Batch Operations
- Method: POST
- URL:
https://{domain}.my.workfront.com/attask/api/v{version}/batch - Watch out for: Batch endpoint reduces API call volume. Maximum number of operations per batch request is not explicitly documented; test conservatively.
Request example
POST /attask/api/v18.0/batch
Authorization: Bearer {access_token}
Content-Type: application/json
{"updates":[{"method":"PUT","uri":"/user/abc123","body":{"isActive":false}},{"method":"PUT","uri":"/user/def456","body":{"isActive":false}}]}
Response example
{
"data": [
{"ID":"abc123","isActive":false},
{"ID":"def456","isActive":false}
]
}
Search Users by Filter
- Method: GET
- URL:
https://{domain}.my.workfront.com/attask/api/v{version}/user/search - Watch out for: Filter parameters are passed as query string key=value pairs matching field names. Wildcard searches use the _Mod suffix (e.g., emailAddr_Mod=contains&emailAddr=example.com).
Request example
GET /attask/api/v18.0/user/search?emailAddr=jdoe@example.com&fields=ID,username,isActive
Authorization: Bearer {access_token}
Response example
{
"data": [
{"ID":"abc123","username":"jdoe","isActive":true}
]
}
Rate limits, pagination, and events
Rate limits: Adobe Workfront does not publicly document specific numeric rate limits in its official API documentation. Throttling behavior exists but thresholds are not published.
Rate-limit headers: No
Retry-After header: No
Rate-limit notes: Official docs do not specify rate-limit headers or Retry-After behavior. Adobe support recommends implementing exponential backoff. Bulk operations should use the batch endpoint to reduce request volume.
Pagination method: offset
Default page size: 100
Max page size: 2000
Pagination pointer: $$FIRST and $$LIMIT (e.g., $$FIRST=0&$$LIMIT=100)
Webhooks available: Yes
Webhook notes: Workfront supports Event Subscriptions (webhooks) that send HTTP POST payloads to a configured endpoint when object state changes occur. Subscriptions are managed via the /attask/eventsubscription/api/v1/subscriptions endpoint.
Alternative event strategy: For polling-based approaches, use the /user/search endpoint with date filters on lastUpdateDate to detect changes.
Webhook events: USER_CREATE, USER_UPDATE, USER_DELETE
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: Enterprise
- Endpoint: Not documented
Limitations:
- Workfront does not expose a native SCIM 2.0 endpoint. Auto-provisioning is available via SAML 2.0 SSO (JIT provisioning) with supported IdPs such as Okta and Microsoft Entra ID.
- Okta and Entra ID connectors for Workfront use the Workfront REST API internally, not a SCIM interface.
- SSO prerequisite is required for auto-provisioning; SAML 2.0 must be configured before enabling JIT user creation.
Common scenarios
Three scenarios cover the majority of programmatic user lifecycle needs:
Bulk deactivate departed employees: Query
GET /user/searchwith relevant filters, collect user IDs, then submit batchedPUT /user/{ID}calls with{"isActive":false}viaPOST /batch. Process in chunks of 50 or fewer - batch size limits are undocumented and oversized requests risk timeouts. Deactivation does not immediately revoke active sessions.Provision a new user with access level and group: Dynamically resolve
accessLevelIDviaGET /accesslevel/searchandhomeGroupIDviaGET /group/searchbefore posting toPOST /user. These GUIDs are instance-specific and must never be hardcoded across dev and production environments. For SSO environments, setssoUsernameto match the IdP identity exactly; a mismatch causes login failure.Subscribe to user change events: Register an Event Subscription via
POST /attask/eventsubscription/api/v1/subscriptionsforUSERobject withCREATE,UPDATE, andDELETEevent types. Payloads includenewStateandoldStatesnapshots, enabling field-level change detection (e.g.,isActivetransitions). The receiving endpoint must be HTTPS with a valid SSL certificate; Workfront's retry policy on failed deliveries is not fully documented publicly.
Bulk Deactivate Departed Employees
- Retrieve the list of users to deactivate by calling GET /user/search with appropriate filters (e.g., by homeGroupID or a custom field).
- Collect the IDs of users to deactivate.
- Use the POST /batch endpoint to send multiple PUT /user/{ID} requests with {"isActive":false} in a single API call.
- Verify deactivation by re-querying GET /user/{ID}?fields=isActive for a sample of affected users.
Watch out for: Batch request size limits are undocumented; process in chunks of 50 or fewer to avoid timeouts. Deactivation does not revoke active sessions immediately.
Provision New User via API with Access Level and Group
- Retrieve the target Access Level ID: GET /attask/api/v18.0/accesslevel/search?fields=ID,name
- Retrieve the target Home Group ID: GET /attask/api/v18.0/group/search?fields=ID,name
- POST to /user with required fields: username, emailAddr, firstName, lastName, accessLevelID, homeGroupID, and password (or ssoUsername for SSO environments).
- Capture the returned user ID for downstream system mapping.
- Optionally assign a job role: PUT /user/{ID} with {"roleID":"{roleGUID}"}.
Watch out for: Access Level IDs and Group IDs are instance-specific GUIDs. Hardcoding them across environments (dev/prod) will cause failures; always look them up dynamically.
Subscribe to User Change Events via Event Subscriptions
- Ensure your receiving endpoint is HTTPS with a valid SSL certificate.
- POST to /attask/eventsubscription/api/v1/subscriptions with body: {"objCode":"USER","eventType":"UPDATE","url":"https://your-endpoint.example.com/hook","authToken":"your-secret"}
- Repeat for CREATE and DELETE eventTypes as needed.
- Validate incoming payloads using the authToken header Workfront sends with each event.
- Parse the newState and oldState objects in the payload to detect field-level changes (e.g., isActive transition).
Watch out for: Event Subscription payloads include newState and oldState snapshots of the object. The authToken in the subscription is sent as a header on outbound requests for receiver validation, not as OAuth. Subscription management (list, delete) also uses the /eventsubscription API.
Why building this yourself is a trap
The most consequential API caveat is the absence of a native SCIM endpoint. Any integration that assumes SCIM-compatible behavior - standardized schemas, /Users endpoints, automatic attribute mapping - will fail.
Building against the Workfront REST API for identity graph synchronization requires explicit handling of Workfront's object reference model: accessLevelID, homeGroupID, roleID, and companyID are all instance-specific GUIDs with no cross-instance portability.
Two additional traps are worth flagging explicitly. First, the API uses PUT for updates, not PATCH - while partial updates are supported by including only changed fields, the HTTP method is PUT, which can cause issues with integration frameworks that infer full-replacement semantics from PUT.
Second, rate limits exist but numeric thresholds are not publicly documented, and neither rate-limit headers nor a Retry-After header are returned; integrations must implement exponential backoff proactively rather than reactively. Adobe recommends the batch endpoint to reduce request volume, but maximum operations per batch request are also undocumented - test conservatively before scaling.
Automate Workfront workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.