Skip to main content
Version: v5

Webhooks

Incognia's Onboarding solution continuously reassesses new signups for up to 48 hours. You can setup an endpoint to receive assessment modifications as soon as they occur through Incognia's webhook solution.

Capturing risk assessment changes via webhooks#

POST
https://your-domain/your-endpoint/

Headers

Incognia-timestampstringRequiredUNIX timestamp indicating the moment during which the request was sent. Used for authentication
Incognia-signaturestringRequiredHMAC encrypted value used for authentication

Body Parameters

event_idstringRequiredID of the event being notified.
signup_idstringRequiredID of the signup, generated when it was created.
installation_idstringRequiredID of the given installation when the signup was created.
event_typestringRequiredType of risk assessment change. See Understanding event types below.
risk_assessment_beforestringRequiredPrevious risk assessment.
risk_assessment_afterstringRequiredNew risk assessment.
triggered_atdatetimeRequiredString containing datetime of the assessment that was changed, in ISO8601 format.
evidenceobjectRequiredAn object with supporting evidence for the risk assessment. For more information refer to Understanding risk assessments.

Response body example

For a 200-OK response, these are the fields you should expect as a result:

Body
{  "event_id": "5e76a7ca-577c-4f47-a752-9e1e0cee9e49",  "signup_id": "8afc84a7-f1d4-488d-bd69-36d9a37168b7",  "installation_id": "LX2K9uIfkPIL2UIXxQCqSXDTPKkG8gLG2heKnlMrwAaCLV2KHxuji1WLElDrFBlWYJLCwbkghZVmp5WVb6UAjfxlgcExS3W1fgQ4j0ikcp7Z8x9dGTaYcVFXVf0fupbcvhI8Nh0RO9oy+3NavbBX7Q",  "event_type": "verification",  "risk_assessment_before": "unknown_risk",  "risk_assessment_after": "low_risk",  "triggered_at": "2021-05-13T17:31:15.061Z",  "evidence": {    // For a complete explanation of this part of the response,    // please refer to the evidence page in the docs.    "device_model": "Moto Z2 Play",    "geocode_quality": "good",    "location_events_near_address": 38,    "location_events_quantity": 288,    "location_services": {      "location_permission_enabled": true,      "location_sensors_enabled": true     },     "device_integrity": {       "probable_root": false,       "emulator": false,       "gps_spoofing": false,       "from_official_store": true     }  }}

Understanding event types#

The event types which are sent in the event_type request field indicate which type of change happened, so that you may quickly decide how to proceed without having to unfurl the whole event.

Event typeDescription
verificationIndicates that a signup previously assessed as unknown_risk now has a new assessment, which can be low_risk or high_risk .
risk_decreaseIndicates that a signup previously assessed as high_risk was reassessed as low_risk .
risk_increaseIndicates that a signup previously assessed as low_risk was reassessed as high_risk .

Event notification policy#

Whenever we detect a modification in a given signup assessment, we attempt to notify it as fast as possible if your webhook endpoint is configured to receive it. Notifications are only sent for configured event types and for events from users which have been previously queried in our APIs by you.

Response codes#

When we send the POST request to your application, we wait 2 seconds for a response and assume a 4xx timeout response if no 2xx response is received during this window. Because of this, your application should send a 2xx response as quickly as possible when it receives the event.

Retry policy#

In the case of non 2xx responses, we attempt to notify the event again after 1 hour, increasing the retries count. If no 2xx response is received in time by this second attempt, we stop trying to notify this event to you.

Duplicate events#

Our product is built to handle the generation of duplicate events in a best-effort scenario. However, in the rare cases that duplicate events are notified to you, we suggest that your application should be able to correctly handle them.

Authenticating webhook requests#

To assert that a webhook request came from Incognia and not from a possible attacker, two authentication-related headers are included: Incognia-signature and Incognia-timestamp. The signature header holds an HMAC encrypted value which is generated in the following way:

  1. The JSON body is parsed to a String value as-is (keeping all characters). To do this, you may use most JSON parsing libraries available for your application's language;
  2. The timestamp contained in the Incognia-timestamp header is concatenated with the parsed body using a dot separator as such timestamp + "." + body;
  3. The signature content is HMAC SHA256 signed using Incognia's configured webhook secret as a secret key. The following code demonstrates how to do so in Java:
public class Signer {  private static final String ALGORITHM = "HMACSHA256";  private Mac mac;
  public Signer() throws NoSuchAlgorithmException {    mac = Mac.getInstance(ALGORITHM);  }
  public String sign(String data, String key) throws InvalidKeyException {    SecretKeySpec secretKeySpec =        new SecretKeySpec(StandardCharsets.US_ASCII.encode(key).array(), ALGORITHM);    mac.init(secretKeySpec);    return Hex.encodeHexString(        mac.doFinal(StandardCharsets.US_ASCII.encode(data).array()));  }

For authenticating the request, you should execute the algorithm above and compare the result with the signature provided in Incognia-signature header.

Protecting against replay attacks#

The Incognia-timestamp header value may also be utilized to protect your application from replay attacks, where an attacker may attempt to replicate a request that was previously made to your server with malicious intent.

Since the timestamp is also utilized in the signature generation, attackers aren't able to modify the timestamp without invalidating the signature in the process. Hence, if a request is received at a server UNIX time which makes the request timestamp too old, it may be discarded as a possible malicious request.