How to use the directory sync JSON file to import team hierarchy and membership into Span

Last updated: April 23, 2026

Directory Sync is the feature Span uses to keep people records and team structure up to date. It can accept people data, team hierarchy data, or both via API, and any incoming changes are staged for review before they go live. It is currently early access / feature-flagged, and Span recommends enabling it with your rep first.  

Before you start

Make sure these prerequisites are in place:

  • Directory Sync is enabled in your Span account, since the feature is behind a flag.  

  • The user reviewing or approving the sync in Span has the global Member Management permission.  

  • You have a Span API token to authenticate requests.

  • You have your JSON payload ready in the format expected by the Directory Sync API.

Your uploaded OpenAPI file shows the endpoint is:

POST https://api.span.app/external/v1/directory-sync  

It also shows the API uses bearer-token authentication in the Authorization header. The security scheme is an HTTP bearer scheme with PAT format.  

What the API accepts

The request body can contain either of these top-level fields:

  • peopleHierarchy

  • groupsHierarchy  

For your use case of importing team hierarchy and membership, the main section you need is groupsHierarchy.

Each group object supports:

  • externalId

  • name

  • slug optional

  • managerEmail optional

  • memberEmails

  • children  

The required group fields are:

  • externalId

  • name

  • children  

That means team membership is typically supplied in memberEmails, and nested team structure is supplied in children. The API supports a true hierarchy, so parent teams can contain child teams recursively.  

Step 1: Decide what you are syncing

You have two main options:

  1. Sync only team hierarchy and memberships using groupsHierarchy

  2. Sync both people records and team hierarchy in one payload using both peopleHierarchy and groupsHierarchy  

Span’s help center says Directory Sync can combine multiple sources, but recommends using the API as the source of truth for both people and team hierarchy whenever possible.  

Step 2: Build your JSON file

Create a JSON file, for example directory-sync-payload.json.

Example: team hierarchy and membership only

{
  "groupsHierarchy": [
    {
      "externalId": "eng",
      "name": "Engineering",
      "slug": "engineering",
      "managerEmail": "vp-eng@company.com",
      "memberEmails": [],
      "children": [
        {
          "externalId": "platform",
          "name": "Platform",
          "slug": "platform",
          "managerEmail": "platform-manager@company.com",
          "memberEmails": [
            "alice@company.com",
            "bob@company.com"
          ],
          "children": []
        },
        {
          "externalId": "product-eng",
          "name": "Product Engineering",
          "slug": "product-engineering",
          "managerEmail": "product-manager@company.com",
          "memberEmails": [
            "carol@company.com",
            "dan@company.com"
          ],
          "children": [
            {
              "externalId": "growth",
              "name": "Growth",
              "slug": "growth",
              "managerEmail": "growth-manager@company.com",
              "memberEmails": [
                "erin@company.com"
              ],
              "children": []
            }
          ]
        }
      ]
    }
  ]
}

This structure matches the uploaded schema: top-level groupsHierarchy, with each group carrying metadata plus nested children.  

Example: people plus hierarchy

If you also want Span to update people records through the same API, include peopleHierarchy too:

{
  "peopleHierarchy": [
    {
      "email": "vp-eng@company.com",
      "firstName": "Vera",
      "lastName": "Ng",
      "timezone": "America/New_York",
      "jobTitle": "VP Engineering",
      "jobFamily": "Engineering",
      "location": "New York",
      "startDate": "2024-01-15",
      "terminationDate": null,
      "vcsUsernames": ["verang"],
      "reports": [
        {
          "email": "platform-manager@company.com",
          "firstName": "Priya",
          "lastName": "Shah",
          "timezone": "America/Los_Angeles",
          "jobTitle": "Director, Platform",
          "jobFamily": "Engineering",
          "location": "San Francisco",
          "startDate": "2023-05-01",
          "terminationDate": null,
          "vcsUsernames": ["pshah"],
          "reports": []
        }
      ]
    }
  ],
  "groupsHierarchy": [
    {
      "externalId": "eng",
      "name": "Engineering",
      "children": []
    }
  ]
}

In the schema, each person requires:

  • email

  • firstName

  • lastName

  • reports  

Step 3: Set up authorization

The API uses bearer-token authentication. In practice, that means you send your personal access token in the Authorization header like this:

Authorization: Bearer YOUR_SPAN_PAT

That header format is implied by the uploaded OpenAPI definition’s HTTP bearer security scheme.  

Step 4: Send the payload with curl

Basic curl command

curl -X POST "https://api.span.app/external/v1/directory-sync" \
  -H "Authorization: Bearer YOUR_SPAN_PAT" \
  -H "Content-Type: application/json" \
  --data @directory-sync-payload.json

This sends your local JSON file directly to the Span Directory Sync endpoint defined in the OpenAPI file.  

curl command with inline JSON

curl -X POST "https://api.span.app/external/v1/directory-sync" \
  -H "Authorization: Bearer YOUR_SPAN_PAT" \
  -H "Content-Type: application/json" \
  --data '{
    "groupsHierarchy": [
      {
        "externalId": "eng",
        "name": "Engineering",
        "managerEmail": "vp-eng@company.com",
        "memberEmails": [],
        "children": [
          {
            "externalId": "platform",
            "name": "Platform",
            "managerEmail": "platform-manager@company.com",
            "memberEmails": ["alice@company.com", "bob@company.com"],
            "children": []
          }
        ]
      }
    ]
  }'

Step 5: Check the response

The OpenAPI file shows the response body contains:

{
  "success": true
}

The success boolean is the only required response field in the schema.  

Step 6: Review the staged sync in Span

Submitting the API payload does not immediately push changes live. Span’s help center says Directory Sync:

  • pulls data from configured sources

  • calculates a staged update

  • lets you review and approve the changes

  • does not apply updates until you explicitly approve them.  

Also, additions and deletions of people, teams, and memberships are reviewable, while individual field changes like title updates are not individually reviewable.  

Step 7: Approve the changes

Once the staged sync looks correct in Span, approve it in the Directory Sync page. Span only applies the updates after approval.  

Step 8: Correct errors in the source JSON if needed

If something looks wrong in the staged update:

  • fix the data in your source system or JSON payload

  • resend the updated payload

  • review the new staged update in Span.  

Recommended formatting rules for your JSON

To make imports more reliable:

  • Use stable externalId values for every team so Span can recognize the same group across future syncs. This is inferred from the schema design, where externalId is the group identifier.  

  • Keep memberEmails aligned to actual employee email addresses already known to Span or included in peopleHierarchy. This is a practical implementation step based on how group membership is keyed in the schema.  

  • Put subteams under children rather than flattening the structure if you want hierarchy preserved.  

  • Use the API as the source of truth for both people and hierarchy whenever possible, per Span’s best-practice guidance.  

Here are the steps, summarized:

  1. Enable Directory Sync with your Span rep.  

  2. Prepare a JSON payload using groupsHierarchy for teams and memberEmails for membership.  

  3. Authenticate with Authorization: Bearer <PAT>.  

  4. POST the file to https://api.span.app/external/v1/directory-sync.  

  5. Review the staged update in Span.  

  6. Approve the sync to apply the changes.