For administrators
Faculty Upload API
The Faculty Upload API lets your institution send its faculty roster to Atom Grants as a CSV. Atom stores the file and notifies our team to process the faculty invitations in the same way as a roster uploaded through onboarding.
Before you begin
An Atom administrator must first enable the Faculty Upload API for your organization. Once it is enabled, an organization admin or owner can create and manage keys under Admin > Settings > Faculty Upload API Key.
When creating a key:
- Give it a name that identifies the system or environment using it, such as
Production faculty sync. - Copy the key immediately and store it in a password manager or secrets manager. Atom shows the plaintext key only once and cannot recover it later.
- Pass the key to your integration through a secret environment variable. Do not commit it to source control or include it in the CSV.
Keys begin with atom_sk_. Your organization can have up to five active keys, which allows you to create a new key before revoking an old one during rotation.
Endpoint and authentication
POST https://atomgrants.com/api/faculty-upload
Authorization: Bearer YOUR_API_KEY
The API key identifies your organization. You do not need to send an organization ID or user session.
The maximum request size is 4 MB. The endpoint accepts either:
- a raw CSV request body with
Content-Type: text/csv; or - a multipart request with the CSV in a form field named
file.
CSV format
Include a header row. Name and Email are required; the other template columns are optional.
Name,Email,Department,Job Title,Admin (True/False),Send Invite (True/False)
John Smith,jsmith@university.edu,Computer Science,Professor,True,True
Jane Doe,jdoe@university.edu,Physics,Associate Professor,False,True
| Column | Required | Description |
|---|---|---|
Name | Yes | Faculty member's full name. |
Email | Yes | Faculty member's email address. |
Department | No | Department or organizational unit. |
Job Title | No | Faculty member's title. |
Admin (True/False) | No | Whether the person should be an organization admin. Use True or False. |
Send Invite (True/False) | No | Whether Atom should send the person an invitation. Use True or False. |
Required header matching is case-insensitive and ignores leading or trailing spaces. Empty lines are skipped. The API confirms that the file can be parsed and contains the required headers, but it does not validate every row's email address or values before accepting the upload. Review the roster before sending it.
For safety, cells that could be interpreted as spreadsheet formulas are neutralized before the CSV is stored.
Request examples
curl
curl -X POST https://atomgrants.com/api/faculty-upload \
-H "Authorization: Bearer $ATOM_API_KEY" \
-H "Content-Type: text/csv" \
-H "X-File-Name: faculty.csv" \
--data-binary @faculty.csv
X-File-Name is optional for a raw upload. If omitted, Atom uses faculty.csv.
Python
import os
import requests
with open("faculty.csv", "rb") as csv_file:
response = requests.post(
"https://atomgrants.com/api/faculty-upload",
headers={
"Authorization": f"Bearer {os.environ['ATOM_API_KEY']}",
"Content-Type": "text/csv",
"X-File-Name": "faculty.csv",
},
data=csv_file,
timeout=30,
)
response.raise_for_status()
print(response.json())
Node.js
import { readFile } from "node:fs/promises";
const response = await fetch("https://atomgrants.com/api/faculty-upload", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ATOM_API_KEY}`,
"Content-Type": "text/csv",
"X-File-Name": "faculty.csv",
},
body: await readFile("faculty.csv"),
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());
Multipart upload
When using multipart form data, the file field must be named file. Let the HTTP client set the multipart Content-Type and boundary.
curl -X POST https://atomgrants.com/api/faculty-upload \
-H "Authorization: Bearer $ATOM_API_KEY" \
-F "file=@faculty.csv;type=text/csv"
Responses
A successful request returns HTTP 200:
{
"success": true,
"path": "organization-id/1785942000000-faculty.csv",
"rows": 128
}
rows is the number of parsed data rows. path is Atom's internal storage path and should be treated as an opaque reference.
An HTTP 200 means the CSV was accepted and stored and the Atom team was notified. It does not mean faculty invitations have already been sent. Our team processes the roster after upload.
Errors use a JSON body with an error string:
{
"error": "CSV is missing required column(s): email. Expected columns: Name, Email, Department, Job Title, Admin (True/False), Send Invite (True/False)"
}
| Status | Meaning | What to do |
|---|---|---|
400 | The body is empty, too large, missing the multipart file field, has no data rows, cannot be parsed, or is missing Name or Email. | Correct the file or request before trying again. |
401 | The key is missing, malformed, unknown, or revoked. | Check the Authorization header or create a replacement key. |
403 | Your organization's Faculty Upload API access is disabled. | Contact your Atom administrator. Repeating the request will not help until access is restored. |
500 | Atom could not store or process the request. | Retry with exponential backoff. Contact Atom if failures continue. |
Do not automatically retry 400, 401, or 403 responses. The endpoint does not currently accept an idempotency key. If your integration loses the connection before receiving a response, confirm the outcome with Atom before repeatedly resending the same roster.
Key rotation and revocation
To rotate a key without interrupting an integration:
- Create a second, clearly named key under Admin > Settings.
- Update your integration's secret and make a successful request with the new key.
- Return to Admin > Settings and revoke the old key.
Revocation is immediate and permanent. Requests using a revoked key return 401. If a key is lost or exposed, revoke it and create a new one.