Titel | Event API | ||||||||||||||||||||||
Status |
| ||||||||||||||||||||||
Stadium |
| ||||||||||||||||||||||
Versie | 0.0.1 | ||||||||||||||||||||||
Datum | 17 Mei 2023 | ||||||||||||||||||||||
Auteur | Architectenraad Edu-V | ||||||||||||||||||||||
Acties |
|
De Events API is de technische implementatie van het transactiepatroon Abonneren op wijzigen middels notificaties.
...
Table of Contents |
---|
Samenvatting
Scopes |
| Consent | Conform vereisten van het bericht, zowel met als zonder schoolIdentifier voor controle van instemming door onderwijsinstelling.
|
Producer |
| ||
Consumer |
| ||
Berichten | Event | ||
Endpoints | POST Receive events POST Receive one event POST Request Initial Seed GET Get Events GET Get SchemaVersions |
Berichtdefinitie: Event
Een Event bevat alle informatie ten behoeve van de berichteninfrastructuur om deze als Leverancier correct te kunnen verwerken.
Bij het versturen van Event berichten hanteren we de volgende afspraken:
In het veld data wordt het dataobject waarvoor een event wordt verstuurd opgenomen. Dit is conform het type bericht behorende bij het dataobject. Het type bericht is opgenomen in het veld type en de gehanteerde schemaversie in het veld schemaVersion.
Zodra er meerdere Events tegelijkertijd worden verstuurd dan zijn ze gesorteerd op volgorde van aanmaken (veld created), de oudste events als eerste.
In het Ecosysteem worden Events gestuurd na een gebeurtenis en het aanmaken van een dataobject (bijvoorbeeld een nieuwe, gewijzigde of verwijderde entiteit). Al deze Events dienen te worden verwerkt door de ontvanger.
Ieder Event heeft een eigen unieke identifier id en de identifier van het dataobject objectId.
In het veld created is een tijdstempel opgenomen van de actie die als trigger heeft gediend voor het event. Deze tijdstempel betreft niet het moment van versturen of verwerken van het event. Dit veld kan door de Ontvanger gebruikt worden om berichten op volgorde te verwerken.
Voor het verwijderen van een dataobject kan door de Verzender gebruik gemaakt worden van het veld isDeleteEvent met de waarde True. Het veld data kan in dat geval leeg blijven en alleen het veld objectId is dan verplicht. Dit is tevens het signaal voor de Ontvanger dat er geen verdere berichten meer verstuurd worden voor dit dataobject.
Veld | Type | Format | Omschrijving | Voorbeeld | O/V | Vullingsregel |
id | string | uuid | Unieke identifier voor Event | d290f1ee-6c54-4b01-90e6-d701748f0851 | V |
|
schemaVersion | string | string | Het versienummer van de berichtdefinitie die wordt gehanteerd. | 1.3.0 | V | Conform Semantic Versioning 2.0.0 |
type | string | ENUM | Het type bericht dat via dit Event wordt verstuurd. | Alle Events zoals opgenomen in deze documentatie | V |
|
objectId | string | string | Identifier van het dataobject dat wordt verstuurd in het Event. | - | O | Is verplicht bij isDeleteEvent |
userIdType | string | ENUM | Het type userId dat wordt gehanteerd in het veld objectId, indien het object een user betreft. | ECKiD | O* | Indien het object een Student, Teacher of StudentDelivery betreft, dan wordt hier gespecificeerd welke type userId is gehanteerd als objectId |
created | string | datetime | Tijdstempel van actie die als trigger heeft gediend voor het event | 2017-07-21T17:32:28Z | V |
|
data | object | - | Het dataobject dat conform de bijbehorende berichtdefinitie wordt verstuurd. | - | O | Kan leeg blijven bij isDeleteEvent |
isDeleteEvent | boolean | boolean | Indicatie voor de ontvanger dat dit het laatste bericht is betreffende dit dataobject aangezien deze verwijderd is. | True of False | O |
|
Status- en foutcodes
Status code | Status | statusMessage | Toelichting |
200 | 0 | OK | Bericht succesvol verwerkt |
400 | 1 | Failing event | Schemavalidatie niet succesvol |
400 | 2 | schemaVersion not supported | De ontvanger kan de gehanteerde SchemaVersion niet verwerken |
401 | 3 | scope required | Verzender is niet geautoriseerd voor scope |
403 | 4 | consent required | De gegevenssoort is van classificatie IV. Dit vereist een activering van de gegevensuitwisseling. Dit is in dit foutscenario niet het geval. |
403 | 5 | schoolIdentifier unknown | De Verzender communiceert in de context van een Onderwijsorganisatie die niet bekend is bij Ontvanger |
400 | 99 | Vullingsregel: in statusMessage een beschrijving van de reden opnemen | Overige reden |
Technisch: API specificatie
Open api | ||||
---|---|---|---|---|
| ||||
openapi: 3.0.0
info:
version: 0.0.1
title: Events API
components:
schemas:
schemaVersion:
type: string
description: 'Schema version of this event/object using semantic versioning 2.0.0'
default: 1.3.0
Event:
type: object
x-tags:
- Event
description: |-
An event is a notification that something of interest has happened within a service. A subscriber receives events within an authorized scope and for certain events in the context of a school (using consent). This enables parties to communicate with each other in a loosely coupled way. The event mediator has no direct connection to any of the subscribing systems.
Events are sent after an activity of a Student or Teacher (e.g. usage, progress or results). Events are also sent if an object (e.g. Product, Course, Student, Group) is created, modified or deleted. For the latter category the last version of the object is sent as part of the Event `data` field. All previous events about the same object may be ignored.
All Events have a unique `id`. Moreover, the event also includes an `objectId`, the identifier of the object they carry. This can be used to make sure events are processed in order for that object. The `created` time of the event is the time the action that triggered the event happened. It is not the time the event was sent or processed.
Deleting an object is supported by sending an event with the field `isDeleteEvent` flagged as true. This indicates that this is the last event you will get about this object. The data is empty in this case.
title: Event
properties:
id:
type: string
format: uuid
example: d290f1ee-6c54-4b01-90e6-d701748f0851
description: 'Unique identifier for this Event.'
schemaVersion:
$ref: '#/components/schemas/schemaVersion'
type:
type: string
description: 'The type of Event object sent within this Event message.'
enum:
- la.Product
- la.Course
- la.CourseStructure
- la.InitialActivation
- la.Usage
- la.SimpleProgress
- la.SimpleResult
- mp.Entitlement
- mp.EntitlementConfirmation
- mp.ChangeLicenseStatus
- mp.ChangeLicenseStatusConfirmation
- mp.ActivationCodeRequest
- mp.ActivationCodeConfirmation
- mp.ActivationCodeRevokeRequest
- mp.ActivationCodeRevokeConfirmation
- mp.OrderRequest
- mp.OrderConfirmation
- mp.CreditOrderRequest
- mp.CreditOrderConfirmation
- sis.Student
- sis.StudentDelivery
- sis.Teacher
- sis.Group
- sis.SchoolSubject
- sis.SchoolPeriod
objectId:
type: string
description: 'Unique identifier of the object sent within this event.'
userIdType:
type: string
description: 'In case the object is a Student or Teacher, this field should be filled with the used userId format in the objectId.'
enum:
- ECKiD
- nlPersonProfileId
- nlPersonRealId
- Las-key
- Leerlingnummer
- Medewerkernummer
created:
type: string
format: date-time
description: |
The moment that the action happened which triggered this event. As Events are sent asynchronous, this is not the moment the Event was sent.
Format: openapi in ZULU time as specified in RFC 3339, section 5.6
data:
$ref: '#/components/schemas/EventData'
isDeleteEvent:
type: boolean
description: 'Indication that this is the last event you will ever see, as the object is deleted.'
required:
- id
- schemaVersion
- type
- created
EventData:
title: EventData
description: 'The data object sent in the Event. The `type` field in the Event message specifies the type of data object.'
x-tags:
- Event
oneOf:
- $ref: ./catalogue.v1.yaml#/components/schemas/Product
- $ref: ./course.v1.yaml#/components/schemas/Course
- $ref: ./course.v1.yaml#/components/schemas/CMI5.CourseStructure
- $ref: ./usage.v1.yaml#/components/schemas/InitialActivation
- $ref: ./usage.v1.yaml#/components/schemas/Usage
- $ref: ./progress.v1.yaml#/components/schemas/SimpleProgress
- $ref: ./results.v1.yaml#/components/schemas/SimpleResult
- $ref: ./entitlement.v1.yaml#/components/schemas/EntitlementEvent
- $ref: ./entitlement.v1.yaml#/components/schemas/EntitlementConfirmation
- $ref: ./entitlement.v1.yaml#/components/schemas/ChangeLicenseStatus
- $ref: ./entitlement.v1.yaml#/components/schemas/ChangeLicenseStatusConfirmation
- $ref: ./entitlement.v1.yaml#/components/schemas/ActivationCodeRequest
- $ref: ./entitlement.v1.yaml#/components/schemas/ActivationCodeConfirmation
- $ref: ./entitlement.v1.yaml#/components/schemas/ActivationCodeRevokeRequest
- $ref: ./entitlement.v1.yaml#/components/schemas/ActivationCodeRevokeConfirmation
- $ref: ./order.v1.yaml#/components/schemas/OrderRequest
- $ref: ./order.v1.yaml#/components/schemas/OrderConfirmation
- $ref: ./order.v1.yaml#/components/schemas/CreditOrderRequest
- $ref: ./order.v1.yaml#/components/schemas/CreditOrderConfirmation
- $ref: ./sisdata.v1.yaml#/components/schemas/Student
- $ref: ./sisdata.v1.yaml#/components/schemas/StudentDelivery
- $ref: ./sisdata.v1.yaml#/components/schemas/Teacher
- $ref: ./sisdata.v1.yaml#/components/schemas/Group
- $ref: ./sisdata.v1.yaml#/components/schemas/SchoolSubject
- $ref: ./sisdata.v1.yaml#/components/schemas/SchoolPeriod
nullable: true
EventResponse:
type: object
x-tags:
- Event
description: 'The response for a single Event given by the Consumer that received the Event.'
properties:
id:
type: string
description: 'The identifier of the Event where this response refers to.'
status:
type: integer
description: 'See functional status codes within the Documentation.'
statusMessage:
type: string
description: 'See functional status messages within the Documentation.'
required:
- id
- status
SchemaVersions:
type: object
x-tags:
- SchemaVersion
description: 'The supported schema versions of a specific schema in an api.'
properties:
api:
type: string
description: 'The api where the schema is part of.'
enum:
- 'events-api'
- 'consent-api'
- 'catalogue-api'
- 'course-api'
- 'usage-api'
- 'progress-api'
- 'results-api'
- 'entitlement-api'
- 'order-api'
- 'sis-api'
schema:
type: string
description: 'The schema within the api.'
enum:
# Events API
- Event
- EventResponse
- SchemaVersion
# Consent API
- ConsentUpdate
- ConsentRegistration
# Catalogue API
- Product
# Course API
- Course
- CourseStructure
# Usage API
- InitialActivation
- Usage
- IndividualUsage
- EntitlementUsage
# Progress API
- SimpleProgress
# Results API
- SimpleResult
# Entitlement API
- EntitlementEvent
- EntitlementConfirmation
- ChangeLicenseStatus
- ChangeLicenseStatusConfirmation
- ActivationCodeRequest
- ActivationCodeConfirmation
- ActivationCodeRevokeRequest
- ActivationCodeRevokeConfirmation
# Order API
- OrderRequest
- OrderConfirmation
- CreditOrderRequest
- CreditOrderConfirmation
# SIS API
- SchoolPeriod
- SchoolSubject
- Student
- Teacher
- Group
- StudentDelivery
schemaVersions:
type: array
description: 'The schema versions supported for this schema.'
items:
type: string
description: 'Schema version of the schema using semantic versioning 2.0.0'
example: 1.3.0
required:
- api
- schema
- schemaVersions
securitySchemes:
OAuth2:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://api.example.com/oauth2/token
refreshUrl: https://api.example.com/oauth2/token
scopes:
la.catalogue: 'scope that allows a MP or LMS to receive Products from the Catalogue API.'
la.course: 'Scope that allows a LMS to receive Course information from the Course API.'
la.usage.activation: 'a scope that allows a MP or LMS to receive InitialActivation information from the Usage API.'
la.usage.usage: 'a scope that allows a MP or LMS to receive Usage information from the Usage API.'
la.progress: 'a scope that allows a LMS to receive Progress information from the Progress API.'
la.results: 'a scope that allows a LMS or SIS to receive Results information from the Results API'
sis.school: 'a scope that allows a MP, LA or LMS to receive basic school information: periods and subjects from the SIS API.'
sis.student-teacher-group: 'a scope that allows a MP, LA or LMS to receive student, teacher and group data from the SIS API.'
sis.student-teacher-delivery: 'a scope that that allows a MP to receive student delivery information including address from the SIS API.'
mp.entitlement: 'a scope that allows a LA or LMS to receive entitlement information from the Entitlement API.'
mp.activationcode: 'a scope that allows a MP to send activation code requests from the Entitlement API.'
mp.order: 'a scope that allows a MP to send order requests from the Order API.'
paths:
/event:
post:
summary: Receive a single Event
operationId: post-event
x-tags:
- Event
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/EventResponse'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/EventResponse'
'401':
description: Unauthorized - No valid token presented
content:
application/json:
schema:
$ref: '#/components/schemas/EventResponse'
'403':
description: Forbidden - No consent given to access the requested resource
content:
application/json:
schema:
$ref: '#/components/schemas/EventResponse'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Event'
description: |
The request body contains a single Event.
Events are processed asynchronous. In the request body a status code and message is included as a confirmation if the events are received in a correct format. All events are confirmed with a status ok (0), excluding events that have an invalid format or events that were sent in an invalid security scope or consent. See Documentation for functional status codes and messages.
description: |
Endpoint to receive a single Event as a Consumer from different Producers. For example a party in the role of LMS can receive events from all parties offering SIS, MP and LA roles.
security:
- OAuth2:
- la.catalogue
- la.course
- la.usage.activation
- la.usage.usage
- la.progress
- la.result
- mp.entitlement
- mp.activationcode
- mp.order
- sis.student-teacher-group
- sis.student-delivery
- sis.school
/events:
post:
summary: Receive Events
operationId: post-events
x-tags:
- Event
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/EventResponse'
'400':
description: Bad Request
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/EventResponse'
'401':
description: Unauthorized - No valid token presented
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/EventResponse'
'403':
description: Forbidden - No consent given to access the requested resource
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/EventResponse'
description: |
Endpoint to receive events as a Consumer from different Producers. For example a party in the role of LMS can receive events from all parties offering SIS, MP and LA roles.
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Event'
description: |-
The request body contains a list of Events, sorted oldest events first. For Events that require Consent to be sent and received between parties, Events can only be grouped in the same request if they are from the same school.
Events are processed asynchronous. In the request body a status code and message is included as a confirmation if the events are received in a correct format. All events are confirmed with a status ok (0), excluding events that have an invalid format or events that were sent in an invalid security scope or consent. See Documentation for functional status codes and messages.
security:
- OAuth2:
- la.catalogue
- la.course
- la.usage.activation
- la.usage.usage
- la.progress
- la.result
- mp.entitlement
- mp.activationcode
- mp.order
- sis.student-teacher-group
- sis.student-delivery
- sis.school
get:
summary: Get Events After Created DateTime
operationId: get-events-after-created
x-tags:
- Event
parameters:
- schema:
type: string
in: query
name: createdAfter
description: 'Timestamp to filter on events created after a certain moment. Format: openapi in ZULU time as specified in RFC 3339, section 5.6'
- schema:
type: string
example: la.Product
in: query
name: type
description: 'Filter by a specific type of event.'
- schema:
type: integer
in: query
name: start
description: 'Start point for pagination of results, defaults to 0'
examples:
default:
value: 0
summary: 'The start point for pagination'
- schema:
type: integer
maximum: 100
in: query
name: limit
description: 'Limit of number of results returned by page, defaults to 20 with max 100.'
examples:
default:
value: 20
summary: 'The default value if none is provided'
max:
value: 100
summary: 'The largest recommended page size'
- schema:
type: string
name: schemaVersion
in: query
required: false
description: 'Optional parameter to request an Event in a specific schema version. If none supplied, the server will choose its default schema version. This schemaVersion refers to the version of the Event format.'
- schema:
type: string
name: schemaVersionObject
in: query
required: false
description: 'Optional parameter to request the object format in a specific schema version. If none supplied, the server will choose its default schema version. This schemaVersion refers to the version of the format of the data object sent within the Event.'
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Event'
'400':
description: Bad Request
'401':
description: Unauthorized - No valid token presented
'403':
description: Forbidden - No consent given to access the requested resource
security:
- OAuth2:
- la.catalogue
- la.course
- la.usage.activation
- la.usage.usage
- la.progress
- la.result
- mp.entitlement
- mp.activationcode
- mp.order
- sis.student-teacher-group
- sis.student-delivery
- sis.school
description: |
Allows a subscriber to retrieve a list of past events. The provider will not keep the events indefinite. This API is available to a party that had downtime and needs to catch up on processing or receiving events. The intended retention is a few days to support catching up.
/requestseed/{api}:
parameters:
- schema:
type: string
enum:
- 'catalogue-api'
- 'course-api'
- 'usage-api'
- 'progress-api'
- 'entitlement-api'
- 'order-api'
- 'sis-api'
name: api
in: path
required: true
description: 'API for which an initial seed of Events is requested.'
post:
summary: 'Request Initial Seed for API'
x-tags:
- Event
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
status:
type: integer
description: 'See functional status codes within the Documentation.'
statusMessage:
type: string
description: 'See functional status messages within the Documentation.'
'400':
description: Bad Request
content:
application/json:
schema:
type: object
properties:
status:
type: integer
description: 'See functional status codes within the Documentation.'
statusMessage:
type: string
description: 'See functional status messages within the Documentation.'
'401':
description: Unauthorized - No valid token presented
content:
application/json:
schema:
type: object
properties:
status:
type: integer
description: 'See functional status codes within the Documentation.'
statusMessage:
type: string
description: 'See functional status messages within the Documentation.'
'403':
description: Forbidden - No consent given to access the requested resource
content:
application/json:
schema:
type: object
properties:
status:
type: integer
description: 'See functional status codes within the Documentation.'
statusMessage:
type: string
description: 'See functional status messages within the Documentation.'
operationId: request-seed
description: |
Endpoint to request an initial seed of Events from a Producer. The combination of the parameter `api` and the chosen `scope` and `consent` gives the Producer all information to send the initial seed of Events.
| producer | consumer | `api` | `scope` | `consent` | events | description |
|---|---|---|---|---|---|---|
| LA | LMS, MP | catalogue-api | la.catalogue | no | la.Product | All Product objects relevant for the requesting Consumer LMS or MP. |
| LA | LMS | course-api | la.course | no | la.Course<br>la.CourseStructure | All Course and CourseStructure objects relevant for the requesting Consumer LMS. |
| LA | LMS, MP | usage-api | la.usage.activation | yes | la.InitialActivation | All InitialActivation events from all active entitlement of the School. |
| LA | LMS, MP | usage-api | la.usage.usage | yes | la.Usage | All Usage events from all active entitlement of the School. |
| LA | LMS | progress-api | la.progress | yes | la.SimpleProgress | All SimpleProgress events (including their last status) from the start of the schoolyear. |
| MP | LA, LMS | entitlement-api | mp.entitlement | yes (for LMS)<br>no (for LA) | mp.EntitlementEvent<br>mp.ChangeLicenseStatus | All active EntitlementEvents (including their last status) and ChangeLicenseStatus events. This allows a LMS to place links as if they were received as new Entitlements and a LA to provision products. See documentation for specific handling rules of these events. Both LMS and LA respond with a confirmation message. |
| MP | LA | entitlement-api | mp.activationcode | no | mp.ActivationCodeRequest<br>mp.ActivationCodeRevokeRequest | All requests which are not processed by the LA yet. This allows a MP to start requesting activation code before the data exchange has been established. The LA can process these events as soon as the connection is made. The LA respond with a confirmation message. |
| MP | LA | order-api | mp.order | no | mp.OrderRequest<br>mp.CreditOrderRequest | All requests which are not processed by the LA yet. This allows a MP to start ordering before the data exchange has been established. The LA can process these events as soon as the connection is made. The LA respond with a confirmation message. |
| SIS | LA, LMS, MP | sis-api | sis.school | yes | la.SchoolPeriod<br>la.SchoolSubject | All SchoolPeriod and SchoolSubjects objects relevant for the requesting Consumer LA, LMS or MP. |
| SIS | LA, LMS, MP | sis-api | sis.student-teacher-group | yes | la.Student<br>la.Teacher<br>la.Group | All Students, Teachers, and Groups objects relevant for the requesting Consumer LA, LMS or MP. |
| SIS | MP | sis-api | sis.student-delivery | yes | la.StudentDelivery | All StudentDelivery objects relevant for the requesting Consumer MP. |
security:
- OAuth2:
- la.catalogue
- la.course
- la.usage.activation
- la.usage.usage
- la.progress
- la.result
- mp.entitlement
- mp.activationcode
- mp.order
- sis.student-teacher-group
- sis.student-delivery
- sis.school
/schemaversions/{api}:
parameters:
- schema:
type: string
enum:
- 'events-api'
- 'consent-api'
- 'catalogue-api'
- 'course-api'
- 'usage-api'
- 'progress-api'
- 'results-api'
- 'entitlement-api'
- 'order-api'
- 'sis-api'
name: api
in: path
required: true
description: 'API for which the supported schema versions is requested.'
get:
summary: Get Schema Version for API
operationId: get-schemaversion-api
x-tags:
- Event
responses:
'200':
description: 'A list of schema versions supported for each Event object or Response body in the API.'
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SchemaVersions'
'400':
description: Bad Request
'401':
description: Unauthorized - No valid token presented
'403':
description: Forbidden - No consent given to access the requested resource
security:
- OAuth2:
- la.catalogue
- la.course
- la.usage.activation
- la.usage.usage
- la.progress
- la.result
- mp.entitlement
- mp.activationcode
- mp.order
- sis.student-teacher-group
- sis.student-delivery
- sis.school
description: |
Allows a Producer to check a Consumer's supported schema versions of a specific API. This prevents schema validation errors when sending events to the Consumer.
x-tags:
- name: Event
- name: SchemaVersion |