> ## Documentation Index
> Fetch the complete documentation index at: https://help.gowindmill.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SCIM Attributes and Field Sources

> Every employee field Windmill can sync through SCIM, the exact attribute names and namespaces to use in your identity provider, and how SCIM works with field sources.

Windmill's SCIM (System for Cross-domain Identity Management) endpoint accepts the standard SCIM user attributes, the enterprise manager extension, and a Windmill extension for job level, start date, pronouns, and gender. This article lists every supported attribute and explains how the values reach employee profiles.

For the identity provider setup, see [Set up SCIM with Okta](/security/scim-okta) or [Set up SCIM with Microsoft Entra ID](/security/scim-entra-id).

## Supported attributes

Core attributes sit at the top level of the SCIM user. Extension attributes sit inside an object keyed by the extension's schema URI.

### Core user attributes

Schema: `urn:ietf:params:scim:schemas:core:2.0:User`

| Windmill field  | SCIM attribute                               | Notes                                                                            |
| --------------- | -------------------------------------------- | -------------------------------------------------------------------------------- |
| Work email      | `userName` or `emails[type eq "work"].value` | **Required.** Windmill uses the work email to identify the member.               |
| External ID     | `externalId`                                 | Your identity provider's ID for the person. Optional but recommended.            |
| Access          | `active`                                     | `false` archives the member. `true` restores access.                             |
| First name      | `name.givenName`                             |                                                                                  |
| Last name       | `name.familyName`                            |                                                                                  |
| Display name    | `displayName`                                | If first and last name are missing, Windmill derives them from the display name. |
| Job title       | `title`                                      |                                                                                  |
| Work phone      | `phoneNumbers[type eq "work"].value`         | Must be a valid phone number.                                                    |
| Profile picture | `photos[type eq "photo"].value`              | Must be an HTTPS URL.                                                            |

### Manager

Schema: `urn:ietf:params:scim:schemas:extension:enterprise:2.0:User`

