Events API
The Events API ingests Caliper v1p2 learning events from your application. Events are send-only — use the Analytics API and XP API to read back processed data.
All endpoints require Authorization: Bearer <token> and scope events.write.
Base prefix: https://api.alpha-1edtech.ai/events/1.0
POST /events/1.0/
Submit a Caliper event.
Ingest a Caliper v1p2 event for processing. Send one event per POST. Accepts either a bare Caliper v1p2 event (a single JSON object with @context and type) or a Caliper envelope ({ sensor, sendTime, dataVersion, data: [...] }). SessionEvent payloads (type: "SessionEvent") with actions LoggedIn, LoggedOut, or TimedOut are handled synchronously to create/close sessions. All other event types are enqueued for asynchronous processing and return 202.
Scope: events.write
Supported event types
| Event Type | Actions | Processing |
|---|---|---|
GradeEvent | Graded | Processed — creates assessment results, line items, and analytics facts |
AssessmentItemEvent | Started, Skipped, Completed | Processed when action is Completed; others acknowledged |
AssessmentEvent | Started, Paused, Resumed, Restarted, Submitted | Processed — records assessment lifecycle |
AssignableEvent | Activated, Deactivated, Started, Completed, Submitted, Reviewed | Processed — records assignment lifecycle |
ViewEvent | Viewed | Processed — records resource views |
SessionEvent | LoggedIn, LoggedOut, TimedOut | Synchronous — creates/closes sessions (HTTP 200) |
Common fields
Every event must include:
| Field | Type | Required | Description |
|---|---|---|---|
@context | string | yes | Must contain "caliper" (use http://purl.imsglobal.org/ctx/caliper/v1p2) |
id | string | yes | Unique event ID as URN (e.g., urn:uuid:...) |
type | string | yes | Caliper event type |
actor | object | yes | Who performed the action — { "id": "...", "type": "Person" } for student actions; { "id": "...", "type": "SoftwareApplication" } for GradeEvent and TimedOut |
action | string | yes | Event action |
object | object | yes | The thing acted upon — always a full entity object |
generated | object | varies | Result entity (Score, Attempt, Response) — required for GradeEvent |
eventTime | string | yes | ISO 8601 timestamp |
edApp | object | no | Your app as a SoftwareApplication object with @context, id, and type |
extensions | object | yes | Must include { "subject": "..." } — the academic subject for this event |
session | string or object | no | Session entity, or "urn:tag:auto-attach" to use the student's active session |
Response
200 OK—SessionEventprocessed synchronously:{ "status": "created", "sessionId": "..." }or{ "status": "closed", "sessionId": "...", "durationInSeconds": ... }202 Accepted—{ "status": "accepted", "eventCount": 1 }400 Bad Request— Invalid event payload
GradeEvent examples
scoreType: QUESTION_RESULT
Report the result of a single question attempt. The attempt.id must match the one from the corresponding AssessmentItemEvent.Completed.
{
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "urn:uuid:event-unique-id",
"type": "GradeEvent",
"profile": "GradingProfile",
"actor": {
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "https://api.alpha-1edtech.ai/applications/1.0/your-app",
"type": "SoftwareApplication"
},
"action": "Graded",
"object": {
"id": "https://vendor.example.com/attempts/question-attempt-123",
"type": "Attempt",
"count": 1,
"assignee": {
"id": "https://api.alpha-1edtech.ai/rostering/1.0/users/student-123",
"type": "Person"
},
"assignable": {
"id": "https://vendor.example.com/questions/fraction-addition-q1",
"type": "DigitalResource",
"mediaType": "application/json",
"isPartOf": {
"id": "https://vendor.example.com/collections/fractions-quiz",
"type": "DigitalResourceCollection"
}
},
"extensions": { "activityName": "Fraction Addition Question 1" }
},
"generated": {
"id": "https://vendor.example.com/scores/score-qr-123",
"type": "Score",
"attempt": "https://vendor.example.com/attempts/question-attempt-123",
"maxScore": 1,
"scoreGiven": 1,
"extensions": { "scoreType": "QUESTION_RESULT" }
},
"eventTime": "2026-01-15T10:07:30.000Z",
"edApp": {
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "https://api.alpha-1edtech.ai/applications/1.0/your-app",
"type": "SoftwareApplication"
},
"extensions": {
"subject": "Math",
"course": { "id": "https://api.alpha-1edtech.ai/rostering/1.0/courses/COURSE_SOURCED_ID" }
},
"session": "urn:tag:auto-attach"
}
scoreType: XP
Award experience points for an activity.
{
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "urn:uuid:event-unique-id",
"type": "GradeEvent",
"profile": "GradingProfile",
"actor": {
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "https://api.alpha-1edtech.ai/applications/1.0/your-app",
"type": "SoftwareApplication"
},
"action": "Graded",
"object": {
"id": "https://vendor.example.com/attempts/xp-attempt-123",
"type": "Attempt",
"assignee": {
"id": "https://api.alpha-1edtech.ai/rostering/1.0/users/student-123",
"type": "Person"
},
"extensions": { "activityName": "Fractions Practice Session" }
},
"generated": {
"id": "https://vendor.example.com/scores/score-xp-123",
"type": "Score",
"attempt": "https://vendor.example.com/attempts/xp-attempt-123",
"scoreGiven": 150,
"extensions": { "scoreType": "XP" }
},
"eventTime": "2026-01-15T14:30:00.000Z",
"edApp": {
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "https://api.alpha-1edtech.ai/applications/1.0/your-app",
"type": "SoftwareApplication"
},
"extensions": {
"subject": "Math",
"course": { "id": "https://api.alpha-1edtech.ai/rostering/1.0/courses/COURSE_SOURCED_ID" }
},
"session": "urn:tag:auto-attach"
}
scoreType: MASTERY
Record mastery of a curriculum standard or content unit.
{
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "urn:uuid:event-unique-id",
"type": "GradeEvent",
"profile": "GradingProfile",
"actor": {
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "https://api.alpha-1edtech.ai/applications/1.0/your-app",
"type": "SoftwareApplication"
},
"action": "Graded",
"object": {
"id": "https://vendor.example.com/attempts/mastery-attempt-123",
"type": "Attempt",
"assignee": {
"id": "https://api.alpha-1edtech.ai/rostering/1.0/users/student-123",
"type": "Person"
},
"assignable": {
"id": "https://vendor.example.com/standards/fractions-basics",
"type": "AssignableDigitalResource",
"mediaType": "curriculum/standard",
"name": "Basic Fractions Understanding"
},
"extensions": { "activityName": "Basic Fractions Mastery" }
},
"generated": {
"id": "https://vendor.example.com/scores/score-mastery-123",
"type": "Score",
"attempt": "https://vendor.example.com/attempts/mastery-attempt-123",
"maxScore": 100,
"scoreGiven": 100,
"extensions": { "scoreType": "MASTERY" }
},
"eventTime": "2026-01-15T14:30:00.000Z",
"edApp": {
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "https://api.alpha-1edtech.ai/applications/1.0/your-app",
"type": "SoftwareApplication"
},
"extensions": {
"subject": "Math",
"course": { "id": "https://api.alpha-1edtech.ai/rostering/1.0/courses/COURSE_SOURCED_ID" }
},
"session": "urn:tag:auto-attach"
}
SessionEvent examples
LoggedIn — create a session
Returns { "status": "created", "sessionId": "..." }.
{
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "urn:uuid:f6a7b8c9-d0e1-2345-f012-678901234567",
"type": "SessionEvent",
"profile": "SessionProfile",
"actor": {
"id": "https://api.alpha-1edtech.ai/rostering/1.0/users/student-123",
"type": "Person"
},
"action": "LoggedIn",
"object": {
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "https://api.alpha-1edtech.ai/applications/1.0/your-app",
"type": "SoftwareApplication"
},
"eventTime": "2026-02-26T15:00:00Z",
"edApp": {
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "https://api.alpha-1edtech.ai/applications/1.0/your-app",
"type": "SoftwareApplication"
},
"extensions": { "subject": "Math" },
"session": {
"id": "https://vendor.example.com/sessions/session-123",
"type": "Session",
"startedAtTime": "2026-02-26T15:00:00Z",
"extensions": {
"requiresHeartbeat": true,
"processInsights": false
}
}
}
LoggedOut — close a session
Returns { "status": "closed", "sessionId": "...", "durationInSeconds": 3600 }.
curl -X POST https://api.alpha-1edtech.ai/events/1.0/ \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{ "@context": "http://purl.imsglobal.org/ctx/caliper/v1p2", "id": "urn:uuid:...", "type": "GradeEvent", "action": "Graded", "actor": { "id": "...", "type": "SoftwareApplication" }, "object": { "id": "...", "type": "Attempt", "assignee": { "id": "https://api.alpha-1edtech.ai/rostering/1.0/users/student-123", "type": "Person" } }, "generated": { "id": "...", "type": "Score", "scoreGiven": 85, "maxScore": 100, "extensions": { "scoreType": "QUESTION_RESULT" } }, "eventTime": "2026-01-15T10:07:30.000Z", "extensions": { "subject": "Math" }, "session": "urn:tag:auto-attach" }'
POST /events/1.0/sessions/:sessionId/heartbeat
Extend a session's endedAtTime to indicate the student is still active. Only works for sessions created with requiresHeartbeat: true.
Scope: events.write
Path params
| Name | Description |
|---|---|
sessionId | Session UUID |
Request body
{
"eventTime": "2026-02-26T15:05:00Z"
}
| Field | Type | Required | Description |
|---|---|---|---|
eventTime | string (ISO 8601) | yes | Timestamp of the heartbeat |
Response
200 OK — { "status": "ok", "sessionId": "...", "endedAtTime": "..." }
404 — Session not found.
Example
curl -X POST "https://api.alpha-1edtech.ai/events/1.0/sessions/SESSION_UUID/heartbeat" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{ "eventTime": "2026-02-26T15:05:00Z" }'
POST /events/1.0/heartbeat
Partner-friendly alias for POST /events/1.0/sessions/{sessionId}/heartbeat. Pass sessionId either in the JSON body alongside eventTime or as a ?sessionId=... query parameter. Behaviour and response shape are identical to the per-session form. Only works for sessions created with requiresHeartbeat: true.
Scope: events.write
Query params
| Name | Description | Required |
|---|---|---|
sessionId | Session UUID (alternative to passing it in the body) | no |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
sessionId | string | no | Session UUID (alternative to ?sessionId=...) |
eventTime | string (ISO 8601) | yes | Timestamp of the heartbeat |
Response
200 OK — { "status": "ok", "sessionId": "...", "endedAtTime": "..." }
400 Bad Request — Missing sessionId (provide in body or as ?sessionId=...).
404 — Session not found.
Example
curl -X POST "https://api.alpha-1edtech.ai/events/1.0/heartbeat" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"sessionId": "SESSION_UUID",
"eventTime": "2026-02-26T15:05:00Z"
}'