Skip to main content

Bulk import

A bulk import creates or updates many users from one CSV file. It works in two steps, and nothing in Active Directory changes before the second one:

  1. Upload and preview. Vertex reads the file, checks every row against the directory and shows what each row would do: create, update or invalid (with the reasons).
  2. Commit. You confirm with a step-up; Vertex applies the valid rows and skips the invalid ones. A result file lists the outcome of every row.

Imports need the Tenant admin role and the users write switch.

The web interface is in development

The API calls are given in brackets (Vertex API).

The file​

  • Encoding: UTF-8. A byte-order mark (BOM, as Excel writes it) is fine.
  • Delimiter: ; or ,, detected from the header line (whichever occurs more often there). Values that contain the delimiter, quotes or line breaks are quoted with ", as usual in CSV.
  • Header row: required, the first line. Column names are case-insensitive; their order does not matter.
  • Rows: at most 10,000 users per file (the request is at most 5 MB). Empty lines are skipped. Line numbers count the header as line 1.
  • Values are trimmed, except passwords, which keep their spaces.

The template (GET …/imports/template) shows the common columns:

sAMAccountName;password;givenName;sn;displayName;ou;mail;department;title;groups;enabled;mustChangePassword
ipetrov;Change-Me-2026!;Ivan;Petrov;Ivan Petrov;OU=Students,OU=School,DC=school,DC=local;[email protected];10A;Student;Students;true;true

Columns​

ColumnAliasesMeaning
sAMAccountNamesam, username, login, logonThe logon name. Required. It identifies the user: rows are matched to existing users by it. At most 20 characters, none of " / \ [ ] : ; | = , + * ? < > @.
passwordThe password. Optional; see Defaults. At most 256 characters.
oupathThe DN of the OU for a new user, or to move an existing user to. Must be a managed OU or below one.
namecnThe CN of a new user (at most 64 characters). Not used for existing users.
givenNamefirstNameFirst name.
snsurname, lastNameLast name.
displayNameDisplay name.
userPrincipalNameupnUPN (name@suffix).
enabledtrue/false (see below).
mustChangePasswordchangePasswordAtLogonMust change the password at next logon: true/false.
groupsmemberOfGroups to add the user to, separated by ; (see Groups).
emailWritten to mail.
common attributesThese may be used by their LDAP names: mail, description, department, title, company, telephoneNumber, mobile, homePhone, ipPhone, physicalDeliveryOfficeName, employeeID, employeeNumber, employeeType, initials, streetAddress, l, st, postalCode, co, c, manager, info, wWWHomePage, homeDirectory, homeDrive, profilePath.
attr:<ldapName>Any other attribute by its LDAP display name, for example attr:extensionAttribute1 or attr:employeeType. Binary values as b64:<base64>. Attributes on the deny list are refused.
  • A column name Vertex does not know stops the upload (unknown_columns; use attr:<ldapName> for other attributes); so do a column that appears twice (duplicate_column), a missing sAMAccountName column (missing_column) and a denied attr: column (invalid_column).
  • Each attribute column gives one value. An empty cell leaves the attribute as it is.
  • Booleans (enabled, mustChangePassword): true, yes, y, 1, on, да or false, no, n, 0, off, не (any case); an empty cell means "not given".

Groups​

The groups cell lists groups separated by ;. Each group may be given by its DN, its name or its logon name (case-insensitive). Only groups below the managed OUs that are not protected can be used; any other name makes the row invalid (unknown group …). At most 100 groups per row.

When the file itself is separated by ;, a cell with several groups must be quoted:

sAMAccountName;givenName;sn;groups
mivanova;Maria;Ivanova;"Students;Class 10A"

Groups are only added: an import never removes a user from a group.

Modes​

ModeA new logon nameAn existing logon name
createCreatedInvalid (a user with this logon name exists)
updateInvalid (no user with this logon name)Updated
upsertCreatedUpdated

An existing user that is outside the managed OUs or protected makes its row invalid in every mode.

Defaults​

Options of the import fill in what the file leaves out:

OptionApplies toDefault
Default OU (default_ou)New users without ouThe settings' default user OU. Without either, the row is invalid.
UPN suffix (upn_suffix)New users without userPrincipalNameThe settings' UPN suffix: <logon name>@<suffix>.
Enabled (enabled)New users without an enabled valueEnabled when a password is given, else disabled. With the option set, a user is enabled only if the option is on and the row has a password.
Must change password (must_change_password)New users without the columnYes.

For a new user, the name (CN) is name, else "first name last name", else the logon name. An enabled value of true without a password makes the row invalid (an enabled new user needs a password).

Updating an existing user:

  • attributes, UPN, first, last and display name are written only where they differ from the directory (a row with no difference ends as unchanged);
  • a password resets the password;
  • mustChangePassword and enabled are applied when given;
  • an ou different from the user's moves the user there;
  • groups adds the user to groups it is not in yet;
  • name is ignored (existing users are not renamed).

Preview​

Upload the file (POST …/imports with csv, filename, mode and options). The answer is the validated import with its counters: total, invalid, to_create and to_update. Its rows (GET …/imports/{importID}/rows, filterable by action and status) show each row as parsed, without the password (has_password says whether one was given), its action and its problems, for example:

  • sAMAccountName is invalid, the same sAMAccountName as line 7;
  • ou … is outside the managed OUs, no ou (and no default OU);
  • userPrincipalName is invalid, name is invalid, password is too long;
  • unknown group Teachers;
  • attribute "info" value too long;
  • 4 values for 3 columns.

The preview is checked against Vertex's mirror; run a sync first if the directory changed outside Vertex. The upload is recorded in the audit log (directory.import.create).

Nothing has been written yet. Fix the file and upload it again, or cancel the import (POST …/imports/{importID}/cancel), which discards it and its passwords.

Commit​

Commit (POST …/imports/{importID}/commit with a step_up_token) applies the valid rows; invalid rows are marked skipped. An import can be committed once, and only within 24 hours of the upload (import_not_validated otherwise).

  • The rows are sent to the connector in batches of up to 200 users (bulk.users operations), which run one after another. Each batch may run for up to an hour.
  • A committed import is one confirmed action: it does not count against the per-minute change limits. The connector's own cap does apply: each batch counts as many writes as it has rows; the default of 1,000 writes per minute fits a full batch (The local guard).
  • Each row ends as created, updated, unchanged, failed (with error_code and error, for example password_policy or already_exists) or skipped. One failing row does not stop the others.
  • The import's counters (created, updated, unchanged, failed) grow as the batches finish, and the vertex.import event of the live stream announces each change. When no row is pending any more, the import is completed, or failed if every applied row failed.
  • If a whole batch fails (for example the connector's guard refuses it, or it expires before the connector runs it), all its rows are marked failed with the batch's error code.
  • Passwords are kept encrypted until the import is committed or cancelled, handed to the connector once per batch, and never shown again.

Result file​

GET …/imports/{importID}/result.csv returns every row with its outcome. It is separated by ;, UTF-8 with a BOM (it opens in Excel), and never contains passwords:

line;sAMAccountName;action;status;problems;error_code;error;objectGUID
2;ipetrov;create;created;;;;3f1c…
3;mivanova;update;unchanged;;;;9a0b…
4;gdimitrov;invalid;skipped;unknown group Teachers;;;

Cells that a spreadsheet would read as a formula (starting with =, +, -, @) are prefixed with '.

Limits​

LimitValue
Users per file10,000
Request size5 MB
Users per batch on the connector200
Groups per row100
Time to commit after the upload24 hours
A batch waits for the connector at most6 hours
A batch runs at most1 hour