The beta version of the API is now deprecated. For the latest version, click here.
The TrueNorth Enterprise API allows customers to integrate with the TrueNorth and WebCAPE 2.0 platform.
All usage examples are given as curl
commands.
NOTE: The API is currently a beta version and minor changes may be made before the general release.
The API uses a url-based versioning scheme which indicates when it was released, such as /2020q1
for quarter 1 of 2020.
All endpoints are versioned together when we release a new version.
For the best consumer experience, you should use the same version for all requests; avoid making some requests to older endpoints.
Version updates are planned to be infrequent to minimize the work clients need to do to upgrade to the latest versions. Breaking changes will be documented for each affected endpoint. Minor, non-breaking changes may be made to existing endpoints for maintenance without updating the version.
The base url for accessing this version of the API is: https://api.truenorthtest.com/beta
An API key is required with every request to the API.
It must be sent in an Authorization
header as a Bearer
token.
A missing or invalid API key will result in a 401
response status code.
During the beta period, API keys will be distributed from your point-of-contact at Emmersion Learning. Later on, an in-product user interface will allow you to manage your API keys.
In the endpoint documentation below, the example requests indicate the required header in the curl
commands like this:
-H "Authorization: Bearer {api-key}"
Replace {api-key}
with your actual API key in your requests.
In order to safeguard the performance of the Enterprise API, we rate limit the number of requests that will be accepted.
Each account may make up to 2,000 requests per 20 minutes, and no faster than 5 requests per second.
If requests are made too quickly they will not be processed and will result in a 429
status code.
Each account may register a webhook via the Enterprise API in order to be notified whenever key events occur.
The registered URL will be sent a POST
request with a JSON body (Content-Type: application/json
)
containing relevant data for the event.
We strongly recommend that you only register a webhook that uses a secure tunnel (TLS/HTTPS). When your server is called, please attempt to respond within 5 seconds. This means you should avoid processing the data or calling our API as part of receiving the webhook event.
The assessments
endpoint returns the list of assessments available to your account.
curl -H 'Authorization: Bearer {api-key}' \
https://api.truenorthtest.com/beta/assessments
name
and assessmentId
for each assessment.
The assessmentId
values may be required to use other endpoints.
{
"assessments": [
{
"name": "English Grammar",
"assessmentId": "de83346f-aa2d-4c4f-a250-0d3a09d609e3"
},
{
"name": "English Listening",
"assessmentId": "0b5c0072-7cc9-4ef0-96e8-635a4ce012fd"
},
{
"name": "English Speaking",
"assessmentId": "c66496f2-35a7-465d-bb3b-58f6af5caedb"
},
{
"name": "English Speaking Demo",
"assessmentId": "6ce10c60-0761-4dc7-b193-9f73977a9510"
},
]
}
The GET groups
endpoint gets a list of all groups on the account.
Groups can be managed from the administrator dashboard within the product,
or new groups can be created via the create group endpoint.
curl -H 'Authorization: Bearer {api-key}' \
https://api.truenorthtest.com/beta/groups
name
and groupId
for each group associated with your account.
{
"groups": [
{
"name": "English speaking",
"groupId": "80843e92-5be1-46aa-9472-2862d11413b3"
},
{
"name": "grammar",
"groupId": "90dc068c-31bf-4303-a536-fb4398b47f5d"
},
{
"name": "New Group",
"groupId": "23b3ac80-0309-4553-91f8-a4f28fdb2b18"
},
{
"name": "Only WebCAPE",
"groupId": "1cffe784-d006-4f1b-87d4-70d07d7d2dc3"
}
]
}
The POST groups
endpoint creates a new group on the account.
curl -H 'Authorization: Bearer {api-key}' \
-H 'Content-Type: application/json' \
-d '{"name": "English speaking"}' \
-X POST https://api.truenorthtest.com/beta/groups
name
and groupId
of the newly created group.
{
"name": "English speaking",
"groupId": "80843e92-5be1-46aa-9472-2862d11413b3"
}
The assign
endpoint allows you to create a new user and assign an assessment to the user, or if the user already exists, assign an assessment to that user.
You may provide an optional unique identifier that will be associated with the user which you can use on other endpoints to specify this same user.
assessmentId
for the assessment you are assigning (see the assessments endpoint)groupId
values matching the groups that you want the user to be added to.
These values can be obtained from the groups endpoint.
curl -H 'Authorization: Bearer {api-key}' \
-H 'Content-Type: application/json' \
-d '{ "assessmentId": "C66496F2-35A7-465D-BB3B-58F6AF5CAEDB", "givenName": "Steve", "surName": "Stevenson", "emailAddress": "steve.stevenson@example.com"}' \
-X POST https://api.truenorthtest.com/beta/assign/
On success, the response contains the TrueNorth userId
of the user for whom the assessment was assigned
and the userAssessmentId
which is the unique id of that assessment.
It will also include a signInUrl
as described in the generate auto sign in link endpoint.
On failure, the response returns an array of errors
which describe the problem.
The HTTP status code will be 400
if the request was unacceptable, or 409
if the request could not be processed.
{
"userId": "a3a0ff2d-6817-47b9-b9db-fc6674bced8a",
"userAssessmentId": "79fb94aa-344d-43a2-8504-13ed687dd77a",
"signInUrl": "https://operationsservice.truenorthtest.com/api/users/sign-in-with-token?token=adb1a12a-fda3-4957-bf89-389fb46decf0",
"signInUrlExpiresAt": "2020-01-23T21:37:14.3430665+00:00"
}
The create-sign-in-token
endpoint creates a single-use link that a user can click to automatically log in, bypassing the login form.
The link expires after 5 minutes.
curl -H 'Authorization: Bearer {api-key}' \
-H 'Content-Type: application/json' \
-d '{"uniqueIdentifier": "a006d339-4ad0-4679-a37e-0fa36f069301"}' \
-X POST https://api.truenorthtest.com/beta/create-sign-in-token/
On success, the response contains the signInUrl
that a user can use to bypass the login form. The link is single-use and expires after 5 minutes as indicated by the expiresAt
value.
If the user could not be found, a 204
status code will be returned.
A 400
response with an array of errors
is returned in the response body when the request is invalid.
{
"signInUrl": "https://operationsservice.truenorthtest.com/api/users/sign-in-with-token?token=6c42c316-9ba6-4abc-b92e-3b887b35b9a0",
"expiresAt": "2020-01-17T21:58:33.8677872+00:00"
}
The score
endpoint retrieves the data for all assessments and scores assigned to the specified user.
curl -H 'Authorization: Bearer {api-key}' \
-H 'Content-Type: application/json' \
-d '{"uniqueIdentifier": "a006d339-4ad0-4679-a37e-0fa36f069301"}' \
-X POST https://api.truenorthtest.com/beta/score/
On success, each item in the scoreReports
array specifies an assessment assigned to the user, identified by userAssessmentId
.
It includes the status
of the assessment and the score
(if the assessment was completed).
The possible status
values are:
NotStarted
- when the assessment has been assigned but the user has not started itInProgress
- the user has started, but not yet completed the assessmentScorePending
- the user finished the assessment, but it has not yet been scoredCompleted
- the assessment has been finished and scoredNeedsReview
- an error occurred during the assessment which our team is investigating
For TrueNorth assessments, the score
will be a value from 0 to 10, with .1 increments.
WebCAPE scores range from 0 to 1000, with whole number increments.
WebCAPE assessment may also show a placement
field based on the score.
These placement values and their cutpoints are customizable for an account from the admin dashboard.
Many of the fields returned may be null or empty depending on the assessmentType
(whether it was a TrueNorth or WebCAPE assessment) as you can see in the example response below.
If the user could not be found, a 204
status code will be returned.
A 400
response with an array of errors
is returned in the response body when the request was invalid.
{
"userId": "615ba72f-f8a6-462a-b2b2-19d1952d1372",
"uniqueIdentifier": "studentId5799134",
"scoreReports": [
{
"userAssessmentId": "79fb94aa-344d-43a2-8504-13ed687dd77a",
"assessmentType": "WebCAPE",
"assessmentName": "English Grammar",
"status": "Completed",
"started": "2019-09-10T16:29:29.9074258+00:00",
"completed": "2019-09-10T16:30:13.7087307+00:00",
"duration": "00:00:43.8013049",
"score": 825.00,
"placement": "Semester 4",
"proficiencyLevelDescription": null,
"actflSpeakingLevel": null,
"actflDescription": null,
"cefrSpeakingLevel": null,
"cefrDescription": null,
"toeflSpeakingLevel": null,
"ieltsSpeakingLevel": null,
"toeicSpeakingLevel": null,
"diagnosticInfo": [],
"openResponses": [],
"surveyItems": [
{
"question": "What is the highest level of education that you have completed?",
"answer": "graduate degree"
},
{
"question": "Please list any additional languages you speak",
"answer": ""
},
{
"question": "What is your native language?",
"answer": "Spanish"
},
{
"question": "How many years have you been learning English? (in years)",
"answer": "2"
}
],
"subScores": {
"reading": {
"correct": 1,
"total": 2
},
"grammar": {
"correct": 14,
"total": 16
},
"listening": {
"correct": 0,
"total": 0
},
"vocabulary": {
"correct": 1,
"total": 1
}
},
"assessmentVersion": "A.20.01"
},
{
"userAssessmentId": "f8f04710-c569-4afa-9f28-f71cef73f7eb",
"assessmentType": "TrueNorth",
"assessmentName": "English Speaking",
"status": "Completed",
"started": "2019-07-29T18:01:08.8605745+00:00",
"completed": "2019-07-29T18:03:58.5438205+00:00",
"duration": "00:02:49.6832460",
"score": 8.00,
"placement": null,
"proficiencyLevelDescription": "Individuals at this level can express themselves freely and spontaneously, and for the most part accurately, on concrete topics and on most complex issues. They can usually support their opinion and develop hypotheses on topics of particular interest or personal expertise.",
"actflSpeakingLevel": "Advanced Mid - Advanced High",
"actflDescription": "ACTFL Overall Speaking Guideline: Speakers at the Advanced High sublevel perform all Advanced-level tasks with linguistic ease, confidence, and competence. They are consistently able to explain in detail and narrate fully and accurately in all time frames.",
"cefrSpeakingLevel": "B2-C1",
"cefrDescription": "CEFR Overall Production Description: Can give clear, detailed descriptions and presentations on complex subjects, integrating sub-themes, developing particular points and rounding off with an appropriate conclusion.",
"toeflSpeakingLevel": "25-27",
"ieltsSpeakingLevel": "7 - 7.5",
"toeicSpeakingLevel": "170-180",
"diagnosticInfo": [
"Focus on learning and using phrasal verbs (verb + preposition pairs that together form new meaning, ex. \"it just came up\")",
"Listen to native speakers for examples of idioms (ex. \"piece of cake\"). Practice intentionally using idioms in your speech.",
"Consider asking a language-learning partner to occasionally, unexpectedly confront you with unanticipated situations for practice.",
"Search for opportunities to listen to native speakers talk about divisive, hypothetical, or abstract topics.",
"Read as much as you can. Re-read complex passages to ensure you understand all of the words through context."
],
"openResponses": [
{
"question": "What is your favorite book and why?",
"responseAudioUrl": "beta/response-audio/50c76e88-11a8-486e-b283-cf0952651eef/fd1b0881-4506-4436-b5b0-d0e1215b8410"
},
{
"question": "Describe an experience when you got hurt. How did it happen and what did you do afterwards?",
"responseAudioUrl": "beta/response-audio/50c76e88-11a8-486e-b283-cf0952651eef/2d892090-adff-46fc-ae5c-b2689b158dc3"
},
{
"question": "How did you meet your best friend? What were the circumstances?",
"responseAudioUrl": "beta/response-audio/50c76e88-11a8-486e-b283-cf0952651eef/b85f78f8-4d06-4db8-9198-cfea34d41049"
}
],
"surveyItems": [],
"subScores": null,
"assessmentVersion": "C.19.04"
},
{
"userAssessmentId": "bdcceba8-14f1-4fe4-b8db-c98e2f2e4202",
"assessmentType": "TrueNorth",
"assessmentName": "Spanish Speaking",
"status": "NotStarted",
"started": null,
"completed": null,
"duration": null,
"score": 0.0,
"placement": null,
"proficiencyLevelDescription": null,
"actflSpeakingLevel": null,
"actflDescription": null,
"cefrSpeakingLevel": null,
"cefrDescription": null,
"toeflSpeakingLevel": null,
"ieltsSpeakingLevel": null,
"toeicSpeakingLevel": null,
"diagnosticInfo": [],
"openResponses": [],
"surveyItems": [],
"subScores": null,
"assessmentVersion": null
}
]
}
The scores
endpoint retrieves the data for all assessments and scores for the account.
groupId
values; only scores for users in the specified groups will be returned. If empty, scores for all users will be returned.
curl -H 'Authorization: Bearer {api-key}' \
-H 'Content-Type: application/json' \
-d '{"startedOnOrAfter": "2019-11-14T00:00:00Z"}' \
-X POST https://api.truenorthtest.com/beta/scores/
On success, the response body will contain a userScores
array, where each item is identical to the format returned by the user scores endpoint.
It will also include an appliedFilters
object that reflects the request filters that were provided.
{
"appliedFilters": {
"includeIncompleteAssessments": false,
"groupIds": null,
"startedOnOrAfter": "2019-11-14T00:00:00+00:00",
"startedOnOrBefore": null
},
"userScores": [
{
"userId": "615ba72f-f8a6-462a-b2b2-19d1952d1372",
"uniqueIdentifier": "studentId5799134",
"scoreReports": [
{
"userAssessmentId": "99807cea-1225-41e6-a271-eb7e8a732d1b",
"assessmentType": "WebCAPE",
"assessmentName": "English Grammar",
"status": "Completed",
"started": "2019-09-10T16:29:29.9074258+00:00",
"completed": "2019-09-10T16:30:13.7087307+00:00",
"duration": "00:00:43.8013049",
"score": 825.00,
"placement": "Semester 4",
"proficiencyLevelDescription": null,
"actflSpeakingLevel": null,
"actflDescription": null,
"cefrSpeakingLevel": null,
"cefrDescription": null,
"toeflSpeakingLevel": null,
"ieltsSpeakingLevel": null,
"toeicSpeakingLevel": null,
"diagnosticInfo": [],
"openResponses": [],
"surveyItems": [
{
"question": "What is the highest level of education that you have completed?",
"answer": "graduate degree"
},
{
"question": "Please list any additional languages you speak",
"answer": ""
},
{
"question": "What is your native language?",
"answer": "Spanish"
},
{
"question": "How many years have you been learning English? (in years)",
"answer": "2"
}
],
"subScores": {
"reading": {
"correct": 1,
"total": 2
},
"grammar": {
"correct": 14,
"total": 16
},
"listening": {
"correct": 0,
"total": 0
},
"vocabulary": {
"correct": 1,
"total": 1
}
},
"assessmentVersion": "A.20.01"
}
]
},
{
"userId": "e19d106d-22c5-458a-bb0a-957393453084",
"uniqueIdentifier": "studentId1234567",
"scoreReports": [
{
"userAssessmentId": "8e61a04f-29c4-4d9e-a103-a559362455de",
"assessmentType": "TrueNorth",
"assessmentName": "English Speaking",
"status": "Completed",
"started": "2019-07-29T18:01:08.8605745+00:00",
"completed": "2019-07-29T18:03:58.5438205+00:00",
"duration": "00:02:49.6832460",
"score": 8.00,
"placement": null,
"proficiencyLevelDescription": "Individuals at this level can express themselves freely and spontaneously, and for the most part accurately, on concrete topics and on most complex issues. They can usually support their opinion and develop hypotheses on topics of particular interest or personal expertise.",
"actflSpeakingLevel": "Advanced Mid - Advanced High",
"actflDescription": "ACTFL Overall Speaking Guideline: Speakers at the Advanced High sublevel perform all Advanced-level tasks with linguistic ease, confidence, and competence. They are consistently able to explain in detail and narrate fully and accurately in all time frames.",
"cefrSpeakingLevel": "B2-C1",
"cefrDescription": "CEFR Overall Production Description: Can give clear, detailed descriptions and presentations on complex subjects, integrating sub-themes, developing particular points and rounding off with an appropriate conclusion.",
"toeflSpeakingLevel": "25-27",
"ieltsSpeakingLevel": "7 - 7.5",
"toeicSpeakingLevel": "170-180",
"diagnosticInfo": [
"Focus on learning and using phrasal verbs (verb + preposition pairs that together form new meaning, ex. \"it just came up\")",
"Listen to native speakers for examples of idioms (ex. \"piece of cake\"). Practice intentionally using idioms in your speech.",
"Consider asking a language-learning partner to occasionally, unexpectedly confront you with unanticipated situations for practice.",
"Search for opportunities to listen to native speakers talk about divisive, hypothetical, or abstract topics.",
"Read as much as you can. Re-read complex passages to ensure you understand all of the words through context."
],
"openResponses": [
{
"question": "What is your favorite book and why?",
"responseAudioUrl": "2020q1/response-audio/50c76e88-11a8-486e-b283-cf0952651eef/fd1b0881-4506-4436-b5b0-d0e1215b8410"
},
{
"question": "Describe an experience when you got hurt. How did it happen and what did you do afterwards?",
"responseAudioUrl": "2020q1/response-audio/50c76e88-11a8-486e-b283-cf0952651eef/2d892090-adff-46fc-ae5c-b2689b158dc3"
},
{
"question": "How did you meet your best friend? What were the circumstances?",
"responseAudioUrl": "2020q1/response-audio/50c76e88-11a8-486e-b283-cf0952651eef/b85f78f8-4d06-4db8-9198-cfea34d41049"
}
],
"surveyItems": [],
"subScores": null,
"assessmentVersion": "C.19.04"
},
{
"userAssessmentId": "99a17dd0-dc41-47a1-8c7e-400734800c0f",
"assessmentType": "TrueNorth",
"assessmentName": "Spanish Speaking",
"status": "NotStarted",
"started": null,
"completed": null,
"duration": null,
"score": 0.0,
"placement": null,
"proficiencyLevelDescription": null,
"actflSpeakingLevel": null,
"actflDescription": null,
"cefrSpeakingLevel": null,
"cefrDescription": null,
"toeflSpeakingLevel": null,
"ieltsSpeakingLevel": null,
"toeicSpeakingLevel": null,
"diagnosticInfo": [],
"openResponses": [],
"surveyItems": [],
"subScores": null,
"assessmentVersion": null
}
]
}
]
}
The response-audio
endpoint returns the audio file for an open response item, as specified from the user scores endpoint.
Open response items provide you examples of the user speaking the language.
responseAudioUrl
links provided from the user scores endpoint.
curl -H 'Authorization: Bearer {api-key}' \
https://api.truenorthtest.com/beta/response-audio/3f4eda6e-1a64-4c3d-9724-360ce7f8e549/7005c513-55cb-4aac-94e6-7d3bc0b992e4
Content-Type: audio/wav
).
The POST webhook
endpoint allows you to register a webhook URL which the TrueNorth
system will POST
to whenever a relevant event occurs in the system
(e.g. when a user assessment is scored).
Only one webhook may be registered; calling this endpoint will overwrite previous values.
curl -H 'Authorization: Bearer {api-key}' \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com/webhook/truenorth"}' \
-X POST https://api.truenorthtest.com/beta/webhook
200
status code with no response body on success,
or a 400
status code if the provided URL is not a properly formed, absolute http/https url.
The GET webhook
endpoint returns the currently registered webhook url.
curl -H 'Authorization: Bearer {api-key}' \
https://api.truenorthtest.com/beta/webhook
url
along with the createdAt
timestamp
if a webhook is currently registered.
Otherwise it will return a 204
status code.
{
"url": "https://example.com/webhook/truenorth",
"createdAt": "2020-01-22T16:30:13.7087307+00:00"
}
The DELETE webhook
endpoint allows you to unregister your webhook.
No further events will be sent until you register a new one.
curl -H 'Authorization: Bearer {api-key}' \
-X DELETE https://api.truenorthtest.com/beta/webhook
204
status code on success.
The webhook/example
endpoint allows you to trigger an example event which will cause your webhook to be called.
You may use this to test that your webhook URL is configured correctly
and that your server can process the POST
request.
Note that the example event will be triggered no more frequently than once per second.
curl -H 'Authorization: Bearer {api-key}' \
-X POST https://api.truenorthtest.com/beta/webhook/example
200
status code with no response body when the event was triggered successfully.
However, this does not mean that the webhook was called successfully.
This event is triggered when a user assessment is scored.
The data
has the same format as the get user scores endpoint,
except it will only return a single item in the scoreReports
array for the user assessment that was just scored.
Here is an example of the event data:
{
"event": "user-assessment-scored",
"data": {
"userId": "615ba72f-f8a6-462a-b2b2-19d1952d1372",
"uniqueIdentifier": "studentId5799134",
"scoreReports": [
{
"userAssessmentId": "79fb94aa-344d-43a2-8504-13ed687dd77a",
"assessmentType": "WebCAPE",
"assessmentName": "English Grammar",
"status": "Completed",
"started": "2019-09-10T16:29:29.9074258+00:00",
"completed": "2019-09-10T16:30:13.7087307+00:00",
"duration": "00:00:43.8013049",
"score": 825.00,
"placement": "Semester 4",
"proficiencyLevelDescription": null,
"actflSpeakingLevel": null,
"actflDescription": null,
"cefrSpeakingLevel": null,
"cefrDescription": null,
"toeflSpeakingLevel": null,
"ieltsSpeakingLevel": null,
"toeicSpeakingLevel": null,
"diagnosticInfo": [],
"openResponses": [],
"surveyItems": [
{
"question": "What is the highest level of education that you have completed?",
"answer": "graduate degree"
},
{
"question": "Please list any additional languages you speak",
"answer": ""
},
{
"question": "What is your native language?",
"answer": "Spanish"
},
{
"question": "How many years have you been learning English? (in years)",
"answer": "2"
}
],
"subScores": {
"reading": {
"correct": 1,
"total": 2
},
"grammar": {
"correct": 14,
"total": 16
},
"listening": {
"correct": 0,
"total": 0
},
"vocabulary": {
"correct": 1,
"total": 1
}
},
"assessmentVersion": "A.20.01"
}
]
}
}
This event is triggered by calling the example webhook event endpoint.
The example event data will always contain the same JSON:
{
"event":"webhook-example",
"data":{
"userId":"00000000-0000-0000-0000-000000000000",
"uniqueIdentifier":"",
"scoreReports":[]
}
}
No. For security reasons, we do not store the raw API key values in our system. Instead, we store a hashed value which allows us to verify an API key without knowing the original value (similar to password storage practices).
If you have lost your API key or believe it may have been compromised, contact Emmersion Learning to have a new one generated. The old API key will then be revoked.