Student Emails

Provision and manage student email accounts via the REST API.

All student email endpoints require a live API key (nxa_live_...). Test keys are rejected with HTTP 403.

Base URL: https://nexa-ed.com


Create a student email account

Provision a single student email account on your configured email tier.

POST /api/student-emails/create

Warning

Live key required. Test keys (nxa_test_...) cannot deliver real emails and will be rejected with 403 Live API key required for email delivery.

Headers

HeaderRequiredValue
x-api-keyYesnxa_live_...
Content-TypeYesapplication/json

Body

{
  "studentId":     "stu_001",
  "firstName":     "Amara",
  "lastName":      "Obi",
  "tier":          "tier-2-stalwart",
  "domain":        "loretto.edu.ng",
  "gradeLevel":    "JSS2",
  "recoveryEmail": "[email protected]"
}
FieldTypeRequiredDescription
studentIdstringYesYour internal student identifier
firstNamestringYesStudent's first name
lastNamestringYesStudent's last name
tierstringYes"tier-1-nexa" | "tier-2-stalwart" | "tier-3-google"
domainstringYesEmail domain, e.g. "loretto.edu.ng"
emailstringNoOverride auto-generated address
gradeLevelstringNoe.g. "JSS2", "SS3"
recoveryEmailstringNoParent/guardian recovery address

Response 200 OK

{
  "email":             "[email protected]",
  "temporaryPassword": "Tr9x#K2m",
  "providerUserId":    "stw_user_abc123",
  "tier":              "tier-2-stalwart"
}

Example (cURL)

curl -X POST https://nexa-ed.com/api/student-emails/create \
  -H "x-api-key: nxa_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "studentId": "stu_001",
    "firstName": "Amara",
    "lastName":  "Obi",
    "tier":      "tier-2-stalwart",
    "domain":    "loretto.edu.ng"
  }'

Example (Python)

import requests
 
resp = requests.post(
    "https://nexa-ed.com/api/student-emails/create",
    headers={"x-api-key": "nxa_live_..."},
    json={
        "studentId": "stu_001",
        "firstName": "Amara",
        "lastName":  "Obi",
        "tier":      "tier-2-stalwart",
        "domain":    "loretto.edu.ng",
    },
)
account = resp.json()
print(account["email"], account["temporaryPassword"])

Bulk provision accounts

Provision up to 500 student accounts in a single request. Processing happens asynchronously — poll /api/student-emails/status with the returned jobId.

POST /api/student-emails/bulk

Headers

HeaderRequiredValue
x-api-keyYesnxa_live_... or nxa_test_...
Content-TypeYesapplication/json

Body

{
  "students": [
    { "studentId": "stu_001", "firstName": "Amara",  "lastName": "Obi"     },
    { "studentId": "stu_002", "firstName": "Chidi",  "lastName": "Eze"     },
    { "studentId": "stu_003", "firstName": "Ngozi",  "lastName": "Adeyemi" }
  ],
  "tier":   "tier-2-stalwart",
  "domain": "loretto.edu.ng"
}

Response 202 Accepted

{
  "jobId":         "job_a1b2c3",
  "tier":          "tier-2-stalwart",
  "totalStudents": 3,
  "message":       "Bulk provisioning job started. Poll /api/student-emails/status?jobId=job_a1b2c3 for progress."
}

Poll the jobId using Get job status every 3–5 seconds until status is "completed" or "failed".


Get job status

Check the progress of a bulk provisioning job.

GET /api/student-emails/status?jobId=job_a1b2c3

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key

Response 200 OK

{
  "jobId":          "job_a1b2c3",
  "status":         "completed",
  "type":           "bulk-create",
  "totalStudents":  3,
  "processedCount": 3,
  "successCount":   3,
  "failedCount":    0,
  "results": [
    { "studentId": "stu_001", "email": "[email protected]",   "status": "success" },
    { "studentId": "stu_002", "email": "[email protected]",   "status": "success" },
    { "studentId": "stu_003", "email": "[email protected]", "status": "success" }
  ],
  "createdAt":    1743000000000,
  "startedAt":    1743000001000,
  "completedAt":  1743000012000
}

status values: "pending" | "processing" | "completed" | "failed"


List accounts

List student email accounts for your tenant.

GET /api/student-emails/list

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key

Query params

ParamTypeDefaultDescription
statusstring—Filter: "active" | "suspended" | "deleted"
limitnumber100Max results (1–500)

Response 200 OK

{
  "accounts": [
    {
      "email":                 "[email protected]",
      "studentId":             "stu_001",
      "firstName":             "Amara",
      "lastName":              "Obi",
      "status":                "active",
      "provider":              "stalwart",
      "providerUserId":        "stw_user_abc123",
      "passwordResetRequired": false,
      "createdAt":             1743000000000,
      "updatedAt":             1743000000000
    }
  ],
  "total": 1
}

Suspend an account

Disable a student's email login without deleting their mailbox.

POST /api/student-emails/suspend

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key
Content-TypeYesapplication/json

Body

{ "email": "[email protected]" }

Response 200 OK

{ "success": true, "email": "[email protected]", "status": "suspended" }

Restore an account

Re-enable a suspended student account.

POST /api/student-emails/restore

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key
Content-TypeYesapplication/json

Body

{ "email": "[email protected]" }

Response 200 OK

{ "success": true, "email": "[email protected]", "status": "active" }

Reset password

Generate a new temporary password for a student account.

POST /api/student-emails/reset-password

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key
Content-TypeYesapplication/json

Body

{ "email": "[email protected]" }

Response 200 OK

{
  "email":             "[email protected]",
  "temporaryPassword": "Wk8@Lm3z"
}

Share the temporary password securely with the student. They will be prompted to change it on first login.


Error responses

StatusCodeMeaning
401unauthorizedMissing or invalid x-api-key
403live-key-requiredTest key used on an endpoint that requires a live key
403live-key-not-activatedLive key exists but domain not yet verified
404not-foundEmail account does not exist
409email-existsAn account with that address already exists
422validation-errorMissing required fields
429rate-limitedToo many requests — see Retry-After header

What's next

On this page