> This page is for version v1.
> For other versions, use one of these documentation indexes:
> - v2 (default): https://autodesk-poc.ferndocs.com/v2/llms.txt
> - v1: https://autodesk-poc.ferndocs.com/v1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://autodesk-poc.ferndocs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://autodesk-poc.ferndocs.com/_mcp/server.

# Get a user's roles

GET https://developer.api.autodesk.com/construction/admin/v1/accounts/{accountId}/users/{userId}/roles

Returns the roles assigned to a specific user across the projects they belong to.

Only users with hub admin permissions can call this endpoint. To verify a user's permissions, call [GET users](https://aps.autodesk.com/en/docs/acc/v1/reference/http/admin-projectsprojectId-users-GET/).

**Note:** This operation is forward compatible. Autodesk may add attributes to the response without prior notice, so your app should ignore any attribute it does not recognize.

Reference: https://autodesk-poc.ferndocs.com/v1/acc-admin/hub-users/get-user-roles

## Authentication

- OAuth2 — send the obtained token as `Authorization: Bearer <token>`
- OAuth2 — send the obtained token as `Authorization: Bearer <token>`
- `Authorization` header (bearer token, required) — **OAuth 2.0 (3-legged)** — user context required. Also accepts a Secure Service Account (SSA) token, which is headless like a two-legged flow but classified as three-legged because it preserves user context. **Authorization Code Flow** Authorization URL: [https://developer.api.autodesk.com/authentication/v2/authorize](https://developer.api.autodesk.com/authentication/v2/authorize) Token URL: [https://developer.api.autodesk.com/authentication/v2/token](https://developer.api.autodesk.com/authentication/v2/token) Refresh URL: [https://developer.api.autodesk.com/authentication/v2/token](https://developer.api.autodesk.com/authentication/v2/token) Scopes: - `data:read` — read your data - `account:read` — read account and project data - `account:write` — modify account and project data

## Request

### Path parameters

- `accountId` (string, required) — The ID of the hub that contains the projects. This corresponds to the hub ID used in the [Data Management API](https://aps.autodesk.com/en/docs/data/v2/), with the "**b.**\" prefix removed. For example, `b.c8b0c73d-3ae9` becomes `c8b0c73d-3ae9`.
- `userId` (string, required) — The ID of the user. To find the ID call [GET users](https://aps.autodesk.com/en/docs/acc/v1/reference/http/admin-projectsprojectId-users-GET/). You can use either the Forma ID (`id`) or the Autodesk ID (`autodeskId`).

### Query parameters

- `filter[projectId]` (list of string, optional) — A list of project IDs. Only results where the user is associated with one or more of the specified projects are returned.
- `filter[id]` (list of string, optional) — Filters roles by their unique ID. You can specify one or more role IDs.
- `filter[status]` (list of enum, optional) — Filters roles by their status. Accepts one or more of the following values: `active` – The role is currently in use. `inactive` – The role has been removed or is no longer in use.
  - Allowed values: `active`, `inactive`
- `filter[name]` (string, optional) — Filters roles by name. By default, this performs a partial match (case-insensitive). You can control how the match behaves by using the `filterTextMatch` parameter. For example, to match only names that start with (`startsWith`), end with (`endsWith`), or exactly equal (`equals`) the provided value.
- `filterTextMatch` (enum, optional, default: contains) — Specifies how text-based filters should match values in supported fields. This parameter can be used in any endpoint that supports text-based filtering (e.g., `filter[name]`, `filter[jobNumber]`, `filter[companyName]`, etc.). Possible values: `contains` (default) – Matches if the field contains the specified text anywhere `startsWith` – Matches if the field starts with the specified text `endsWith` – Matches if the field ends with the specified text `equals` – Matches only if the field exactly matches the specified text Matching is case-insensitive. Wildcards and regular expressions are not supported.
  - Allowed values: `contains`, `startsWith`, `endsWith`, `equals`
- `fields` (list of enum, optional) — A comma-separated list of response fields to include. Defaults to all fields if not specified. Use this parameter to reduce the response size by retrieving only the fields you need. Possible values: `projectIds` – Projects where the user holds this role `name` – Role name `status` – Role status (active or inactive) `key` – Internal key used to translate the role name `isImmutable` – Indicates whether the role is immutable `createdAt` – Timestamp when the role was created `updatedAt` – Timestamp when the role was last updated
  - Allowed values: `projectIds`, `name`, `status`, `key`, `createdAt`, `updatedAt`, `isImmutable`
- `sort` (list of enum, optional, default: name) — Sorts the results by one or more fields. Each field can be followed by a direction modifier: `asc` – Ascending order (default) `desc` – Descending order Possible values: `name`, `createdAt`, `updatedAt`. Default sort: `name asc` Example: `sort=name,updatedAt desc`
  - Allowed values: `name`, `name asc`, `name desc`, `createdAt`, `createdAt asc`, `createdAt desc`, `updatedAt`, `updatedAt asc`, `updatedAt desc`
- `limit` (integer, optional, default: 20) — The maximum number of records to return in the response. Default: `20` Minimum: `1` Maximum: `200` (If a larger value is provided, only 200 records are returned)
- `offset` (integer, optional, default: 0) — The index of the first record to return. Used for pagination in combination with the `limit` parameter. Example: `limit=20` and `offset=40` returns records 41–60.

### Headers

- `Accept-Language` (string, optional, default: en) — This header is not currently supported in the hub Admin API.
- `Region` (string, optional) — Specifies the region where your request should be routed. If not set, the request is routed automatically, which may result in a slight increase in latency. Possible values: `US`, `EMEA`. For a complete list of supported regions, see the [Regions](https://aps.autodesk.com/en/docs/acc/v1/overview/acc-regions/) page.
- `User-Id` (string, optional) — The ID of a user on whose behalf your request is acting. Your app has access to all users specified by the administrator in the SaaS integrations UI. Provide this header value to identify the user to be affected by the request. You can use either the user's Forma ID (`id`), or their Autodesk ID (`autodeskId`). Note that this header is required for hub Admin POST, PATCH, and DELETE endpoints if you want to use a 2-legged authentication context. This header is optional for hub Admin GET endpoints.

## Response

### 200

A list of requested roles associated with the user

- `pagination` (pagination, optional) — Contains pagination details for the records returned by the endpoint.
- `results` (list of userRoleResponse, optional) — The requested page of roles associated with the user.

## Errors

### 400 Bad Request Error

The request could not be understood by the server due to malformed syntax.

- `status` (integer, optional) — The status code for the error.
- `type` (string, optional) — HQ defined error code for the type of error.
- `title` (string, optional) — The title of the error. ex: Bad Request.
- `detail` (string, optional) — A detailed description of the error with possible suggestions for fixing them.
- `id` (string, optional) — A unique id for the request.
- `errors` (list of fieldError, optional) — List of field validation errors.

### 401 Unauthorized Error

Request has not been applied because it lacks valid authentication credentials for the target resource.

- `authenticationUrl` (string, optional) — The url used for authenticating the user.
- `status` (integer, optional) — The status code for the error.
- `type` (string, optional) — HQ defined error code for the type of error.
- `title` (string, optional) — The title of the error. ex: Bad Request.
- `detail` (string, optional) — A detailed description of the error with possible suggestions for fixing them.
- `id` (string, optional) — A unique id for the request.

### 403 Forbidden Error

The server understood the request but refuses to authorize it.

- `status` (integer, optional) — The status code for the error.
- `type` (string, optional) — HQ defined error code for the type of error.
- `title` (string, optional) — The title of the error. ex: Bad Request.
- `detail` (string, optional) — A detailed description of the error with possible suggestions for fixing them.
- `id` (string, optional) — A unique id for the request.

### 404 Not Found Error

The resource could not be found.

- `status` (integer, optional) — The status code for the error.
- `type` (string, optional) — HQ defined error code for the type of error.
- `title` (string, optional) — The title of the error. ex: Bad Request.
- `detail` (string, optional) — A detailed description of the error with possible suggestions for fixing them.
- `id` (string, optional) — A unique id for the request.

### 406 Not Acceptable Error

The server cannot produce a response matching the list of acceptable values defined in the request.

- `status` (integer, optional) — The status code for the error.
- `type` (string, optional) — HQ defined error code for the type of error.
- `title` (string, optional) — The title of the error. ex: Bad Request.
- `detail` (string, optional) — A detailed description of the error with possible suggestions for fixing them.
- `id` (string, optional) — A unique id for the request.

### 410 Gone Error

Access to the target resource is no longer available.

- `status` (integer, optional) — The status code for the error.
- `type` (string, optional) — HQ defined error code for the type of error.
- `title` (string, optional) — The title of the error. ex: Bad Request.
- `detail` (string, optional) — A detailed description of the error with possible suggestions for fixing them.
- `id` (string, optional) — A unique id for the request.

### 429 Too Many Requests Error

User has sent too many requests in a given amount of time.

- `any`

### 500 Internal Server Error

An unexpected error occurred on the server.

- `status` (integer, optional) — The status code for the error.
- `type` (string, optional) — HQ defined error code for the type of error.
- `title` (string, optional) — The title of the error. ex: Bad Request.
- `detail` (string, optional) — A detailed description of the error with possible suggestions for fixing them.
- `id` (string, optional) — A unique id for the request.

### 503 Service Unavailable Error

Server is not ready to handle the request.

- `status` (integer, optional) — The status code for the error.
- `type` (string, optional) — HQ defined error code for the type of error.
- `title` (string, optional) — The title of the error. ex: Bad Request.
- `detail` (string, optional) — A detailed description of the error with possible suggestions for fixing them.
- `id` (string, optional) — A unique id for the request.

## Types

### pagination

Contains pagination details for the records returned by the endpoint.

- `limit` (integer, optional, default: 20) — The maximum number of records returned per page. The last page may contain fewer records than the specified limit.
- `offset` (integer, optional, default: 0) — The index of the first record in the returned page. Used for pagination.
- `totalResults` (integer, optional) — The total number of records matching the request.
- `nextUrl` (string, optional) — The URL for the next page of records, if more results are available. Max length: 2000 characters.
- `previousUrl` (string, optional) — The URL for the previous page of records, if applicable. Max length: 2000 characters.

### userRoleResponse

Information about the role associated with the user.

- `id` (string, optional) — The unique ID of the role.
- `status` (enum, optional) — The role status. Possible values: active, inactive.
  - Allowed values: `active`, `inactive`
- `name` (string, optional) — The name of the role. Predefined roles are localized based on the request language.
- `key` (string, optional) — The internal key used for translating predefined role names.
- `createdAt` (datetime, optional) — The timestamp when the role was created.
- `updatedAt` (datetime, optional) — The timestamp when the role was last updated.
- `isImmutable` (boolean, optional) — Indicates whether the role is immutable. If true, the role cannot be modified or deleted.
- `projectIds` (list of string, optional) — The list of projects where the user is associated with this role.

### fieldError

Error description for a field validation error.

- `type` (string, optional) — HQ defined error code for the type of error.
- `field` (string, optional) — Name of the field associated to the error.
- `title` (string, optional) — Title for the error.
- `detail` (string, optional) — A detailed description of the error so the user knows how to fix it.

## Examples

**Response**

```json
{
  "pagination": {
    "limit": 20,
    "offset": 10,
    "totalResults": 121,
    "nextUrl": "https://resource?limit=20&offset=30",
    "previousUrl": "https://resource?limit=20&offset=0"
  },
  "results": [
    {
      "id": "287d5cc2-9008-462c-96e5-c9491db85d97",
      "status": "active",
      "name": "Architect",
      "key": "architect",
      "createdAt": "2018-01-01T12:45:00.000Z",
      "updatedAt": "2019-01-01T12:45:00.000Z",
      "isImmutable": false,
      "projectIds": [
        "3e354e66-ac8b-41dd-9bc1-93fc182c25dd"
      ]
    }
  ]
}
```

**SDK Code**

```python
import requests

url = "https://developer.api.autodesk.com/construction/admin/v1/accounts/d73fc742-4538-401c-8d0f-853b49b750b2/users/6cc15635-2fbd-4f73-afbe-abd833408a1d/roles"

querystring = {"fields":"name","filterTextMatch":"contains","filter[id]":"287d5cc2-9008-462c-96e5-c9491db85d97","filter[name]":"filter[name]","filter[projectId]":"39712a51-bd64-446a-9c72-48c4e43d0a0d,d1163421-e7eb-4862-ac15-b33777ba42de","filter[status]":"active","limit":"20","offset":"0","sort":"name"}

headers = {
    "Accept-Language": "en",
    "Region": "US",
    "User-Id": "6cc15635-2fbd-4f73-afbe-abd833408a1d",
    "Authorization": "<token>."
}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript
const url = 'https://developer.api.autodesk.com/construction/admin/v1/accounts/d73fc742-4538-401c-8d0f-853b49b750b2/users/6cc15635-2fbd-4f73-afbe-abd833408a1d/roles?fields=name&filterTextMatch=contains&filter%5Bid%5D=287d5cc2-9008-462c-96e5-c9491db85d97&filter%5Bname%5D=filter%5Bname%5D&filter%5BprojectId%5D=39712a51-bd64-446a-9c72-48c4e43d0a0d%2Cd1163421-e7eb-4862-ac15-b33777ba42de&filter%5Bstatus%5D=active&limit=20&offset=0&sort=name';
const options = {
  method: 'GET',
  headers: {
    'Accept-Language': 'en',
    Region: 'US',
    'User-Id': '6cc15635-2fbd-4f73-afbe-abd833408a1d',
    Authorization: '<token>.'
  }
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://developer.api.autodesk.com/construction/admin/v1/accounts/d73fc742-4538-401c-8d0f-853b49b750b2/users/6cc15635-2fbd-4f73-afbe-abd833408a1d/roles?fields=name&filterTextMatch=contains&filter%5Bid%5D=287d5cc2-9008-462c-96e5-c9491db85d97&filter%5Bname%5D=filter%5Bname%5D&filter%5BprojectId%5D=39712a51-bd64-446a-9c72-48c4e43d0a0d%2Cd1163421-e7eb-4862-ac15-b33777ba42de&filter%5Bstatus%5D=active&limit=20&offset=0&sort=name"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Accept-Language", "en")
	req.Header.Add("Region", "US")
	req.Header.Add("User-Id", "6cc15635-2fbd-4f73-afbe-abd833408a1d")
	req.Header.Add("Authorization", "<token>.")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://developer.api.autodesk.com/construction/admin/v1/accounts/d73fc742-4538-401c-8d0f-853b49b750b2/users/6cc15635-2fbd-4f73-afbe-abd833408a1d/roles?fields=name&filterTextMatch=contains&filter%5Bid%5D=287d5cc2-9008-462c-96e5-c9491db85d97&filter%5Bname%5D=filter%5Bname%5D&filter%5BprojectId%5D=39712a51-bd64-446a-9c72-48c4e43d0a0d%2Cd1163421-e7eb-4862-ac15-b33777ba42de&filter%5Bstatus%5D=active&limit=20&offset=0&sort=name")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Accept-Language"] = 'en'
request["Region"] = 'US'
request["User-Id"] = '6cc15635-2fbd-4f73-afbe-abd833408a1d'
request["Authorization"] = '<token>.'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://developer.api.autodesk.com/construction/admin/v1/accounts/d73fc742-4538-401c-8d0f-853b49b750b2/users/6cc15635-2fbd-4f73-afbe-abd833408a1d/roles?fields=name&filterTextMatch=contains&filter%5Bid%5D=287d5cc2-9008-462c-96e5-c9491db85d97&filter%5Bname%5D=filter%5Bname%5D&filter%5BprojectId%5D=39712a51-bd64-446a-9c72-48c4e43d0a0d%2Cd1163421-e7eb-4862-ac15-b33777ba42de&filter%5Bstatus%5D=active&limit=20&offset=0&sort=name")
  .header("Accept-Language", "en")
  .header("Region", "US")
  .header("User-Id", "6cc15635-2fbd-4f73-afbe-abd833408a1d")
  .header("Authorization", "<token>.")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://developer.api.autodesk.com/construction/admin/v1/accounts/d73fc742-4538-401c-8d0f-853b49b750b2/users/6cc15635-2fbd-4f73-afbe-abd833408a1d/roles?fields=name&filterTextMatch=contains&filter%5Bid%5D=287d5cc2-9008-462c-96e5-c9491db85d97&filter%5Bname%5D=filter%5Bname%5D&filter%5BprojectId%5D=39712a51-bd64-446a-9c72-48c4e43d0a0d%2Cd1163421-e7eb-4862-ac15-b33777ba42de&filter%5Bstatus%5D=active&limit=20&offset=0&sort=name', [
  'headers' => [
    'Accept-Language' => 'en',
    'Authorization' => '<token>.',
    'Region' => 'US',
    'User-Id' => '6cc15635-2fbd-4f73-afbe-abd833408a1d',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://developer.api.autodesk.com/construction/admin/v1/accounts/d73fc742-4538-401c-8d0f-853b49b750b2/users/6cc15635-2fbd-4f73-afbe-abd833408a1d/roles?fields=name&filterTextMatch=contains&filter%5Bid%5D=287d5cc2-9008-462c-96e5-c9491db85d97&filter%5Bname%5D=filter%5Bname%5D&filter%5BprojectId%5D=39712a51-bd64-446a-9c72-48c4e43d0a0d%2Cd1163421-e7eb-4862-ac15-b33777ba42de&filter%5Bstatus%5D=active&limit=20&offset=0&sort=name");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept-Language", "en");
request.AddHeader("Region", "US");
request.AddHeader("User-Id", "6cc15635-2fbd-4f73-afbe-abd833408a1d");
request.AddHeader("Authorization", "<token>.");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Accept-Language": "en",
  "Region": "US",
  "User-Id": "6cc15635-2fbd-4f73-afbe-abd833408a1d",
  "Authorization": "<token>."
]

let request = NSMutableURLRequest(url: NSURL(string: "https://developer.api.autodesk.com/construction/admin/v1/accounts/d73fc742-4538-401c-8d0f-853b49b750b2/users/6cc15635-2fbd-4f73-afbe-abd833408a1d/roles?fields=name&filterTextMatch=contains&filter%5Bid%5D=287d5cc2-9008-462c-96e5-c9491db85d97&filter%5Bname%5D=filter%5Bname%5D&filter%5BprojectId%5D=39712a51-bd64-446a-9c72-48c4e43d0a0d%2Cd1163421-e7eb-4862-ac15-b33777ba42de&filter%5Bstatus%5D=active&limit=20&offset=0&sort=name")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```