
# Update a directory

`PATCH /v1/directories/{directory_id}` · permission `directories:write`

Updates the directory's name and provisioning settings with a JSON merge patch (RFC 7396, `Content-Type: application/merge-patch+json`). `If-Match` is required; the current value is the `ETag` header of `GET /v1/directories/{directory_id}`. No field accepts `null`. A patch that changes nothing writes nothing and keeps the version. The write is audited as `directory.updated` with the old and new value of each changed setting.

- `provisioning_mode` cannot change while the directory has user records that are not deleted (`409 conflict`); delete and recreate the directory instead.
- `attribute_allowlist` is replaced as a whole. An attribute removed from the list is deleted from the directory's user records in the same transaction.
- `mass_deprovision_guard` can be patched partly; the sub-fields you leave out are kept.

## Request

| Field | Type | Required | Description |
|---|---|---|---|
| `directory_id` | path | yes | SCIM directory ID (`dir_…`). |
| `If-Match` | header | yes | Current `ETag` of the directory. |
| `name` | string | no | 1–64 characters, no control characters, no leading or trailing spaces. |
| `provisioning_mode` | string | no | `user_store` (environment users, organization memberships and group roles are written too) or `mirror` (only the directory records are kept). |
| `attribute_allowlist` | array | no | Optional SCIM attributes that are stored, without duplicates: `title`, `usertype`, `phonenumbers` and the enterprise extension's `employeenumber`, `department`, `division`, `costcenter`, `organization`, `manager` (full `urn:ietf:params:scim:schemas:extension:enterprise:2.0:user:` names). |
| `unverified_domain_action` | string | no | A user whose email domain is not verified: `invite` (invited membership) or `mirror_only` (directory record only). |
| `delete_action` | string | no | SCIM `DELETE /Users`: `remove_membership` or `delete_user` (deletes the user the directory manages). |
| `on_delete_memberships` | string | no | What happens to the memberships from this directory when the directory is deleted: `keep`, `suspend` or `remove`. |
| `mass_deprovision_guard` | object | no | `enabled` (boolean), `percent` (5–50) and `absolute_min` (10–1000): deprovisions above both thresholds within 5 minutes are held for approval. |
| `send_welcome_email` | boolean | no | Whether a new directory user gets an account activation email. |

## Response

`200 OK` with the directory and its new `ETag`.

```json
{
  "id": "dir_01j9xm2n4p6q8r0s2t4v6w8y0z",
  "organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
  "type": "scim",
  "name": "Okta EU",
  "state": "active",
  "base_url": "https://acme.eu.keenauth.app/scim/v2/dir_01j9xm2n4p6q8r0s2t4v6w8y0z",
  "created_at": "2026-10-19T09:31:00.123456Z",
  "last_request_at": null,
  "provisioning_mode": "user_store",
  "attribute_allowlist": ["title", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:user:department"],
  "unverified_domain_action": "invite",
  "delete_action": "remove_membership",
  "on_delete_memberships": "keep",
  "mass_deprovision_guard": {"enabled": true, "percent": 20, "absolute_min": 25},
  "send_welcome_email": false
}
```

## Errors

| HTTP | code | When |
|---|---|---|
| 400 | `malformed_request` | The body is not a JSON object. |
| 400 | `unknown_field` | The patch contains a field that cannot be written (for example `state`). |
| 404 | `not_found` | The directory does not exist in this environment. |
| 409 | `conflict` | `provisioning_mode` changes while the directory has user records, or the directory is being deleted. |
| 412 | `precondition_failed` | `If-Match` does not match the current version. |
| 415 | `unsupported_media_type` | `Content-Type` is not `application/merge-patch+json`. |
| 422 | `validation_failed` | A field is `null` or invalid; the error names the field (for example `/mass_deprovision_guard/percent` `invalid`). |
| 428 | `precondition_required` | `If-Match` is missing. |
| 401 | `unauthenticated` | The credential is missing, invalid or revoked. |
| 403 | `insufficient_permissions` | The credential lacks the required permission. |
| 429 | `rate_limited` | The rate limit was exceeded; retry after the `Retry-After` period. |
| 503 | `service_unavailable` | Directory sync is temporarily unavailable or not configured in this deployment; retry after the `Retry-After` period. |

## Example

```bash
curl -i -X PATCH "https://api.eu.keenauth.com/v1/directories/dir_01j9xm2n4p6q8r0s2t4v6w8y0z" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H 'If-Match: "3"' \
  -H "Content-Type: application/merge-patch+json" \
  -d '{"name":"Okta EU","mass_deprovision_guard":{"percent":20}}'
```
