Course Feed API
The Course Feed API lets a course, class or academy send a student's progress to the student's parents in JarSave: classes attended, lessons completed, term reports, certificates and badges. Every course uses the same API, so a course connects once and every family that asks is covered.
You only make calls to JarSave. You host nothing, and you need no parent portal or OAuth server.
- A parent opens JarSave and gets a one-time link code for their child.
- The parent gives the code to you, in your student portal or to your admin.
- You create a link with the code and your student number. The parent confirms it in JarSave.
- You send the student's past items once, then each new item as it happens.
- The parent approves each item in JarSave. Nothing reaches the child's record without that tap.
The API accepts and returns JSON over HTTPS. Times are ISO 8601 with an offset; dates are YYYY-MM-DD.
Base URL
https://api.jarsave.com/v1Not a developer?
Forward this page to the person who runs your learning system. Keys are in the dashboard; questions go to support@jarsave.com.
Authentication
Each course has two secret keys: a sandbox key that starts with sk_test_ and a live key that starts with sk_live_. Send the key as a bearer token on every request, with the API version you built against.
Sign up in the dashboard with your work email and your sandbox key is there at once. A sandbox key reaches only test students: the dashboard's Test family plays the parent. A live key is issued after one test link works end to end and JarSave has checked the business behind the course.
Keep keys on your server. A key in an app or a web page can be copied, and anything sent with it would carry your course's name. The examples on this page read it from JARSAVE_SECRET_KEY, an environment variable on your server.
Authenticated request
curl https://api.jarsave.com/v1/links/lnk_8Gm2QxT4 \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29"Errors
JarSave answers with a standard HTTP status. A 2xx means the item was received. A 4xx means something in the request needs fixing, and the body says what. A 5xx is on our side: retry later with the same request.
| Status | Meaning |
|---|---|
| 200, 201 | Received. 201 when the object is new, 200 when it replaced one with the same id. |
| 400 | A field is missing or invalid. error.field names it. |
| 401 | The key is missing, wrong or revoked. |
| 404 | No link with that id belongs to your course. |
| 409 | The link is still waiting for the parent to confirm it. Send the item again later. |
| 410 | The link was revoked. Stop sending for this student. |
| 429 | Too many requests. Wait for the seconds in Retry-After. |
| 500, 503 | Something failed at JarSave. Retry with backoff. |
Error response
{
"error": {
"type": "invalid_request",
"field": "study_hours",
"message": "study_hours must be a number of hours, for example 20."
}
}Idempotent requests
Every item you send carries your own id for it: session_id, lesson_id, report_id, certificate_no or badge_id. Sending the same id again for the same link never creates a second item, so a retry after a timeout is always safe.
If the body has changed, JarSave treats it as a correction: it replaces the item and shows the parent what changed.
Good to know
Ids are unique per course and per kind of item. Use the ids your system already has; JarSave does not need new ones.
Versioning
Send JarSave-Version with the date of the version you built against. The current version is 2026-10-29.
New optional fields can appear in any version. A change that could break an integration comes as a new dated version, and requests that send the old date keep the old behaviour.
Header
JarSave-Version: 2026-10-29The link object
v1A link joins one of your students to one child in JarSave. Every item you send goes to a link. The parent starts it with a code, confirms it, and can end it at any time; so can you.
Attributes
id string
Unique identifier for the link, starting with lnk_.
object string, value is "link"
The object's type.
student_id string
Your student number, as you sent it.
student_name string
The student's full name as your reports and certificates print it.
status enum
pending until the parent confirms, then active. revoked once either side ends it.
created timestamp
When you created the link.
confirmed_at timestamp, nullable
When the parent confirmed it in JarSave.
revoked_at timestamp, nullable
When the link ended.
revoked_by enum, nullable
parent or course.
The link object
{
"id": "lnk_8Gm2QxT4",
"object": "link",
"student_id": "STD-1024",
"student_name": "Ayu Lestari Putri",
"status": "active",
"created": "2026-11-20T15:04:11+07:00",
"confirmed_at": "2026-11-20T15:06:40+07:00",
"revoked_at": null,
"revoked_by": null
}Create a link
POST/v1/links
Turns the parent's one-time code into a link. The code is 8 characters, works once and expires 24 hours after JarSave shows it. JarSave then asks the parent to confirm that this student, at your course, is their child. The link is pending until they do.
In the sandbox, make codes with Make a test link code in the dashboard, and confirm the link there with Confirm as parent.
Parameters
code string Required
The one-time code the parent gave you, for example K7PM-Q2XD. Dashes and case do not matter.
student_id string Required
Your student number. Items name the student by the link, not by this number.
student_name string Required
The full name as printed on your reports and certificates. The parent sees it when confirming.
Returns
The link object, with status pending. A code that is wrong, used or expired returns 400 with error.field set to code.
Request
curl https://api.jarsave.com/v1/links \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29" \
-H "Content-Type: application/json" \
-d '{"code": "K7PM-Q2XD", "student_id": "STD-1024", "student_name": "Ayu Lestari Putri"}'Response
{
"id": "lnk_8Gm2QxT4",
"object": "link",
"student_id": "STD-1024",
"student_name": "Ayu Lestari Putri",
"status": "pending",
"created": "2026-11-20T15:04:11+07:00",
"confirmed_at": null,
"revoked_at": null,
"revoked_by": null
}Retrieve a link
GET/v1/links/:id
Returns the link, so you can see whether the parent has confirmed it or ended it. Check it before sending a batch of past items.
Returns
The link object, or 404 if no link with that id belongs to your course.
Request
curl https://api.jarsave.com/v1/links/lnk_8Gm2QxT4 \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29"Revoke a link
DELETE/v1/links/:id
Ends the link, for example when the student leaves your course. Items sent afterwards return 410. When the parent ends a link in JarSave, your next request for it returns 410 too.
Returns
The link object, with status revoked and revoked_by set to course.
Request
curl -X DELETE https://api.jarsave.com/v1/links/lnk_8Gm2QxT4 \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29"The attendance object
v1One class session and whether the student came. Send one for every session on the student's timetable, including absences, so the parent sees the whole term. In JarSave a session the child attended counts as a practice day for that subject.
Attributes
session_id string Required
Your id for this session. Sending it again replaces the item (see idempotent requests).
course_id string Required
Your id for the course.
course_name string Required
The course as the parent knows it, for example Junior Coding 2.
subject string Required
What the course teaches, in one or two words: Coding, English, Piano.
starts_at timestamp Required
When the session started, with its offset, for example 2026-11-26T15:00:00+07:00.
ends_at timestamp Required
When it ended.
mode enum Required
in_person or online.
status enum Required
present, late, absent or excused.
meeting_no integer, nullable
The session's number in the course, for example 14 of 21.
The attendance object
{
"session_id": "ses_55120",
"course_id": "crs_junior_coding_2",
"course_name": "Junior Coding 2",
"subject": "Coding",
"starts_at": "2026-11-26T15:00:00+07:00",
"ends_at": "2026-11-26T16:30:00+07:00",
"mode": "in_person",
"status": "present",
"meeting_no": 6
}Send attendance
POST/v1/links/:id/attendance
Send each session once attendance is taken, the same day. For the history, send the past sessions of the current course when the link becomes active.
Parameters
The attendance object's attributes. To send up to 100 at once, put them in an items array.
Returns
The item with its JarSave id, the link, status pending (waiting for the parent) and received. With items, a list: {"object": "list", "data": [...]}, one entry per item in the order sent.
Request
curl https://api.jarsave.com/v1/links/lnk_8Gm2QxT4/attendance \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29" \
-H "Content-Type: application/json" \
-d @session.jsonResponse
{
"id": "itm_3Rk9Vb2W",
"object": "attendance",
"link": "lnk_8Gm2QxT4",
"session_id": "ses_55120",
"status": "pending",
"received": "2026-11-26T16:41:02+07:00"
}The lesson object
v1A lesson the student finished, with its score when the lesson is graded. In JarSave it shows the parent what the child built or learned that week.
Attributes
lesson_id string Required
Your id for this student's lesson.
course_id string Required
Your id for the course.
course_name string Required
The course as the parent knows it.
lesson_no integer Required
The lesson's number in the course.
title string Required
The lesson's title, for example Make the Robot Dance.
goals array of strings
What the lesson teaches, one short line each, as in your syllabus.
completed_at timestamp Required
When the student finished it.
score integer, nullable
0 to 100, only if the lesson is graded.
project_url string, nullable
A public page of what the student made, if your system has one. No photos of the child.
The lesson object
{
"lesson_id": "les_77031",
"course_id": "crs_junior_coding_2",
"course_name": "Junior Coding 2",
"lesson_no": 3,
"title": "Make the Robot Dance",
"goals": [
"Learn what a loop is",
"Move the robot with a loop"
],
"completed_at": "2026-11-26T16:12:40+07:00",
"score": 86,
"project_url": null
}Send a lesson
POST/v1/links/:id/lessons
Send a lesson when the student finishes it. Send one item per lesson, not one per quiz attempt: if the score changes later, send the same lesson_id again.
Parameters
The lesson object's attributes, or up to 100 of them in an items array.
Returns
The item with its JarSave id, link, status and received. With items, a list: {"object": "list", "data": [...]}, one entry per item in the order sent.
Request
curl https://api.jarsave.com/v1/links/lnk_8Gm2QxT4/lessons \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29" \
-H "Content-Type: application/json" \
-d @lesson.jsonResponse
{
"id": "itm_7Ha1Lc0P",
"object": "lesson",
"link": "lnk_8Gm2QxT4",
"lesson_id": "les_77031",
"status": "pending",
"received": "2026-11-26T16:12:44+07:00"
}The term report object
v1The report a teacher writes at the end of a term or a block of meetings. Send its scores and teacher notes as fields, not only inside the PDF: JarSave reads them to give the parent ideas for helping at home.
Attributes
report_id string Required
Your id for this report.
course_id string Required
Your id for the course.
course_name string Required
The course as the parent knows it.
period_start date Required
The first day the report covers.
period_end date Required
The last day it covers.
meeting_from integer, nullable
The first meeting it covers, for example 14.
meeting_to integer, nullable
The last meeting it covers, for example 21.
issued_on date Required
The day the report was published.
criteria array of objects Required
One row per criterion the teacher assessed.
Show child attributes
name string Required
The criterion, for example Coding Concept & Practice.
score integer, nullable Required
0 to 100, or null if the criterion has only a grade.
grade string Required
The grade as printed, for example A.
teacher_note string Required
The teacher's words for this criterion, unedited.
lessons array of objects
The lesson scores the report lists.
Show child attributes
meeting_no integer Required
The meeting the lesson was in.
title string Required
The lesson's title.
score integer Required
0 to 100.
grade string Required
The grade as printed.
grading_scale array of objects Required
Your grades and what they mean, so the parent can read them.
Show child attributes
grade string Required
For example A.
min integer Required
The lowest score for this grade.
max integer Required
The highest score for this grade.
label string Required
For example Very Good.
summary object
Totals for the period, as the report prints them: hours, projects, skills_gained.
signed_by object Required
Who signed the report: name and role, for example Head of Teachers.
file_url string Required
The report as PDF. See files.
The term report object
{
"report_id": "rpt_20931",
"course_id": "crs_junior_coding_2",
"course_name": "Junior Coding 2",
"period_start": "2026-09-03",
"period_end": "2026-10-22",
"meeting_from": 1,
"meeting_to": 7,
"issued_on": "2026-10-29",
"criteria": [
{
"name": "Coding Concept & Practice",
"score": 92,
"grade": "A",
"teacher_note": "Uses loops with confidence and explains them in her own words."
}
],
"lessons": [
{ "meeting_no": 3, "title": "Make the Robot Dance", "score": 86, "grade": "A" }
],
"grading_scale": [
{ "grade": "A", "min": 86, "max": 100, "label": "Very Good" },
{ "grade": "B", "min": 75, "max": 85, "label": "Good" }
],
"summary": { "hours": 10.5, "projects": 4, "skills_gained": 3 },
"signed_by": { "name": "Dewi Anggraini", "role": "Head of Teachers" },
"file_url": "https://files.academy.example/r/20931.pdf?sig=..."
}Send a term report
POST/v1/links/:id/reports
Send a report on the day you publish it to families. For the history, send every report of the student's courses so far when the link becomes active.
Parameters
The term report object's attributes, one report per request.
Returns
The item with its JarSave id, link, status and received.
Request
curl https://api.jarsave.com/v1/links/lnk_8Gm2QxT4/reports \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29" \
-H "Content-Type: application/json" \
-d @report.jsonResponse
{
"id": "itm_2Wd8Ms5N",
"object": "report",
"link": "lnk_8Gm2QxT4",
"report_id": "rpt_20931",
"status": "pending",
"received": "2026-10-29T10:20:15+07:00"
}The certificate object
v1The certificate a student gets for finishing a course or passing a level. In JarSave it becomes a lasting entry in the child's record, so send the file the family would print, and a page that proves it is real.
Attributes
certificate_no string Required
The number printed on the certificate. It is the item's id.
course_id string Required
Your id for the course.
course_name string Required
The course or level as printed, for example Junior Coding 2.
subject string Required
What the course teaches, in one or two words: Coding, English, Piano.
level string, nullable
The level as printed, for example Level 2 or A2 Flyers.
started_on date Required
The first day of the course.
completed_on date Required
The day the student finished it.
issued_on date Required
The date printed on the certificate.
study_hours number Required
The course's teaching hours, as you publish them, for example 20.
final_grade string, nullable
The overall grade, only if the certificate prints one.
rank string, nullable
A place or distinction, only if the certificate prints one, for example 1st place.
issuer string Required
The course provider's legal name, as printed.
file_url string Required
The certificate as PDF or PNG. See files.
verify_url string, nullable
A public page on your site that confirms this certificate. A course that issues verifiable digital badges can send that badge's link.
The certificate object
{
"certificate_no": "EXA-2026-004517",
"course_id": "crs_junior_coding_2",
"course_name": "Junior Coding 2",
"subject": "Coding",
"level": "Level 2",
"started_on": "2026-09-03",
"completed_on": "2027-01-28",
"issued_on": "2027-02-01",
"study_hours": 20,
"final_grade": "A",
"rank": null,
"issuer": "PT Contoh Akademi Digital",
"file_url": "https://files.academy.example/c/004517.pdf?sig=...",
"verify_url": "https://academy.example/verify/EXA-2026-004517"
}Send a certificate
POST/v1/links/:id/certificates
Send a certificate when it is issued. For the history, send every certificate the student already has when the link becomes active.
Parameters
The certificate object's attributes, one certificate per request.
Returns
The item with its JarSave id, link, status and received.
Request
curl https://api.jarsave.com/v1/links/lnk_8Gm2QxT4/certificates \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29" \
-H "Content-Type: application/json" \
-d @certificate.jsonResponse
{
"id": "itm_9Tq4Ze7A",
"object": "certificate",
"link": "lnk_8Gm2QxT4",
"certificate_no": "EXA-2026-004517",
"status": "pending",
"received": "2027-02-01T09:02:31+07:00"
}The badge object
v1A badge or achievement the student earned in your system. Send only badges the student has earned, not the ones still locked.
Attributes
badge_id string Required
Your id for this student's badge.
name string Required
The badge's name, for example 3D Builder.
subject string Required
What it is for, in one or two words, for example Coding.
course_id string, nullable
The course it belongs to, if any.
image_url string Required
The badge picture, PNG or SVG, square, at least 256 pixels. See files.
earned_at timestamp Required
When the student earned it.
The badge object
{
"badge_id": "bdg_3d_builder_1024",
"name": "3D Builder",
"subject": "Coding",
"course_id": "crs_junior_coding_2",
"image_url": "https://files.academy.example/b/3d-builder.png",
"earned_at": "2027-01-28T16:30:00+07:00"
}Send a badge
POST/v1/links/:id/badges
Send a badge when the student earns it, and every earned badge once when the link becomes active.
Parameters
The badge object's attributes, or up to 100 of them in an items array.
Returns
The item with its JarSave id, link, status and received. With items, a list: {"object": "list", "data": [...]}, one entry per item in the order sent.
Request
curl https://api.jarsave.com/v1/links/lnk_8Gm2QxT4/badges \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29" \
-H "Content-Type: application/json" \
-d @badge.jsonFiles
Reports, certificates and badges carry a file link. JarSave downloads the file when it receives the item and keeps its own copy, so a signed link that expires is fine.
- The link must work, without a login, for at least 24 hours after you send the item.
- PDF, PNG, JPEG or SVG, up to 10 MB.
- The file must name the student as
student_namedoes. JarSave declines a file that names a different child and tells the parent why.
Good to know
If a file cannot be downloaded, the item returns 400 with error.field set to file_url. Send it again with a fresh link.
What JarSave does with it
JarSave is a family app: parents reward effort and learning, and their child keeps the record. The data you send is the child's, and the parent decides what happens to it.
- Every item waits for the parent's approval before it reaches the child's record.
- Either side can end a link, and nothing new arrives after that.
- JarSave's assistant reads teacher notes to suggest how the parent can help at home. It receives the child's age only, never the name, school or teacher.
- Data is stored in Singapore.
Not accepted
Send only the fields on this page. JarSave does not take:
Questions
Keys, a test family, or anything on this page: support@jarsave.com.
JarSave is run by PT Nadi Inovasi Nusantara, Indonesia.