Roster, Assignments & Activity API
Keep your own systems in step with PrepareBuddy: who your students are, what is assigned to them, how active they are — and assign work automatically. New to APIs? Start with the API Quick Start.
Base address: https://www.preparebuddy.com/api/v1/ · Header on every request: X-API-Key: <your-key>
| Method & path | Key needed | Use it for |
|---|---|---|
GET /students/ |
read-only or full | Your whole roster: who, their access, their courses. |
GET /catalog/ |
read-only or full | Everything you can assign: language tests, quizzes, assessments — with their ids. |
GET /assignments/ |
read-only or full | What is assigned to whom, its status, due date — and the result it produced. |
POST /assignments/ |
full | Assign a test, quiz or assessment to a student. |
GET /activity/daily/ |
read-only or full | Engagement: time on the platform, tests started/finished, per student per day. |
Paging (every list): the first call returns up to limit rows plus has_more and next_cursor. While
has_more is true, call again adding cursor=<next_cursor>. Store the last next_cursor to continue later.
Times: timestamps are in UTC (+00:00). Add tz=Asia/Kolkata (any zone name such as Europe/London,
America/New_York) to get them in local time instead.
GET /students/ — your roster
Every student of your organization: people with the student role, and anyone enrolled in one of your courses. Staff are not listed.
curl -H "X-API-Key: YOUR_KEY" "https://www.preparebuddy.com/api/v1/students/?status=active&limit=100"
| Parameter | Meaning |
|---|---|
status |
active (a student with access now) or inactive (left, or access ended). Default: both. |
course_id |
Only students enrolled in this course (ids from GET /courses/). |
tz, limit (1–500, default 100), cursor |
See above. |
{
"status": "ok", "count": 1, "has_more": false, "next_cursor": "WzgxMl0",
"students": [{
"user_id": 812, "email": "asha.rao@uni.example", "first_name": "Asha", "last_name": "Rao",
"has_set_password": true, "joined_at": "2026-08-01T09:12:00+00:00", "last_login": "2026-09-27T08:00:00+00:00",
"membership": {"role": "member", "status": "active"},
"enrollments": [{"course_id": 31, "course_name": "IELTS Batch A", "course_type": "ielts", "status": "active",
"start_date": "2026-08-01", "end_date": "2026-10-31", "grace_period_end": "2026-11-07",
"has_access": true}]
}]
}
has_access— can the student use PrepareBuddy for that course today (including any grace period).has_set_password—falsemeans they have not signed in with a password yet (e.g. only from an LMS).
To look up one student, keep using GET /students/?email=… (API Reference).
GET /catalog/ — what you can assign
curl -H "X-API-Key: YOUR_KEY" "https://www.preparebuddy.com/api/v1/catalog/?kind=quiz"
kind is optional: test, quiz, assessment (comma-separate several).
{
"status": "ok", "count": 2,
"items": [
{"kind": "test", "item_id": 57, "title": "IELTS Academic Mock 3", "type": "ielts", "type_label": "IELTS",
"max_score": 9.0, "lti_link": "https://www.preparebuddy.com/lti/test/57/"},
{"kind": "quiz", "item_id": 88, "title": "Grammar check 4", "type": "quiz", "type_label": "Quiz · 20 questions",
"max_score": 100.0, "lti_link": "https://www.preparebuddy.com/lti/quiz/88/"}
]
}
Use kind + item_id with POST /assignments/. lti_link is the address for an LMS (LTI 1.1) link.
POST /assignments/ — assign work (full-access key)
Assign one test, quiz or assessment to one student — for example, when someone buys a mock test.
curl -X POST https://www.preparebuddy.com/api/v1/assignments/ \
-H "X-API-Key: YOUR_FULL_ACCESS_KEY" -H "Content-Type: application/json" \
-d '{"email": "asha.rao@uni.example", "kind": "test", "item_id": 57, "due_date": "2026-10-31"}'
| Field | Required | Meaning |
|---|---|---|
email or user_id |
yes | The student. They must already be a student of your organization with access — onboard them first (Complete Onboarding Walkthrough). |
kind |
yes | test, quiz or assessment. |
item_id |
yes | From GET /catalog/. |
due_date |
no | 2026-10-31 (= end of that day) or an exact time 2026-10-31T18:00:00+05:30. |
notify |
no | false to skip the in-app "you have a new test" notice/email for language tests (default true). |
Answer — assigned now (201):
{
"status": "ok", "created": true,
"assignment": {"id": "test-assignment:1f2e9c4a-…", "kind": "test",
"student": {"user_id": 812, "email": "asha.rao@uni.example", "first_name": "Asha", "last_name": "Rao"},
"item": {"id": 57, "title": "IELTS Academic Mock 3", "type": "ielts"},
"status": "pending", "overdue": false, "assigned_at": "2026-09-27T10:00:00+00:00",
"due_date": "2026-10-31T18:29:59+00:00", "completed_at": null, "result_id": null}
}
Answer — already assigned (200, "created": false): the student already has that work open, so the
existing assignment is returned and nothing new is created. It is safe to repeat a call (a retried
automation never assigns twice).
| Error | Why |
|---|---|
403 read-only |
Use a full-access key. |
404 student |
Not a student of your organization. |
404 item |
Wrong item_id, or not yours — check GET /catalog/. |
409 |
The student exists but currently has no access. |
GET /assignments/ — what is assigned
curl -H "X-API-Key: YOUR_KEY" "https://www.preparebuddy.com/api/v1/assignments/?status=overdue&tz=Asia/Kolkata"
| Parameter | Meaning |
|---|---|
status |
open (not finished), completed, or overdue (past due, not finished). |
kind |
test, quiz, assessment. |
email / user_id / course_id |
Narrow to students. |
since |
Only assignments made on/after this date (e.g. 2026-09-01). |
tz, limit (1–500), cursor |
See the top of this page. |
Each row is the same object POST /assignments/ returns. status is pending, in_progress, submitted
(an assessment handed in, awaiting marking), completed, or the assignment's own state such as expired.
result_id matches the id in GET /results/ and in the result.final webhook — use it to
join an assignment to its score.
GET /activity/daily/ — engagement
One row per student per day they were active, from PrepareBuddy's attendance register.
curl -H "X-API-Key: YOUR_KEY" "https://www.preparebuddy.com/api/v1/activity/daily/?from=2026-09-01&to=2026-09-30"
| Parameter | Meaning |
|---|---|
from, to |
Dates (default: the last 30 days; at most 366 days per call). |
email / user_id / course_id |
Narrow to students. |
tz |
Writes first_seen_at / last_seen_at in your zone. |
limit (1–1000, default 500), cursor |
Paging. |
{
"status": "ok", "from": "2026-09-01", "to": "2026-09-30", "day_timezone": "Asia/Kolkata",
"count": 1, "has_more": false, "next_cursor": "…",
"days": [{
"student": {"user_id": 812, "email": "asha.rao@uni.example", "first_name": "Asha", "last_name": "Rao"},
"date": "2026-09-26", "first_seen_at": "2026-09-26T03:10:00+00:00", "last_seen_at": "2026-09-26T05:02:00+00:00",
"visits": 2, "active_minutes": 74, "page_views": 58, "tests_started": 1, "tests_completed": 1
}]
}
dateis a calendar day inday_timezone(the platform's register, India Standard Time).tzchanges how the times are written, not which day a row belongs to.- A day with no activity has no row. The register is compiled once a day: yesterday is complete, today appears tomorrow.
For scores per day, use GET /progress/daily/.
