Import people
Add or update staff and students from a CSV, a nightly SFTP file, or your SIS over OneRoster. How matching, roles and locations work.
Open the People tab of Admin › Account › Import Data to bring everyone into schoolOS at once. People you import can sign in with their district email and arrive with the right role at the right school.
Your SIS connection#
Once a roster connection is saved, the People tab opens on it instead of the CSV upload. The panel at the top says what it's connected to, like Connected to Alma · OneRoster API, and shows:
- Last sync. When the last run ended and how: Imported 412 people, Failed: and the reason, and so on.
- Schedule. When it syncs on its own and when the next run is, like Every day at 2:00 AM · Next run 10/30/2026, 2:00:00 AM, or Off when the scheduled import is turned off.
- Sync now. Reads your SIS now, for a OneRoster API connection. SFTP files are picked up when they arrive.
The settings follow the panel. A CSV upload is still there, under Upload a file instead at the bottom: Upload a CSV opens the upload, and Download Template gives you the columns. Uploading a file doesn't change your SIS connection. While you're on the upload, a note at the top says where your roster syncs from, with Back to your SIS connection.
What a sync is doing#
After you select Sync now, the line under the panel's heading follows the run until it ends. It stays there; you don't need to reload.
| It says | What it means | | --- | --- | | Queued. Waiting for the sync to start… | The sync is waiting for schoolOS to start it, usually a few seconds. | | The sync hasn't started yet. schoolOS staff have been notified. | It has waited more than two minutes. schoolOS staff were told when it passed two minutes; it starts on its own once the problem is fixed. You don't need to select Sync now again. | | Running… | Reading your SIS and importing. Once people are read, it counts them: Running… 412 people read so far. | | Waiting for your review | The first import stopped before changing anything, so you can check it. Select Review the first import to go to it. See First-import review. | | Imported 412 people | Finished: that many people were added or updated. Finished. Everyone was already up to date. means nothing changed. | | Failed: and a reason | Nothing was imported. The reason is the same as Test connection would give. | | Blocked by a safety check | A circuit breaker stopped the run, like Blocked by the users deactivated check. It waits for your review in the run list. |
You also see a message in the corner when the run ends. Selecting Sync now again while a sync is queued follows the same sync instead of starting a second one.
First-import review#
The first import from a roster connection doesn't change anything until you've seen what it would do, when it would adopt people who are already in schoolOS, match schools by name, or turn anyone off. It appears at the top of the People tab, under the panel, as Confirm before the first import: how many people are already linked, will be adopted, created or turned off, and which schools were matched by name.
- Confirm and import starts the import. For a OneRoster API connection it starts right away, and the panel follows it; for SFTP, the next file run imports it.
- Re-check works it out again. For a OneRoster API connection that reads your SIS again, and the new numbers appear when that run stops for review.
A first import that only creates people (nobody to adopt, no school matched by name) doesn't stop.
Import History#
Import History lists your roster syncs above your file uploads. Roster syncs shows each OneRoster API and SFTP run with its source, status, changes (created, updated, turned off), when it started and finished, who started it (Schedule when nobody did), and, for a run that failed, was stopped or hasn't started, why. File uploads lists your CSV imports as before.
Choose how your roster arrives#
How your roster reaches schoolOS has three options. It's at the top of the page until a roster connection is saved, then under the SIS panel:
- Manual upload. You upload a CSV yourself. Nothing runs on a schedule.
- SFTP. Your SIS drops a file in a folder we host, and schoolOS imports it every night. A file identical to one already imported is skipped, and the run says which file it matched.
- OneRoster API. schoolOS connects to your SIS directly. No export job, no file.
Which should I choose?#
| Option | What it keeps up to date | Choose it when | | --- | --- | --- | | Manual upload | Only what's in the file, when you upload it. New people are added, and existing people's names, phone, school role, active status and your own fields are updated from the columns you map; see Update or Overwrite for blank cells. Their schoolOS role and home school aren't changed, and people missing from the file stay as they are. | Your first import, a small district, or staff your SIS doesn't hold, like substitutes and contractors. | | SFTP | The same, every night, from a CSV your SIS exports. A OneRoster file dropped in the folder is handled like the OneRoster API instead. | Your SIS can export a file on a schedule but can't connect over OneRoster. | | OneRoster API | Everything your SIS knows: schoolOS role, school, grades, classes and guardian links. People who drop out of the roster are turned off, unless so many would be that it looks like a bad sync. | Your SIS supports OneRoster, and you want it to be the source of truth for students, staff and families. |
You can start with a manual upload and switch to SFTP or OneRoster later. Nothing you imported is lost when you switch.
On the SFTP and OneRoster pages, Roster data starts open. The sections after it (Roster import or OneRoster sync, Role mapping, Connection, Roster file mapping, Sync behavior) start closed and show what they're set to, like On or 12 columns mapped; select a section's name to open it. The page remembers what you left open.
Connect over the OneRoster API#
Choose your SIS and the OneRoster version it offers, then copy these from your SIS's OneRoster settings:
- Base URL. The address of your SIS's OneRoster API. The box shows the shape your SIS uses where it publishes one; otherwise paste the URL your SIS gives you. It can end with the version path (
/ims/oneroster/v1p1) or stop before it. - Client ID and Client secret.
- Token URL (optional). Where schoolOS signs in. Leave it blank to use the address shown in the box, which is worked out from your Base URL. Enter one if your SIS gives you a Token URL. PowerSchool always needs it entered. For Alma, the box shows
https://yourdistrict.api.getalma.com/v2/yourdistrict/access-token, worked out from a Base URL likehttps://yourdistrict.api.getalma.com/v2/yourdistrict/ims/oneroster/v1p1. - Scope (optional). Leave it blank to ask for read-only access to the roster, which is all schoolOS reads. Enter a scope only if your SIS asks for a different one.
Test connection signs in and reads your schools before you save. It doesn't save anything: Sync now reads the saved connection, so until you save, it's off and says Save your connection to sync. When a test works on settings you haven't saved yet, Save and sync saves them and starts the first sync in one step (the first import may still wait for your review). With ClassLink, there is nothing to enter: pick your district, and Test connection checks both that your district still grants schoolOS access and that its roster answers.
Sign-in method
OneRoster servers don't all sign in the same way. Under Advanced, Sign-in method has three choices:
- Automatic. schoolOS tries OAuth 2 with the scope above, then OAuth 2 with no scope, then OAuth 1.0a, and remembers the one your SIS accepts. Test connection tries them every time; a sync tries them once and uses what worked from then on. Changing the client ID, secret, Base URL, Token URL or scope makes schoolOS find out again. It stops trying as soon as your SIS has an outage (a server error or no answer) rather than a sign-in problem, so an outage is reported as one.
- OAuth 2 (client credentials). schoolOS trades the client ID and secret for a token at the Token URL. What most SIS systems use, and the default for every SIS in the list.
- OAuth 1.0a (signed requests). schoolOS signs every request with the client ID and secret instead. Some older OneRoster servers work this way. There is no Token URL or scope, so those boxes are hidden.
If you chose Other / not listed, the sign-in method starts on Automatic.
When Test connection fails
The result says which step failed (signing in, or the first request for your schools, with its status) and which address answered. Never your secret.
| What it says | What it means | What to ask your SIS | | --- | --- | --- | | The SIS rejected the client ID or secret | The token address answered, but not with these credentials. | Are this client ID and secret active, and allowed to read rostering? | | The SIS doesn't accept the scope schoolOS asked for | The credentials are fine; the scope isn't one this client has. | Which scope strings should we request? Enter that in Scope, or set Sign-in method to Automatic to try without one. | | The SIS doesn't use this sign-in method (OAuth 2) | The server doesn't do OAuth 2 client credentials. | Does your API use OAuth 1.0a? If so, choose it, or Automatic. | | No token endpoint at … | Nothing at that address handles sign-in. Either the Token URL is wrong, or the SIS signs each request (OAuth 1.0a). | What is the token URL? | | Signing in worked, but the SIS refused to read orgs | The token is good, but this client can't read the roster. | Can this client have read-only roster access? | | Couldn't find the server, Couldn't make a secure connection, didn't answer | The address doesn't resolve, its certificate is invalid or expired, or it timed out. Nothing about your credentials yet. | Check the Base URL and Token URL for typos first. | | No sign-in method worked. OAuth 2: … · OAuth 2 without scope: … · OAuth 1.0a: … | Automatic tried all three; each part says how that one failed. | Send the whole line to your SIS, and to schoolOS support if you contact us. |
If you're not sure how your SIS signs in, send them this: "Does your OneRoster 1.1 API use OAuth 2 client credentials or OAuth 1.0a? If OAuth 2, what is the token URL and which scope strings should we request?"
ClassLink: schoolOS confirms your district#
Every district in ClassLink reaches schoolOS through the same connection, so picking a district is what decides whose roster schoolOS reads. To make sure nobody can pick a district that isn't theirs, someone at schoolOS confirms your pick before anything is read:
- Pick your district under Your district in ClassLink and save.
- The screen says Waiting for schoolOS to confirm your ClassLink district. While it waits, nothing syncs, there's no Sync now button, Test connection only checks that your district still grants schoolOS access, and nobody can sign in with ClassLink.
- Once schoolOS confirms it, Sync now appears, the nightly sync starts, and ClassLink sign-in works.
You don't need to do anything else while it waits. If you pick a different district later, or disconnect and connect again, it waits for schoolOS again. If schoolOS can't confirm it, your pick is cleared and the screen tells you; pick your district again, or contact schoolOS support.
Every run reads all of your roster, however many records your SIS sends at a time. If your SIS keeps sending new records past 10,000 pages of one kind, the run stops and imports nothing, because importing part of a roster could turn off everyone it didn't reach. A nightly run after the first reads only what changed since a few minutes before the last successful run began, so a change made while a run was reading is picked up the next night.
Weekly full roster check
A changes-only read can't see someone your SIS deleted, or simply stopped sending, instead of marking them inactive: they aren't among the changes, so nothing happens to them. Once a week, the sync reads your whole roster instead. Choose the day under Sync behavior › Full roster check; it's Sunday unless you change it. Days are counted in your district's time zone, or in UTC if your district hasn't set one.
- With Full roster sync, people missing from that full read are turned off, under the same deactivation threshold and circuit breakers as any full sync. If more would be turned off than your threshold allows, nobody is, and the run waits for your review.
- With Create only or Create + update, nobody is turned off. The weekly read only refreshes everyone.
- A connection made before this check existed waits for its chosen day for its first full read, so nobody is turned off the night the check arrives. If your sync never runs on that day, the first full read happens a week after it started waiting.
- If the full read doesn't happen because the run failed, was stopped by a circuit breaker, or your sync doesn't run on that day, the next sync reads everything once a week or more has passed since the last full read. A read that fails or stops partway turns nobody off.
Last full check under the same setting shows when the last full read ran and how many people it turned off. Some SIS systems can't report what changed; for those, every sync is already a full read. SFTP files aren't affected: each file is a whole roster already.
For example, a district on Full roster sync with the full check on Saturday: a student withdrawn on Tuesday whom the SIS deletes rather than marks inactive stays active through the week's changes-only reads, and is turned off on Saturday night.
For example, a district with 12 schools uploads a CSV of staff to get started in the summer, then switches to the OneRoster API before school starts. From then on, a student who moves from the middle school to the high school is moved in schoolOS the next night, and a guardian with two students is linked to both. When the roster gets one person wrong and your SIS can't fix it, turn on Keep my changes for that person.
Upload a CSV#
- Select Download Template for a CSV with the right columns, or use your own export. With a roster connection saved, both are under Upload a file instead: select Upload a CSV first.
- Pick a Default role (see below).
- Choose what a blank cell does to people who are already in schoolOS: Update or Overwrite.
- Drop your CSV on the page, or click to browse.
- Select Continue to Field Mapping and match each column in your file to a schoolOS field. Columns you don't map are ignored.
- Review the counts: how many people will be created, updated, or restored, and which fields the updates change or clear. Rows with problems are listed with the reason, so you can fix them in your file and upload again. When it's done, the result says how many people were imported and with which roles, like 12 people (10 Staff, 2 Agent).
- Start the import. A file of up to 500 rows is imported right away. A larger file, up to 500,000 rows and 1 GB, is queued with Queue User Import and runs in the background; you can leave the page once it's queued. A file over 48 MB goes up in pieces first, and the button shows how far it's got ("Uploading 40%"). Import History shows every import and its result.
People the import creates sign in with their district account. Only roles that get an invite email receive a temporary password; everyone else sets one from the sign-in page if they ever need it.
Default role#
Default role, above the upload box, is the schoolOS role for new people whose row has no schoolOS Role. It starts at Staff, and lists the same roles as Add user on Admin › People › Users: the built-in roles you're allowed to give, never one above your own, and your account's own roles that you rank high enough to give. It only shows when you can give more than one.
- One kind of person per file (all teachers, or all students): pick their role here, and leave the schoolOS Role column out.
- A mix in one file (a front office list with a few agents): add a schoolOS Role column for the rows that differ, and let the default cover the rest.
The default only applies to people the import creates. It never changes the role of someone who's already in schoolOS.

