External Delivery¶
The Delivery OData API can be used to facilitate delivery through an external system such as an external printing and scanning process. The API does not provide direct access to Questionmark OnDemand’s builtin support for Printing and Scanning but it does provide the data necessary to integrate an alternate solution.
The following comparison table documents the features supported by this API and those that are only available through the Questionmark OnDemand portal.
Process |
Available through API? |
---|---|
Creating snapshots |
Yes |
HTML5 & XML of snapshots |
Yes |
Create/select bubble sheets |
No |
Creating PrintBatches |
Yes |
Upload scanned PDFs of bubble sheets |
No |
Upload raw response data for scoring |
Yes |
Snapshots¶
Before an assessment can be delivered a snapshot must be created. The purpose of the snapshot is to fix any random variation in the assessment so that anyone referring to the snapshot will know exactly which questions are to be presented/scored, the order of the questions and the order of any shuffled choices within those questions.
An application might start by presenting a list of assessments which can be obtained with a query such as:
GET /deliveryodata/123456/Assessments
A list of snapshots for a specific assessment might be obtained using
a filter on the deliveryodata.AssessmentSnapshots
feed:
GET /deliveryodata/123456/AssessmentSnapshots?$filter=AssessmentID eq 5649284224767710L
If none of the snapshots listed meet your needs then you can create a new snapshot by POSTing to the feed:
POST /deliveryodata/123456/AssessmentSnapshots
When posting, the ID, CreatedDateTime and ModifiedDateTime values will be automatically generated and can be set to any value (0 is recommended for the ID). Use the AssessmentID of the required assessment and choose a human-readable Name.
On creation, the actual entity is returned (along with the actual ID
allocated to it) and a link to the HTML view of the snapshot in the
deliveryodata.AssessmentSnapshot.PrintableDocumentSourceUrl
.
This link is time stamped for security so cannot be stored for later
use, instead, you should store the ID of the snapshot entity and
retrieve it immediately prior to use. For example, if the ID is 34:
GET /deliveryodata/123456/AssessmentSnapshots(34)
When you create a snapshot, the associated AssessmentSnapshotData entity is created automatically and linked via a navigation property. It is a media-link entity that contains the XML-raw source of the snapshot. The format is described in Snapshot File Format. To retrieve the XML document use a query such as:
GET /deliveryodata/123456/AssessmentSnapshots(34)/AssessmentSnapshotData/$value
Note the use of $value to return the document rather than the document’s metadata.
The XML file contains all the information you need to deliver the assessment to the participant. For example, for an external printing and scanning service you can parse this XML to discover the information required to print a bubble sheet customised to the number of questions and the expected response types (e.g., number of choices, validation constraints, etc).
PrintBatches¶
A print batch is used to associate a group of participants to a particular snapshot for external or offline delivery. Despite the name it doesn’t have to be through a printing and scanning process. You are not required to use print batches, it is possible to upload responses for a participant without an associated PrintBatch if you prefer.
An application might start by presenting a list of groups which can be obtained with a query such as:
GET /deliveryodata/123456/Groups
A list of PrintBatches for a specific group might be obtained using a
filter on the deliveryodata.PrintBatches
feed:
GET /deliveryodata/123456/PrintBatches?$filter=GroupID eq 335363530
If none of the PrintBatches listed meet your needs then you can create a new batch by POSTing to the feed:
POST /deliveryodata/123456/PrintBatches
The ID, CreatedDateTime and ModifiedDateTime properties are assigned values automatically on creation and dummy values can be specified when posting. The GroupID and the SnapshotID are required and the Name property provides a human-readable name for the batch. The navigation property to the associated Group is automatically populated using the supplied GroupID.
You should store the ID associated your PrintBatch as it can be used later when uploading responses to automatically associated a group with the participants result. You obtain the actual ID allocated by reading the value from the response.
Uploading Answers¶
However you collect the participant responses, ultimately they must be uploaded through the API to enable scoring and the creation of finalised results.
The steps to do this are:
1 Create an Attempt for the participant concerned
2 Prepare an answer upload file with the participant’s answers
3 POST the upload file to the AnswerUploads media-link feed
The OData API channels all assessment delivery through an Attempt entity. The attempt entity signals the authority for a single identified participant to take a specific assessment. Once the attempt has been used to generate a result it cannot be used again.
It is recommended that you create attempts on a just-in-time basis. In other words, create an attempt only when you are ready to upload the corresponding answers. Creating an attempt is done by POSTing to the Attempts feed:
POST /deliveryodata/123456/Attempts
The ID and LastModifiedDateTime properties are automatically assigned on creation and dummy values can be supplied.
For this use case, the following properties are required.
ParticipantID
The ID of the participant authorised to take the assessment.
AssessmentID
The ID of the assessment the participant is taking
AssessmentSnapshotID
The ID of the snapshot the participant was presented with. (Although optional when creating Attempts in general it is required if the answers are to be uploaded through the AnswerUploads feed.)
ExternalAttemptID
A string identifier that uniquely identifies this attempt in your system. This ID is designed to be used to prevent the accidental creation of multiple attempts where one was intended. If you POST a new attempt with the same ExternAttemptID as an existing one the request will fail. This helps avoid race conditions such as two processes processing the same participant responses simultaneously creating an attempt.
LockStatus, LockRequired
These values are only used during online delivery and can be set to False.
The ID of the attempt can be read from the entity returned and should be used in the next step.
The AnswerUpload file is a JSON file formatted as per Answer Upload File Format. Note that the ID of the Attempt is included in the file format as is the (optional) ID of the associated PrintBatch.
To upload the file you POST it to the AnswerUploads feed:
POST /deliveryodata/123456/AnswerUploads
If there are any validation errors or formatting problems with the file the POST will fail with an error code.
There can only ever by one AnswerUpload associated with an attempt, the metadata for the AnswerUpload entity uses the AttemptID as the key. You can review the actual file uploaded at any time using this ID to query the feed, for example, for attempt ID 75:
GET /deliveryodata/123456/AnswerUploads(75)/$value
The API processes the uploaded file and creates the corresponding result associating it with the attempt entity automatically. On success, you can therefore use the attempts entity to discover the outcome of the uploaded assessment:
GET /deliveryodata/123456/Attempts(75)
The ResultID will have been populated and can be used to get summary information directly from the Delivery system:
GET /deliveryodata/601871/Results(304562138)
You can obtain item level scores by expanding the answers in your query:
GET /deliveryodata/601871/Results(304562138)?$expand=Answers
You can obtain more detailed result information using the QMWISe method
GetResult
or by querying the OData feeds from the Results
Warehouse (though in the latter case you will have to wait until the
next scheduled ETL run has completed).