Webhooks

The Coremetrix system can notify your backend when certain events occur, using webhooks. You can subscribe to real-time events via the Coremetrix webhooks. The webhooks can be managed via the Subscriptions API.

This API can be used to subscribe to various events from the quiz lifecycle.

How it works:

webhook

Supported events

Currently we support subscriptions to the following events:

event_namedescription
quiz_consentTriggered when a user has agreed to the processing of personal data relating to him or her
quiz_consent_withdrawalTriggered when a user has withdrawn his consent to the processing of personal data relating to him or her
landing_loadTriggered when a user loads the landing page of a quiz (if a landing page is setup)
quiz_loadTriggered when a user loads the first quiz page
quiz_startTriggered when a user has started the quiz (the first question of the quiz has been submitted)
quiz_completeTriggered when a user has completed the quiz (the last question of the quiz has been submitted)
attempt_scoredTriggered when an attempt has been scored (or flagged)
attempt_profiledTriggered when an attempt has been profilled (or flagged)

Note: The complete list of events you can subscribe to can be found by calling the/subscriptions/events endpoint:

gethttps://api.coremetrix.com/subscriptions/events?apikey={YOUR_API_KEY}

Webhook payload

When creating a subscription via the Subscriptions API, you are required to provide an URL. When any of the events described above happen, Coremetrix will POST the corresponding data to the URL provided. Your API should be able to consume the following payload:

quiz_consent

{
  • "event": "quiz_consent",
  • "consentTime": "2020-01-31T13:14:35.208Z",
  • "lastUpdated": "2020-01-31T13:14:35.208Z",
  • "slug": "sandbox",
  • "puid": "a_puid",
  • "quizId": "481ac0fe-ac33-402a-9367-2aaa7a98b49d",
  • "consent": true
}

Note: the lastUpdated and consentTime are in ISO8601 format

quiz_consent_withdrawal

{
  • "event": "quiz_consent_withdrawal",
  • "withdrawalTime": "2020-01-31T13:25:02.786Z",
  • "lastUpdated": "2020-01-31T13:25:02.786Z",
  • "slug": "sandbox",
  • "puid": "a_puid",
  • "quizId": "481ac0fe-ac33-402a-9367-2aaa7a98b49d",
  • "consent": false
}

Note: the lastUpdated and consentTime are in ISO8601 format

landing_load

{
  • "attemptId": "0012ba6f-f8a2-493a-b32d-7cda370af477",
  • "event": "landing_load",
  • "puid": "test-70b8f195-8d75-4177-b094-4e0ac7472e",
  • "quizId": "511c77c5-f6a3-48fd-a136-93f18d47116a",
  • "timestamp": 1727174639100
}

Note: the puid is optional and the timestamp is in Epoch milliseconds

quiz_load

{
  • "event": "quiz_load",
  • "attemptId": "4d1c90d4-f1fe-4303-ad83-535d99a61cf5",
  • "quizId": "481ac0fe-ac33-402a-9367-2aaa7a98b49d",
  • "puid": "a_puid",
  • "timestamp": 1562161162000
}

Note: the puid is optional and the timestamp is in Epoch milliseconds

quiz_start

{
  • "event": "quiz_start",
  • "attemptId": "4d1c90d4-f1fe-4303-ad83-535d99a61cf5",
  • "quizId": "481ac0fe-ac33-402a-9367-2aaa7a98b49d",
  • "puid": "a_puid",
  • "timestamp": 1562161162000
}

Note: the puid is optional and the timestamp is in Epoch milliseconds

quiz_complete

{
  • "event": "quiz_complete",
  • "attemptId": "4d1c90d4-f1fe-4303-ad83-535d99a61cf5",
  • "quizId": "481ac0fe-ac33-402a-9367-2aaa7a98b49d",
  • "puid": "a_puid",
  • "timestamp": 1562161162000
}

Note: the puid is optional and the timestamp is in Epoch milliseconds

attempt_scored

{
  • "event": "attempt_scored",
  • "attemptId": "4d1c90d4-f1fe-4303-ad83-535d99a61cf5",
  • "quizId": "481ac0fe-ac33-402a-9367-2aaa7a98b49d",
  • "puid": "a_puid",
  • "age": "age",
  • "gender": "gender",
  • "maritalStatus": "maritalStatus",
  • "occupation": "occupation",
  • "accommodation": "accommodation",
  • "education": "education",
  • "scores": [
    • {
      • "value": 203.04200292294007,
      • "model": "generic_model"
      }
    ],
  • "flags": [ ],
  • "status": "COMPLETED_SCORED"
}
Note:

- the puid is optional

- the age, gender, maritalStatus, occupation,
accommodation and education are also optional as some questionnaires might not have demographic questions

Attempt status can be one of the following:

statusdescription
COMPLETED_SCOREDQuiz has been completed, expect profiles present.
COMPLETED_PARTIALLY_SCOREDQuiz has been completed, expect profiles and flags present.
COMPLETED_NOT_SCOREDUnable to score quiz, possible reasons: quiz was answered too fast (no profile will be generated and a FAST_CLICK flag will be present instead), no profile models have been set up / enabled.
attempt_profiled - Example with profiles