Fields#
Three fields are required in every row:
- Email. How schoolOS recognizes the person, and how they sign in.
- First Name and Last Name.
The rest are optional:
- schoolOS Role. The role that decides what they can do, like Staff or Student, written as its name or its key (
end_user). Your account's own roles work too, by name. Rows without one get the Default role. A role you can't give flags the row, with the list of roles you can. It's used for new people only. - School Role. Their job, for example Teacher or Principal. It's a label, not permissions. A school role that doesn't exist yet is created for you.
- Location Name. The school or building they belong to, matched by the location's name. Required for roles that only see their own school. People without one are placed at your account's default location.
- A person has one location. An Other Locations column from an older file is ignored: the other schools someone looks after come from their teams.
- Rooms. The rooms they're in, separated by semicolons:
AHS/104; AHS/118, or104; 118for rooms in their own location. The first is their primary room. Rooms must already exist on Admin › Locations › Locations (the Locations & Rooms import adds them in bulk); a room that doesn't flags the row. Given for someone already in schoolOS, the column replaces their rooms. See rooms on a profile. - Phone.
- User ID number. Their student or employee number from your SIS. Headers like
Student Number,Student IDorEmployee IDare recognized too. MySchoolBucks finds a student's fees by it. A number in the file replaces theirs; a blank cell never clears it. - Active.
trueorfalse(yes,no,1and0work too). Usefalseto turn off someone who has left, without deleting them. Empty means "leave it": a new person starts active, and someone already in schoolOS keeps their status, so importing your roster again never turns back on someone you turned off. A blank Active never turns anyone off either, even with Overwrite. - Your own fields. Each field added on Admin › People › User Fields is offered too, matched by its name or its key. Values are checked against the field's type and options, and a blank cell keeps what the person has. Dates and numbers read as in an asset import (see Dates and numbers):
2024-03-15is best, slash dates are month first, and15/03/2024, which can only be day first, is read that way with a warning on the row. Numbers take thousands commas (1,250.50) but a period for decimals. See User fields.
How people are matched#
schoolOS matches each row to an existing person in your account by email address, ignoring capitalization.
- No match: the person is created.
- A match: their name is updated from the file, and their active status when the Active cell says
trueorfalse. A blank Phone, School Role or field of your own keeps what they already have, unless you chose Overwrite. Their schoolOS role and home location aren't changed: change those on Admin › People › Users. - A match with someone who was removed: they're restored, with their history intact.
- Someone in another district only: they're added to yours as a new person, with the role the import gives. They keep the way they sign in, and are emailed that you added them instead of a password. See Work in more than one district.
Because matching is by email, changing someone's email in your file creates a new person instead of updating the old one. Change it on their profile in schoolOS first.
An import only updates people you could manage yourself: people at schools you reach, with a role you can give. A row that matches anyone else is flagged and skipped. Updating people also takes permission to edit people; without it, the import only adds new people, and a row whose email is already in schoolOS is flagged.
Update or Overwrite#
When a cell is blank, above the upload box, decides what an empty cell does to someone who's already in schoolOS:
| Choose | A blank cell | Use it when | | --- | --- | --- | | Update (the default) | Keeps what's in schoolOS. | You're adding people or fixing a few columns. Nothing you leave empty is lost. | | Overwrite | Clears that field on the person. | The file is the record now, like a cleanup where an empty Phone or Grade should be empty in schoolOS too. |
In both, a column the file doesn't have, or one you skip when mapping, is never touched. New people are the same either way.
Overwrite clears Phone, School Role and your own fields. It never clears what identifies a person or what every person has: Email, First Name, Last Name, schoolOS Role, Location Name, Rooms and User ID number keep their value when the cell is blank. Active is never cleared either: a blank Active keeps their status in both modes, and only false turns someone off.
Before anything is written, the import names what Overwrite will clear and for how many people: "Overwrite clears Grade, Phone on 120 people where the file leaves them blank." When you import, a confirmation repeats it. Select Overwrite to go ahead, or Cancel and start again with Update. The import's status shows which one it used, beside the Job ID.
For example, after a phone system change, export your staff, correct the Phone column, and empty the cells for people who no longer have a desk phone. Import with Overwrite, mapping only Email, First Name, Last Name and Phone: the emptied phones clear, and nothing else about anyone changes.
What a nightly import changes#
A roster that arrives every night mostly says what it said the night before. Each run compares every person it covers with what schoolOS holds and writes only the people something changed for; everyone else is left alone, with their modified date and history as they were. The run's summary counts them separately: updated is the people whose record changed, unchanged the people the roster matched and had nothing new about. A file whose bytes are identical to one this connection already imported isn't read at all; its run is marked skipped and names the earlier file.
Who can do what#
- Upload a CSV needs Add people (
users.create). It adds and updates people only where your role reaches, with the roles you can give. - An import you started is yours to fix, re-check and commit. Someone else's import runs with its starter's rights, so only they or a super admin can change it. People whose role reaches the whole account can open anyone's import to see its rows; everyone else sees only their own.
- Set up, change or turn off SFTP roster sync, or approve a run that stopped because it would turn off too many people, needs Manage integrations (
integrations.view) and Add people, and a role that reaches the whole account. A roster file changes people in every school.
If something doesn't look right#
- A row is flagged for its location. The name in your file has to match a location's name. Check Admin › Locations › Locations for the spelling.
- People landed at the wrong school. They had no Location Name, so they went to the default location. Importing again won't move them, because an import doesn't change the home location of people who already exist. On Admin › People › Users, sort by Location to group them, tick the ones at the same school, choose Change role… with their current role, and pick the right location in the dialog that opens. Or use Edit in each person's row menu.
- Saving says the SFTP username is already used by another schoolOS account. Each username signs in to one district's folder only, so two districts can't share one, whatever the capitalization. Choose a different username.
- Your district isn't in the ClassLink list, or saving says it's connected to another schoolOS account. The list shows only districts that granted schoolOS access in ClassLink and that schoolOS hasn't confirmed for another account. If your district is connected somewhere it shouldn't be, contact schoolOS support.
- ClassLink sign-in or sync stopped after you changed your ClassLink district. A new pick waits for schoolOS to confirm it, and nothing syncs or signs in with ClassLink until then. See ClassLink: schoolOS confirms your district.
Was this article helpful?
Related articles
- Import your dataOne page to bring your locations, people, assets, tickets and help articles into schoolOS, with how many of each you have. What to import first, file or connection, and whether to bring it in once or keep it in sync.
- Get started with schoolOSThe setup steps for a new account, in order. Which ones are required, which can wait, and what changes with each one.
- UsersThe list of everyone in your account. Search and filter people, choose columns, add someone, change roles and status for many at once, and deactivate or delete.
- Import locationsAdd or update all your schools, buildings and their rooms at once from one CSV. The template, every field, how rows are matched to the locations and rooms you have, and what to do when a row is skipped or rejected.
- Roles and permissionsWhat each built-in role is for, how to change one for your account or put it back, how to make roles of your own, and what every setting in the role editor does.
Updated October 29, 2026
