The Emmersion Enterprise API allows customers to integrate with the TrueNorth and WebCAPE 2.0 platform.
All usage examples are given as curl
commands.
This page details the individual endpoints. For more information about common patterns and use cases for the API, please see our API Integration Guide.
The API uses a url-based versioning scheme which indicates when it was released, such as /2020q3
for quarter 3 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 the latest version of the API is: https://api.emmersion.ai/2020q3
Documentation for other versions of the API can be found here.
An API key is required with every request to the API.
It must be sent in an Authorization
header as a Bearer
token (never as a query string parameter).
A missing or invalid API key will result in a 401
response status code.
To obtain an API key, log into the administrative dashboard. Under "Settings" then "API Keys" there is a UI for generating new API keys and revoking old ones that are no longer needed.
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.
Revoking an API key immediately cuts off access to the Enterprise API and that key is no longer usable (though a new one can be generated).
Emmersion reserves the right to revoke an API key if we observe suspicious, abusive, malicious, or excessive behavior. Whenever possible, we will reach out before taking this drastic action.
API Keys can also be revoked from the administrative dashboard. Please revoke and replace any API key you have reason to believe is compromised. Doing so helps keep your account secure.
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.
All requests to our API must be secure (HTTPS) connections using TLS 1.2 or higher. Also, please note that our certificate may change unexpectedly; we do not support certificate pinning.
We do not provide a list of IP addresses for our API or webhook functionality because of how our system is hosted and the potential for spoofing IPs.
Calling the API should always be done by the URL, not directly by IP address, and the default Host
header should be present.
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.
When a webhook is registered, a signing key will be returned that can be used to verify the authenticity of the request. This signing key cannot be retrieved after webhook registration.
We provide a signature in the X-Signature
HTTP header. The signature is calculated using the signing key which is provided when registering a webhook.
To calculate the signature concatenate the SHA-256 of the content (provided in the X-Content-SHA256
header)
and the timestamp (provided in the X-Request-Timestamp
header) separated by a semicolon.
For example, for a webhook with a signing key of AIFzHU25nf6XKz97ecmeH+IcRY5pR2AYEcUmp3kC9jg=
,
if you receive a request with the following headers:
X-Content-SHA256: aZ4ZT4GuK02F89ShnhQzEcxHlvx0HCADngDcCGsgjCI=
X-Request-Timestamp: 2021-11-10T17:34:16.1622931+00:00
X-Signature: Algorithm=HMAC-SHA256; Signature=ZhUstTlHnebfK6sId90HEfXEDQP/Z3f9dCEDFgEyLTU=
Since the X-Content-SHA256
header value is aZ4ZT4GuK02F89ShnhQzEcxHlvx0HCADngDcCGsgjCI=
,
the X-Request-Timestamp
header value is 2021-11-10T17:34:16.1622931+00:00
, and the signing key
returned when registering the webhook is AIFzHU25nf6XKz97ecmeH+IcRY5pR2AYEcUmp3kC9jg=
, then computing the
HMAC-SHA256 of aZ4ZT4GuK02F89ShnhQzEcxHlvx0HCADngDcCGsgjCI=;2021-11-10T17:34:16.1622931+00:00
should give a result
of ZhUstTlHnebfK6sId90HEfXEDQP/Z3f9dCEDFgEyLTU=
. That value should match the signature value in the
X-Signature
header.
You should also validate that the SHA-256 hash of the body matches to prevent replay attacks.
For webhooks generated before November 2021 no signature will be provided. If you wish to begin validating webhook requests, regenerate your webhook by calling the register webhook endpoint again with the same url.
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.emmersion.ai/2020q3/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.emmersion.ai/2020q3/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.emmersion.ai/2020q3/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)emailAddress
or uniqueIdentifier
is required.
Note that if you do not provide an email address, some features will be unavailable (such as account recovery or score notification).
emailAddress
or uniqueIdentifier
is required.
uniqueIdentifier
above, you will also need to provide it here in order to have this value returned as studentId
in the scoring endpoints.
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.emmersion.ai/2020q3/assign/
On success, the response contains the Emmersion userId
of the user for whom the assessment was assigned
and the userAssessmentId
which is the unique id of that assessment.
It will include a signInUrl
as described in the generate auto sign in link endpoint.
Additionally a singleAssessmentSignInUrl
will be returned. This url allows the test taker to sign in exclusively to this assessment,
and can be used multiple times. It also has a much longer expiration time than the signInUrl
.
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://app-api.emmersion.ai/api/users/sign-in-with-token?token=adb1a12a-fda3-4957-bf89-389fb46decf0",
"signInUrlExpiresAt": "2020-01-23T21:37:14.3430665+00:00",
"singleAssessmentSignInUrl": "https://localhost:44357/api/users/sign-in-with-token?token=pN9mngpPoic1%2fUe87yWvu411xEcDUYx8AoZ8GPosRLgIjxEgGVG8GIEZOjrfsu6VMQlfgKTm13Xg7%2bwJpTVTNQ%3d%3d",
"singleAssessmentSignInUrlExpiresAt": "2021-06-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 for security compliance.
curl -H 'Authorization: Bearer api-key' \
-H 'Content-Type: application/json' \
-d '{"uniqueIdentifier": "a006d339-4ad0-4679-a37e-0fa36f069301"}' \
-X POST https://api.emmersion.ai/2020q3/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://app-api.emmersion.ai/api/users/sign-in-with-token?token=6c42c316-9ba6-4abc-b92e-3b887b35b9a0",
"expiresAt": "2020-01-17T21:58:33.8677872+00:00"
}
The assignments
endpoint returns a list of assignments from a specified assigned on date, optionally filtered by a list of assessment statuses.
Valid values are:
NotStarted
InProgress
Completed
curl -H 'Authorization: Bearer api-key' \
-H 'Content-Type: application/json' \
-d '{"assignedOnOrAfter": "2023-03-28T00:00:00Z", "statuses": ["NotStarted", "InProgress"], "assignedOnOrBefore": "2023-03-28T12:45:00Z"}' \
-X POST https://api.emmersion.ai/2020q3/assignments/
On success, the response contains the assignments that were made during the specified date range. If statuses were specified, only assignments that are currently in the specified status will be included.
A 400
response with a problem detail object describing the error is returned if the request is invalid.
{
"assignments": [
{
"userId": "b13b45fe-4fb8-4667-a2cf-61401f259c69",
"uniqueIdentifier": null,
"email": "user@example.com",
"username": "user@example.com",
"givenName": "First",
"surName": "Last",
"assessmentName": "English Speaking",
"userAssessmentId": "f61835eb-a8e1-4fb7-b86e-d57e1b1fc4eb",
"userAssessmentStatus": "NotStarted",
"assignedAt": "2023-03-01T21:51:00.4925066+00:00",
"expiresAt": "2023-03-31T21:51:00.4925066+00:00",
"startedAt": null,
"completedAt": null
}]
}
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.emmersion.ai/2020q3/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",
"givenName": "John",
"surname": "Smith",
"username": "john-smith",
"email": "john-smith@example.com",
"studentId": "1234567890",
"uniqueIdentifier": "5799134",
"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": [],
"writingOpenResponses": [],
"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",
"certificateUrl": null
},
{
"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": "2020q3/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": "2020q3/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": "2020q3/response-audio/50c76e88-11a8-486e-b283-cf0952651eef/b85f78f8-4d06-4db8-9198-cfea34d41049"
}
],
"writingOpenResponses": [],
"surveyItems": [],
"subScores": null,
"assessmentVersion": "C.19.04",
"certificateUrl": "2020q3/certificate/50c76e88-11a8-486e-b283-cf0952651eef"
},
{
"userAssessmentId": "0e414961-4317-4458-814c-b04ab2b50e55",
"assessmentType": "TrueNorth",
"assessmentName": "English Writing",
"status": "Completed",
"started": "2021-12-14T18:01:08.8605745+00:00",
"completed": "2021-12-14T18:03:58.5438205+00:00",
"duration": "00:02:49.6832460",
"score": 7.20,
"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": [],
"writingOpenResponses": [
{
"question": "Write about a time when you went to dinner at a restaurant and received poor service or food from the restaurant staff.",
"responseTextUrl": "2020q3/response-text/0e414961-4317-4458-814c-b04ab2b50e55/item/e09ad147-b01c-425c-a226-399f56c2ccf4"
}
],
"surveyItems": [],
"subScores": null,
"assessmentVersion": "C.19.04",
"certificateUrl": "2020q3/certificate/0e414961-4317-4458-814c-b04ab2b50e55"
},
{
"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": [],
"writingOpenResponses": [],
"surveyItems": [],
"subScores": null,
"assessmentVersion": null,
"certificateUrl": 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.
completedOnOrAfter
or completedOnOrBefore
are provided, this parameter is ignored.
curl -H 'Authorization: Bearer api-key' \
-H 'Content-Type: application/json' \
-d '{"startedOnOrAfter": "2019-11-14T00:00:00Z"}' \
-X POST https://api.emmersion.ai/2020q3/scores/
curl -H 'Authorization: Bearer api-key' \
-H 'Content-Type: application/json' \
-d '{"startedOnOrBefore": "2019-11-14T00:00:00Z", "includeIncompleteAssessments": true, "groupIds": ["83ccbdeb-6fcf-46c8-a898-0530b4a59707", "79340353-f0ea-4ea7-9c89-ce86c411b3b6"]}' \
-X POST https://api.emmersion.ai/2020q3/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,
"completedOnOrAfter": null,
"completedOnOrBefore": null
},
"userScores": [
{
"userId": "615ba72f-f8a6-462a-b2b2-19d1952d1372",
"givenName": "John",
"surname": "Smith",
"username": "john-smith",
"email": "john-smith@example.com",
"studentId": "1234567890",
"uniqueIdentifier": "5799134",
"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": [],
"writingOpenResponses": [],
"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",
"certificateUrl": null
}
]
},
{
"userId": "e19d106d-22c5-458a-bb0a-957393453084",
"givenName": "Jenny",
"surname": "Doe",
"username": "jenny-doe",
"email": "jenny-doe@example.com",
"studentId": "8675309",
"uniqueIdentifier": "5412349",
"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": "2020q3/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": "2020q3/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": "2020q3/response-audio/50c76e88-11a8-486e-b283-cf0952651eef/b85f78f8-4d06-4db8-9198-cfea34d41049"
}
],
"writingOpenResponses": [],
"surveyItems": [],
"subScores": null,
"assessmentVersion": "C.19.04",
"certificateUrl": "2020q3/certificate/50c76e88-11a8-486e-b283-cf0952651eef"
},
{
"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": [],
"writingOpenResponses": [],
"surveyItems": [],
"subScores": null,
"assessmentVersion": null,
"certificateUrl": 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.emmersion.ai/2020q3/response-audio/3f4eda6e-1a64-4c3d-9724-360ce7f8e549/7005c513-55cb-4aac-94e6-7d3bc0b992e4
Content-Type: audio/wav
).
The response-text
endpoint returns the text file for a writing open response item, as specified from the user scores endpoint.
Writing open response items provide you examples of the user writing the language.
responseTextUrl
links provided from the user scores endpoint.
curl -H 'Authorization: Bearer api-key' \
https://api.emmersion.ai/2020q3/response-text/3f4eda6e-1a64-4c3d-9724-360ce7f8e549/item/7005c513-55cb-4aac-94e6-7d3bc0b992e4
Content-Type: text/plain; charset=utf-8
).
TrueNorth Speaking and Writing assessments include a pdf certificate for the user's score.
The certificate
endpoint allows you to download these certificates via the API.
The user scores endpoint will provide a link to the certificate for a given user assessment.
certificateUrl
links provided from the user scores endpoint.
curl -H 'Authorization: Bearer api-key' \
https://api.emmersion.ai/2020q3/certificate/3f4eda6e-1a64-4c3d-9724-360ce7f8e549
Content-Type: application/pdf
).
The POST webhook
endpoint allows you to register a webhook URL which the Emmersion
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.
The signing key cannot be retrieved after webhook registration.
curl -H 'Authorization: Bearer api-key' \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com/webhook/emmersion"}' \
-X POST https://api.emmersion.ai/2020q3/webhook
200
status code with the signing key that will be needed for request verification,
or a 400
status code if the provided URL is not a properly formed, absolute http/https url.
{
"signingKey": "IQAjTiRFweYusQZL8GSOE+2KiA3si4Rk/kQbTBbXS6k="
}
The GET webhook
endpoint returns the currently registered webhook url.
curl -H 'Authorization: Bearer api-key' \
https://api.emmersion.ai/2020q3/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/emmersion",
"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.emmersion.ai/2020q3/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 -d '' https://api.emmersion.ai/2020q3/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",
"givenName": "John",
"surname": "Smith",
"username": "john-smith",
"email": "john-smith@example.com",
"studentId": "1234567890",
"uniqueIdentifier": "5799134",
"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": [],
"writingOpenResponses": [],
"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",
"certificateUrl": null
}
]
}
}
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",
"givenName":"John",
"surname":"Smith",
"username":"john-smith",
"email":"john-smith@example.com",
"studentId":"",
"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, log into the administrative dashboard and use the API Keys settings page to replace it. After creating a new key, revoke the old one to maintain security on your account.
The uniqueIdentifier
field is the value that the system uses to identify the user.
While this field may be a student id, it may also be a number of other types of identifiers.
There are two separate fields to cover the following scenarios:
First, in some instances, you may want to use something other than a student id as the unique identifier, but you also want to associate a student id to a user to make associations with the scoring data easier.
In this case, uniqueIdentifier
and studentId
may be different values.
Second, you may want to use student id as both the uniqueIdentifier
and studentId
.
If you were to just enter the student id as the uniqueIdentifier
, we would have no way of knowing that this value is also the student id.
This means that we can't make that association in the administrative dashboard and in the scoring endpoints.
We do not support calling the Enterprise API from JavaScript in a web browser because doing so exposes the API key. If someone were to inspect your page, they could take the API key and then make their own calls indistinguishable from legitimate traffic. Therefore, it does not make sense for us to configure CORS to allow this.
Instead, we recommend that you make all calls to our API from your web servers or other non-web systems.
By default, curl
only shows the HTTP response body as output.
But in some cases, such as an invalid API key, our API may not return a response body.
You can add the -i
option to a curl
command to also view the HTTP status code and response headers.
For example:
curl -i -H 'Authorization: Bearer fake-api-key' \
https://api.emmersion.ai/2020q3/assessments
The -i
option is not listed in the examples because the additional output can be confused with the response body.
When successfully calling the API, you should get mostly 200 OK
responses (or possibly some others in the 200-299 range).
Here are some of the more common error codes you may encounter:
400 Bad Request
- occurs when there is a problem with the formatting of your request.
The response body may give you some guidance; otherwise, double check the documentation.
401 Unauthorized
- your API key was not provided correctly, is incorrect, or has been revoked.
Make sure that you are correctly sending the Authorization
header with the Bearer
keyword
403 Forbidden
- your request specified resources you are not allowed to access.
404 Not Found
- the URL for the request was incorrect. Double check it against the endpoint documentation above.
405 Method Not Allowed
- make sure you are sending the correct HTTP method (e.g. GET
, POST
, PUT
, or DELETE
).
409 Conflict
- occurs when you attempt to assign an assessment to an non-eligible test taker, such as administrator on your account.
415 Unsupported Media Type
- make sure you have included the correct Content-Type
header (i.e. Content-Type: application/json
).
429 Too Many Requests
- your account has exceeded our rate limits.
You may need to throttle your requests.
Any errors in the 500+ range indicate a problem on our end and you should retry your request later.
We recommend all POST
request bodies be formatted as JSON and sent with the Content-Type: application/json
header as per all of the examples.
None of our endpoints accept query string parameters at this time.
No, we do not provide a non-production environment (such as staging or UAT) for testing at this time.