{
  • "event": "attempt_profiled",
  • "attemptId": "4d1c90d4-f1fe-4303-ad83-535d99a61cf5",
  • "quizId": "481ac0fe-ac33-402a-9367-2aaa7a98b49d",
  • "puid": "a_puid",
  • "age": "age",
  • "gender": "gender",
  • "maritalStatus": "maritalStatus",
  • "occupation": "occupation",
  • "accommodation": "accommodation",
  • "education": "education",
  • "profiles": {
    • "basic_profile": {
      • "value": "HIGH",
      • "scale": [
        • "LOW",
        • "MEDIUM",
        • "HIGH"
        ]
      }
    },
  • "profileFlags": { },
  • "status": "COMPLETED_SCORED"
}
attempt_profiled - Example with flags

{
  • "event": "attempt_profiled",
  • "attemptId": "4d1c90d4-f1fe-4303-ad83-535d99a61cf5",
  • "quizId": "481ac0fe-ac33-402a-9367-2aaa7a98b49d",
  • "puid": "a_puid",
  • "age": "age",
  • "gender": "gender",
  • "maritalStatus": "maritalStatus",
  • "occupation": "occupation",
  • "accommodation": "accommodation",
  • "education": "education",
  • "profiles": { },
  • "profileFlags": {
    • "basic_profile": {
      • "flag": [
        • "FAST_CLICK"
        ]
      }
    },
  • "status": "COMPLETED_NOT_SCORED"
}
Note:

- the puid is optional

- the age, gender, maritalStatus, occupation,
accommodation and education are also optional as some questionnaires might not have demographic questions

Attempt status can be one of the following:

statusdescription
COMPLETED_SCOREDQuiz has been completed, expect profiles present.
COMPLETED_PARTIALLY_SCOREDQuiz has been completed, expect profiles and flags present.
COMPLETED_NOT_SCOREDUnable to score quiz, possible reasons: quiz was answered too fast (no profile will be generated and a FAST_CLICK flag will be present instead), no profile models have been set up / enabled.

Security

Data encryption during transmission

Coremetrix employs encryption for all data transmission. The Subscriptions API will only accept the https protocol. This is to protect the communication between the Coremetrix system and your back end. You will need to turn on TLS on your server and configure the subscription URL to use https.

Basic http authentication

Coremetrix supports Basic http authentication in order to allow your backend to secure the subscriber URL. This will ensure that Coremetrix only will be able to post data to your server.

The Subscriptions API will allow you to create a subscriber URL with the following format: https://username:password@my_server.com/my_secure_path

Note: username and password should not contain any : or @ symbols.

OAuth 2.0

OAuth 2.0 is an open standard for authorization on the internet. Coremetrix supports OAuth 2.0 authorisation in order to allow our backend limited access to your webhook endpoint.

OAuth 2.0 requires an authentication token, which is issued by an authorization server.

In order to grant Coremetrix access to post data to your webhook endpoint, you must first setup your subscriptions using Subscriptions API.

auth20_config

For each subscription you must also provide the following configuration:

FieldRequiredDescription
Token URLYes

The API endpoint URL to request an access token from (only https allowed).

Note: In accordance with RFC 6749, the token URL must accept a content type of x-www-form-urlencoded.

Client idYesThe web application client ID.
Client secretYesThe web application client secret.
ScopeNoScope of permissions to request.
AudienceNoAudience is the intended reciepient of the token. The audience URI MUST be an absolute URI as defined by Section 4.3 of [RFC3986]
Grant typeNoGrant type.

Note: These parameters will be added using the application/x-www-form-urlencoded format with a character encoding of UTF-8 in the HTTP request entity-body.

Full details can be found here.

Note:

These parameters will be added using the application/x-www-form-urlencoded format with a character encoding of UTF-8 in the HTTP request entity-body.

Full details can be found here.

How it works:

auth20_client_credentials_flow

Client Credentials Flow

OAuth 2.0 specifies multiple flows for obtaining and validating tokens. Coremetrix supports the Client Credential Flow, where the communication is strictly server-to-server. No Refresh Token is issued in this flow since the client can retrieve a new Access Token using its credentials anyway.

When an event occurs, if OAuth 2.0 is configured:

  1. To obtain an Access Token, Coremetrix will call your OAuth server passing the credential (previously registered via the Subscription API) The access token will be used when pushing data to the webhook.

JSON Web Tokens

JSON Web Tokens allow you to verify that the data sent to your server has not been tampered with and that it is actually coming from Coremetrix.

How it works:

jwt
  1. Coremetrix will include the entire event data in the payload of the JWT token.
  2. To prevent replay attacks, , Coremetrix will include a nonce (jti claim), the creation time (iat claim) and and an expiration time (exp claim) as part of the JWT payload. The expiration time is currently set to 60 seconds.
  3. Coremetrix signs the JWT token using HS512 and your secret API key in the format “{apiKey}+{apiKey}”.
  4. Coremetrix will send this token in a header called X-Coremetrix-Signature when posting data to your server.

Validating the JWT:

You will have to validate the JWT to verify its authenticity. You can do this by checking its digital signature and it's claims. There are various libraries out there to help you in doing this. For instance, you can use the jjwt library for java.

Retries and exponential backoff

Coremetrix will retry sending the events in case of error. In addition to the retries, Coremetrix implements exponential backoff algorithm to achieve better flow control. In case of error returned by your server when attempting to deliver the events, the Coremetrix system will retry after a period of time. The wait time will incrementally increase between consecutive retry requests after each failure. This will give your service enough time to recover

retries

Coremetrix will retry sending messages to your system for up to 1 hour approximately. If your service is down for more than one hour, we recommend you use the Coremetrix report API to get the missing information.

BACK