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:
peopleHierarchygroupsHierarchy
For your use case of importing team hierarchy and membership, the main section you need is groupsHierarchy.
Each group object supports:
externalIdnameslugoptionalmanagerEmailoptionalmemberEmailschildren
The required group fields are:
externalIdnamechildren
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:
Sync only team hierarchy and memberships using
groupsHierarchySync both people records and team hierarchy in one payload using both
peopleHierarchyandgroupsHierarchy
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:
emailfirstNamelastNamereports
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_PATThat 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.jsonThis 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
externalIdvalues for every team so Span can recognize the same group across future syncs. This is inferred from the schema design, whereexternalIdis the group identifier.Keep
memberEmailsaligned to actual employee email addresses already known to Span or included inpeopleHierarchy. This is a practical implementation step based on how group membership is keyed in the schema.Put subteams under
childrenrather 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:
Enable Directory Sync with your Span rep.
Prepare a JSON payload using
groupsHierarchyfor teams andmemberEmailsfor membership.Authenticate with
Authorization: Bearer <PAT>.POST the file to
https://api.span.app/external/v1/directory-sync.Review the staged update in Span.
Approve the sync to apply the changes.