15.4Requests and responses
Last updated
Format
Requests and responses use JSON (Content-Type: application/json). Property names are camelCase. Dates and times are ISO 8601 in UTC.
Creating an object
A create takes the object's fixed fields and an attributes bag for any other attributes, keyed by their LDAP display names:
POST /api/ad/users HTTP/1.1
Host: gateway.example.com
X-API-Key: <your API key>
X-Client-Id: hr-sync
Content-Type: application/json
{
"name": "Jane Doe",
"path": "OU=Staff,DC=example,DC=com",
"samAccountName": "jdoe",
"password": "<initial password>",
"accountPolicy": { "enabled": true, "changePasswordAtLogon": true },
"attributes": {
"givenName": "Jane",
"sn": "Doe",
"mail": "jane.doe@example.com",
"department": "Finance"
}
}A successful create answers 201 Created with the new object and a Location header pointing at it.
The accountPolicy object sets account flags without writing userAccountControl directly. It accepts enabled, passwordNeverExpires, smartcardLogonRequired, trustedForDelegation, accountNotDelegated, passwordNotRequired, cannotChangePassword, allowReversiblePasswordEncryption, changePasswordAtLogon and compoundIdentitySupported. Omitted flags keep their defaults. User and computer updates accept accountPolicy too, and change only the flags you send.
Updating an object
An update names how each attribute changes, using four bags:
PATCH /api/ad/users/3f2504e0-4f89-11d3-9a0c-0305e82c3301 HTTP/1.1
Content-Type: application/json
{
"replace": { "title": "Senior Accountant", "department": "Finance" },
"add": { "otherTelephone": ["+370 600 00000"] },
"remove": { "proxyAddresses": ["smtp:old@example.com"] },
"clear": ["description"]
}| Bag | Effect |
|---|---|
replace | Sets the attribute to exactly the given value or values. |
add | Adds values to a multi-valued attribute. |
remove | Removes the listed values. |
clear | Removes every value of the listed attributes. |
Attributes in the attributes and replace bags are checked against the directory's schema before anything is written. A name the schema does not know, a system-only attribute, an array for a single-valued attribute, or a value of the wrong type is refused with 400 and AD.Attributes.ValidationError.
Security-sensitive attributes are refused in every bag, with the same code: among them userAccountControl (use accountPolicy), servicePrincipalName (use the /spns routes on users and computers, which need ad:spn:manage), adminCount, primaryGroupID, sIDHistory, delegation and resource-based delegation attributes, msDS-KeyCredentialLink, userCertificate, altSecurityIdentities, scriptPath, nTSecurityDescriptor and the password attributes. Reading credential attributes such as LAPS passwords and managed service account passwords through the generic read is refused with 403 and AD.Attributes.ReadForbidden.
An administrator can also protect attributes with attribute policies (Chapter 10, Operation policies, attribute policies and agent supervision). They apply to every caller, API keys and agents included, and nothing is queued for approval:
- A write — in any bag, or through a typed field such as
samAccountName— that touches a read-only or blocked attribute is refused with403andAD.Attributes.Protected.metadata.attributeslists each one as{ attribute, access, ruleId, reason }. A batch is refused whole, before any item runs. - A blocked attribute is left out of every read and of the schema routes. Naming it in a properties list, or testing it in an LDAP filter, is refused with
403andAD.Attributes.ReadForbidden. - The schema routes mark a read-only attribute with
isReadOnly: true,access: "ReadOnly"andaccessReason.
Searching and paging
Search endpoints take the container to search from and an optional LDAP filter, and return results one page at a time:
GET /api/ad/users?baseDn=OU%3DStaff%2CDC%3Dexample%2CDC%3Dcom&ldapFilter=(department%3DFinance)&pageSize=100 HTTP/1.1| Parameter | Meaning |
|---|---|
baseDn | The container to search from. Required. |
ldapFilter | An LDAP filter combined with the object type's own filter. |
properties | Additional attributes to return; repeat the parameter for several. |
pageSize | Results per page. Default 50, maximum 1000. |
continuationToken | The token from the previous page, to fetch the next one. |
The response has three parts:
{
"data": [ { "objectGuid": "3f2504e0-4f89-11d3-9a0c-0305e82c3301", "...": "..." } ],
"meta": { "nextContinuationToken": "…", "pageSize": 100, "hasNextPage": true },
"links": { "current": "…", "next": "…" }
}Keep requesting with continuationToken (or follow links.next) until hasNextPage is false.
Last updated
Thank you for your feedback.