> This page is for version v2 (default).
> 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.

# Import project users

POST https://developer.api.autodesk.com/construction/admin/v2/projects/{projectId}/users:import
Content-Type: application/json

Adds multiple users to a project at once. Can add up to 200 users per request.

Note that the `Authorization` header token can be obtained either via a [three-legged](https://aps.autodesk.com/en/docs/oauth/v2/tutorials/get-3-legged-token/) OAuth flow, or via a [two-legged](https://aps.autodesk.com/en/docs/oauth/v2/tutorials/get-2-legged-token/) Oauth flow *with user impersonation*, for which the `User-Id` header is required.

**Note:** This operation is not backward compatible with BIM 360 projects. It only works with Autodesk Construction Cloud projects.

Reference: https://autodesk-poc.ferndocs.com/acc-admin/project-users/import-project-users

## 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

- `projectId` (string, required) — The ID of the project. This corresponds to project ID in the [Data Management API](https://aps.autodesk.com/en/docs/data/v2/). To convert a project ID in the Data Management API into a project ID in the Forma API you need to remove the "**b.**\" prefix. For example, a project ID of `b.a4be0c34a-4ab7` translates to a project ID of `a4be0c34a-4ab7`.

### Headers

- `Accept-Language` (string, optional, default: en) — This header is not currently supported in the Hub Admin API.
- `Region` (string, optional) — The region that the data is stored in. For a full list of supported regions, please check [here](https://aps.autodesk.com/en/docs/acc/v1/overview/acc-regions/).
- `User-Id` (string, optional) — Note that this header is not relevant for Hub Admin GET endpoints. The ID of a user on whose behalf your API request is acting. Required if you're using a 2-legged authentication context, which must be *2-legged OAuth2 security with user impersonation*. 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`).

### Body (application/json)

This endpoint expects an object.

- `users` (list of ProjectsProjectIdUsersImportPostRequestBodyContentApplicationJsonSchemaUsersItems, optional) — User data to import.
- `suppressAutodeskEmails` (boolean, optional, default: false) — Suppresses all emails from Autodesk to the invited users. Defaults to false.
- `suppressAdministrativeEmails` (boolean, optional, default: false) — Controls whether project invitation emails are sent to the invited users. `true`: prevents project invitation emails from being sent to users. `false`: (default) send project invitation emails to the invited users.

## Response

### 202

The request has been received but not yet acted upon.

- `jobId` (string, optional) — We don't currently support this field, but expect to in a future release. If the response returns `jobId` with a valid UUID value, the user import operation was successful.

## 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 cannot 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.

### 409 Conflict Error

The request could not be completed due to a conflict with the current state of the resource.

- `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.

### 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.

### 412 Precondition Failed Error

The server refuses to accept the request because a pre-condition failed.

- `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.

### 415 Unsupported Media Type Error

The server refuses to accept the request because the payload format is in an unsupported format.

- `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

### ProjectsProjectIdUsersImportPostRequestBodyContentApplicationJsonSchemaUsersItems

- `email` (string, required) — The email of the user.
- `firstName` (string, optional) — The first name of the user.
- `lastName` (string, optional) — The last name of the user.
- `userId` (string, optional) — Not relevant
- `companyId` (string, optional, nullable) — The ID of the company that the user is representing in the project. To obtain a list of all company IDs associated with a project, call [GET projects/:projectId/companies](https://aps.autodesk.com/en/docs/acc/v1/reference/http/projects-:project_id-companies-GET/).
- `companyName` (string, optional, nullable) — The name of the user's company.
- `roleIds` (list of string, optional) — A list of the IDs of the user's roles in the project. To obtain role IDs for this parameter, you can call [GET projects/:projectId/users](https://aps.autodesk.com/en/docs/acc/v1/reference/http/admin-projects-projectId-users-GET/) endpoint or [GET projects/:projectId/users/:userId](https://aps.autodesk.com/en/docs/acc/v1/reference/http/admin-projects-projectId-users-userId-GET/) and inspect the `roleId` field in the response.
- `products` (list of ProjectUserProductsResponseItems, optional) — Information about the products activated in the project and the user's access level for each product. Do not include this field if the requester has Member Manager access level. If it is included, the request will be rejected.

### 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.

### ProjectUserProductsResponseItems

- `key` (string, required) — A keyword that identifies the product. Possible values: `autoSpecs`, `build`, `cost`, `designCollaboration`, `docs`, `insight`, `modelCoordination`, `projectAdministration`, and `takeoff`.
- `access` (enum, required) — The user's type of access to the product identified by `key`. Possible values: - `administrator` - `member` - `none` Note that when you're using a POST or PATCH endpoint to set this value, you must adhere to the following guidelines: - If you set a product's `key` to `projectAdministration` and you set `access` to `none`, all other products should be set to `member` access for the user. - If you set a product's `key` to `projectAdministration` and you set `access` to `administrator`, all other products should be set to `administrator` access for the user. - You cannot set a product's `key` to `projectAdministration` and set `access` to `member`.
  - Allowed values: `administrator`, `member`, `none`

## Examples

**Request**

```json
{}
```

**Response**

```json
{
  "jobId": "fa976214-f1fb-4795-a152-04ad20fa7310"
}
```

**SDK Code**

```python
import requests

url = "https://developer.api.autodesk.com/construction/admin/v2/projects/367d5cc2-9008-462c-96e5-c9491db85d93/users:import"

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

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://developer.api.autodesk.com/construction/admin/v2/projects/367d5cc2-9008-462c-96e5-c9491db85d93/users:import';
const options = {
  method: 'POST',
  headers: {
    'Accept-Language': 'en',
    Region: 'US',
    'User-Id': '6cc15635-2fbd-4f73-afbe-abd833408a1d',
    Authorization: '<token>.',
    'Content-Type': 'application/json'
  },
  body: '{}'
};

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"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://developer.api.autodesk.com/construction/admin/v2/projects/367d5cc2-9008-462c-96e5-c9491db85d93/users:import"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("POST", url, payload)

	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>.")
	req.Header.Add("Content-Type", "application/json")

	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/v2/projects/367d5cc2-9008-462c-96e5-c9491db85d93/users:import")

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

request = Net::HTTP::Post.new(url)
request["Accept-Language"] = 'en'
request["Region"] = 'US'
request["User-Id"] = '6cc15635-2fbd-4f73-afbe-abd833408a1d'
request["Authorization"] = '<token>.'
request["Content-Type"] = 'application/json'
request.body = "{}"

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.post("https://developer.api.autodesk.com/construction/admin/v2/projects/367d5cc2-9008-462c-96e5-c9491db85d93/users:import")
  .header("Accept-Language", "en")
  .header("Region", "US")
  .header("User-Id", "6cc15635-2fbd-4f73-afbe-abd833408a1d")
  .header("Authorization", "<token>.")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

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

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://developer.api.autodesk.com/construction/admin/v2/projects/367d5cc2-9008-462c-96e5-c9491db85d93/users:import', [
  'body' => '{}',
  'headers' => [
    'Accept-Language' => 'en',
    'Authorization' => '<token>.',
    'Content-Type' => 'application/json',
    '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/v2/projects/367d5cc2-9008-462c-96e5-c9491db85d93/users:import");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept-Language", "en");
request.AddHeader("Region", "US");
request.AddHeader("User-Id", "6cc15635-2fbd-4f73-afbe-abd833408a1d");
request.AddHeader("Authorization", "<token>.");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Accept-Language": "en",
  "Region": "US",
  "User-Id": "6cc15635-2fbd-4f73-afbe-abd833408a1d",
  "Authorization": "<token>.",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://developer.api.autodesk.com/construction/admin/v2/projects/367d5cc2-9008-462c-96e5-c9491db85d93/users:import")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

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()
```