| Windmill field | SCIM attribute  | Notes                                                                      |
| -------------- | --------------- | -------------------------------------------------------------------------- |
| Manager        | `manager.value` | A reference to the manager. See [Manager references](#manager-references). |

### Windmill extension attributes

Schema: `urn:ietf:params:scim:schemas:extension:gowindmill:2.0:User`

| Windmill field | SCIM attribute | Notes                                                                     |
| -------------- | -------------- | ------------------------------------------------------------------------- |
| Job level      | `jobLevel`     | Free text, for example `Senior` or `L5`.                                  |
| Start date     | `startDate`    | `YYYY-MM-DD` format, for example `2026-09-08`. Invalid dates are skipped. |
| Pronouns       | `pronouns`     | Free text, for example `they/them`.                                       |
| Gender         | `gender`       | Free text.                                                                |

<Info>
  Most identity providers don't include these four attributes in their default SCIM attribute list. You add them once with the attribute name and the Windmill namespace, then map your identity provider's user attributes to them. The [Okta](/security/scim-okta#add-the-windmill-extension-attributes) and [Entra ID](/security/scim-entra-id#add-the-windmill-extension-attributes) guides walk through this.
</Info>

The Windmill extension attributes are **write-only**. Your identity provider can send them, but Windmill never returns them in SCIM responses, and their values don't appear in SCIM audit logs. Department mapping is not supported.

### Manager references

The `manager.value` attribute must identify a person who is already in Windmill. Windmill resolves the reference in this order and stops at the first match:

1. The manager's SCIM user ID, which is their Windmill Member ID
2. The manager's `externalId`
3. The manager's SCIM `userName`
4. The manager's work email

Most identity providers send the SCIM user ID automatically when both the manager and the report are assigned to the Windmill app. If the manager isn't in Windmill yet, Windmill stores the reference and applies it after the manager is provisioned.

A manager change that would create a reporting loop is skipped. A person set as their own manager clears the manager field.

## How SCIM works with field sources

Windmill treats SCIM as a [field source](/org-chart/employee-field-sources), alongside your HRIS (Human Resources Information System), Slack, Google Workspace, and Outlook. Every field on an employee profile has one source, and only that source can update the field.

Every SCIM request has two separate effects:

1. **Windmill stores the values** it receives from your identity provider. This always happens, even for fields another system owns.
2. **Windmill applies the values** to the employee profile for fields where SCIM is the source.

This means you don't need to configure field sources before your identity provider starts sending data. Values accumulate in the background, and Windmill applies them when SCIM becomes the source.

### Which fields SCIM updates

| Field state                                          | What happens when your identity provider sends a value                |
| ---------------------------------------------------- | --------------------------------------------------------------------- |
| No source set                                        | SCIM claims the field for the company and applies the value.          |
| Source is SCIM                                       | Windmill applies the value.                                           |
| Source is another system, like your HRIS             | Windmill stores the value but doesn't change the profile.             |
| Employee has a per-person override to another source | Windmill stores the value but doesn't change that employee's profile. |

When you switch a field's source to SCIM, Windmill applies the latest stored value to every affected employee within a few minutes. You don't need to trigger a new push from your identity provider. Windmill also runs an hourly check that re-applies stored values, so a missed update doesn't leave a profile out of date.

### Setting SCIM as the source for a field

<Steps>
  <Step title="Go to Settings > Org Chart">
    Open the [Org Chart](https://app.gowindmill.com/COMPANY/config/org-chart) and open the **Company defaults** tab.
  </Step>

  <Step title="Find the field">
    Fields are grouped into Personal, Role & reporting, Employment, and Contact. For example, **Job level** is under Role & reporting.
  </Step>

  <Step title="Select SCIM as the source">
    SCIM appears as an option for every field it can manage once your identity provider has connected. Select it to make SCIM the company-wide source.
  </Step>
</Steps>

To manage a field from SCIM for one person only, open the employee and set the source on their **Sources** tab. See [Overriding sources for one employee](/org-chart/employee-field-sources#overriding-sources-for-one-employee).

<Tip>
  If you also connect an HRIS, Windmill defaults job level, start date, gender, and manager to the HRIS. Pronouns default to Slack. Set the source to SCIM for any field you want your identity provider to own.
</Tip>

### Fields SCIM can manage

SCIM can be the source for: first name, last name, display name, work email, job title, job level, start date, pronouns, gender, work phone, profile picture, and manager.

## Clearing and updating values

Your identity provider controls whether a field is updated, left alone, or cleared:

* **A missing attribute leaves the field unchanged.** This applies to full replacements (PUT) as well as partial updates (PATCH), so an identity provider that sends only some attributes never wipes the others.
* **A `null` value, an empty string, or a PATCH `remove` operation clears the field.** An empty phone or photo list also clears the corresponding field.
* **Work email and `active` follow separate rules.** A valid work email is always required.

## Validation

Windmill validates each attribute on its own. An invalid optional attribute is skipped, and the valid attributes in the same request still apply. Your identity provider sees a successful response.

* Text values must be 255 characters or fewer.
* Start dates must be valid `YYYY-MM-DD` dates.
* Phone numbers must be valid phone numbers.
* Profile picture URLs must start with `https://`.
* Phone and photo entries should carry `type: "work"` and `type: "photo"`. If no entry has a matching type, Windmill uses the first entry without a type.

A request fails only for authentication problems, a missing work email, a malformed request, or a person whose employee record is already linked to a different member.

## Example user

This is the shape of a full user request from your identity provider. You don't write this yourself. It shows where each attribute belongs.

```json theme={null}
{
  "schemas": [
    "urn:ietf:params:scim:schemas:core:2.0:User",
    "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
    "urn:ietf:params:scim:schemas:extension:gowindmill:2.0:User"
  ],
  "userName": "alex@example.com",
  "externalId": "idp-alex",
  "name": { "givenName": "Alex", "familyName": "River" },
  "displayName": "Alex River",
  "title": "Software Engineer",
  "phoneNumbers": [{ "type": "work", "value": "+12025550123" }],
  "photos": [{ "type": "photo", "value": "https://example.com/alex.png" }],
  "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
    "manager": { "value": "manager-scim-id" }
  },
  "urn:ietf:params:scim:schemas:extension:gowindmill:2.0:User": {
    "jobLevel": "Senior",
    "startDate": "2026-09-08",
    "pronouns": "they/them",
    "gender": "Non-binary"
  }
}
```

An identity provider can also update one extension attribute on its own with a PATCH request:

```json theme={null}
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "replace",
      "path": "urn:ietf:params:scim:schemas:extension:gowindmill:2.0:User:jobLevel",
      "value": "Staff"
    }
  ]
}
```

## Supported operations

| Resource                                               | Operations                                                                  |
| ------------------------------------------------------ | --------------------------------------------------------------------------- |
| `/Users`                                               | Create, list, read, replace (PUT), update (PATCH), and deprovision (DELETE) |
| `/Groups`                                              | Create, list, read, replace, update membership, and delete                  |
| `/Schemas`, `/ResourceTypes`, `/ServiceProviderConfig` | Discovery                                                                   |

List filters support `eq` and `and` on `userName`, `externalId`, `displayName`, and `emails[type eq "work"].value`. SCIM bulk operations, sorting, ETags, and password changes aren't supported.

## FAQs

<AccordionGroup>
  <Accordion title="Do I have to map every attribute?">
    No. Only the work email is required. Map the fields you want your identity provider to manage. First name and last name are strongly recommended.
  </Accordion>

  <Accordion title="I mapped job level in my identity provider, but it isn't on the employee profile.">
    Check the field's source in [**Settings > Org Chart**](https://app.gowindmill.com/COMPANY/config/org-chart). If an HRIS owns job level, Windmill stores the SCIM value but doesn't apply it. Switch the source to SCIM and the stored value is applied within a few minutes. Also confirm the attribute uses the exact external name `jobLevel` and the namespace `urn:ietf:params:scim:schemas:extension:gowindmill:2.0:User`.
  </Accordion>

  <Accordion title="Can I use SCIM together with an HRIS integration?">
    Yes. Pick a source per field. For example, your HRIS can own job title and start date while SCIM owns names and work email. Windmill never lets two sources write the same field.
  </Accordion>

  <Accordion title="Why doesn't my identity provider show job level, pronouns, or gender as available attributes?">
    These attributes live in the Windmill extension schema, so they're not in your identity provider's default list. Add them once with the attribute name and namespace from the table above. See the [Okta](/security/scim-okta#add-the-windmill-extension-attributes) or [Entra ID](/security/scim-entra-id#add-the-windmill-extension-attributes) guide.
  </Accordion>

  <Accordion title="The manager field is blank even though my identity provider sends it.">
    The manager must already be provisioned into Windmill. Assign the Windmill app to the manager in your identity provider. Windmill keeps the reference and applies it once the manager exists. Also check that the manager field's source is SCIM.
  </Accordion>

  <Accordion title="What happens to a value my identity provider stops sending?">
    Nothing. A missing attribute means "leave unchanged." To clear a field, your identity provider must send an empty value or a remove operation.
  </Accordion>

  <Accordion title="Can I edit a SCIM-managed field in Windmill?">
    Yes. Editing a synced field on the employee's **Info** tab creates a per-person manual override, and SCIM stops updating that field for that person. Clear the override on their **Sources** tab to hand the field back to SCIM. See [Editing a synced field](/org-chart/employee-field-sources#editing-a-synced-field).
  </Accordion>
</AccordionGroup>
