# Curata response service

## Overview

The Curata Response Service submits the outcomes of the biometric verification process of an applicant back to the Consumer. To achieve this, a receiving API on the end of the Consumer is required.

This API requires and endpoint with a JSON-encoded request body with the fields defined below. The response of this service does not require a payload to be returned, only a status code in the success range (200 – 299) is required. All standard HTTP response codes, authentication, and verbs must be implemented by the receiving API. All requests will be made over HTTPS.s

## Consumer API requirements

**Method:** POST

**URL:** To be supplied to Comcorp. This is the endpoint that would need to be exposed for us to send the response message to upon completion of the Curata process.

### Consumer API security

Curata supports the ability to integrate using a variety of header based authentication methods. The preferred method however, is to use an X-API-Key header method for authorisation.

## Curata response content

The content of the response will vary according to the version of Requesting API used, see [Curata API](/biometric-authentication/curata-api.md) for more details on the different versions.

For convenience, we'll devide this section into two, first detailing a normal `generatedynamiclink` v1 response, and then go into more detail on the differences when using `generatedynamiclink` v2.

### Response when using `generatedynamiclink` v1

Unless otherwise configured, the following default response content will be sent by the Curata Response service.

```json
{
	"consumerReference": "10000017",
	"consumerBusinessUnitId": "2130affb-f973-ef11-8582-00155d05b400",
	"transactionStatusId": 5,
	"consent": [],
	"dhaConsumerReference": "10055053",
	"transactionStatus": "Match Failed",
	"matchingScore": 65,
	"livenessScore": 68,
	"hanisReference": "95e4b10c-41cd-4d59-9ae1-9a08a49da016",
	"livenessAttempts": 1,
	"document": "Document Data",
	"documentData": {
		"curataReference": 10055053,
		"hanisReference": "95e4b10c-41cd-4d59-9ae1-9a08a49da016",
		"transactionStatus": "Match Failed",
		"identityNo": "7704285041083",
		"countryOfBirth": "South Africa",
		"firstName": "Gary",
		"firstNameReturned": "BARRY",
		"surname": "Gates",
		"surnameReturned": "BATES ",
		"idCard": "No",
		"idBookDateIssued": "2000-04-15",
		"idCardDateIssued": "",
		"deceasedStatus": "No",
		"maritalStatus": "Married",
		"dateOfMarriage": "2019-01-09",
		"gender": "Male",
		"hanisRetrievalDate": "2024-10-03T16:06:01.3742004+02:00",
		"digitalIdStatus": "Successful",
		"enquiryReference": "R-61071174",
		"citizenship": "South African",
		"dateOfBirth": "1977-04-28",
		"lastUpdated": "31 – 90 days ago",
		"identityType": "ID Book",
		"identityCountry": "South African ID",
		"title": "Mister"
	},
	"capturedImage": "Reference Image"
}
```

### Response when using `generatedynamiclink` v2

When using version 2 of `generatedynamiclink`, it is possible to request for - and receive - additional fields. Depending on the combination of your configuration with Comcorp and the additional fields requested, it is possible to obtain the full payload as depicted below:

```json
{
	"consumerReference": "FinX434",
	"consumerBusinessUnitId": "2130affb-f973-ef11-8582-00155d05b400",
	"transactionStatusId": 1,
	"transactionStatus": "Successful",
	"matchingScore": 65,
	"livenessScore": 68,
	"consent": [
		{
			"description": "Payslip",
			"consented": true
		},
		{
			"description": "Bank Statement",
			"consented": false
		}
	],
	"idRequestedVsIdReturned": "Match Failed",
	"documentValidationStatus": "Invalid",
	"document": "JVBE=",
	"hanisReference": "94755ad7-dd87-46f7-9547-4b5da852f40d",
	"dhaConsumerReference": "10056233",
	"livenessAttempts": 1,
	"documentData": {
		"curataReference": 10056233,
		"nameRequested": "Brandon",
		"nameReturned": "Brandon",
		"surnameRequested": "Sanderson",
		"surnameReturned": "Sanderson",
		"identityNo": "7512195021085",
		"countryOfBirth": "South Africa",
		"idCardIssued": "Yes",
		"idBookDateIssued": "1989-01-31",
		"idCardDateIssued": "2018-01-09",
		"deceasedStatus": "No",
		"gender": "Male",
		"maritalStatus": "Married",
		"dateOfMarriage": "2006-01-09",
		"hanisReference": "94755ad7-dd87-46f7-9547-4b5da852f40d",
		"hanisRetrievalDate": "2024-12-03T12:32:42.5182006+02:00",
		"digitalIdStatus": "Successful",
		"digitalIdStatus": "Successful",
		"enquiryReference": "R-61071174",
		"citizenship": "South African",
		"dateOfBirth": "1975-12-19",
		"lastUpdated": "31 – 90 days ago",
		"identityType": "ID Card",
		"identityCountry": "South African ID",
		"title": "Mister"
	},
	"extractedDocumentData": {
		"curataReference": 10056776,
		"initials": "B",
		"intialsWordConfidence": 0.94,
		"names": "Brandon",
		"namesWordConfidence": 0.99,
		"surname": "Sanderson",
		"surnameWordConfidence": 0.9,
		"identityNumber": "7512195021085",
		"identityNumberWordConfidence": 0.994,
		"passportNumber": "A07508438",
		"passportNumberWordConfidence": 0.9,
		"licenseNumber": 123456789012,
		"licenseNumberWordConfidence": 0.0,
		"dateOfBirth": "1975-12-19T00:00:00",
		"dateOfBirthWordConfidence": 0.993,
		"nationality": "ZAF",
		"nationalityWordConfidence": 0.951,
		"sex": "M",
		"sexWordConfidence": 0.992,
		"dateOfIssue": "2019-05-16T00:00:00",
		"dateOfIssueConfidence": 0.994,
		"dateOfExpiry": "2029-05-15T00:00:00",
		"dateOfExpiryConfidence": 0.994,
		"countryOfIssue": "ZA",
		"countryOfIssueWordConfidence": 0.18,
		"digitalIdStatus": "Successful"
	},
	"documentValidationResults": {
		"metadataCheckPass": {
			"isValid": true,
			"status": "Success",
			"probability": 0,
			"spliceMap": null
		},
		"greyScaleCheckPass": null,
		"photocopyCheckPass": {
			"isValid": true,
			"status": "0% possibility of being photocopied",
			"probability": 0,
			"spliceMap": null
		},
		"recapturedCheckPass": {
			"isValid": true,
			"status": "19% possibility of being recaptured",
			"probability": 19,
			"spliceMap": null
		},
		"spliceDetectionCheckPass": {
			"isValid": true,
			"status": "0% possibility of being spliced",
			"probability": 0,
			"spliceMap": "iVBORw0KGgoAAAANSUhEUgAA5ErkJggg=="
		},
		"securityZoneCheckPass": {
			"isValid": false,
			"status": "Specified country code not supported.",
			"probability": 100,
			"spliceMap": null
		}
	},
	"documentValidationErrors": "",
	"backImage": "/9j/4QJRgABAQAAE5RZgAA...",
	"spliceMapImage": "iVBORw0KGgoAAAANSUhEUgAAAX8gg==",
	"documentTypeSelected": "passport",
	"documentTypeDerived": "greenbook",
	"capturedImage": "data:image/jpeg;base64,/9j/4AAQSkZJ2Q==",
	"extractedImage": "/9j/4AAQSkZJR9k=",
	"uploadedDocumentImage": "/9j/4Q==",
	"matchingImageUsed": "Uploaded photo"
}
```

### Field summary

The presence of the fields in the summary below is dependent on the Provider.\
Fields that are not returned by the Provider will be omitted from both the certificate and the raw data.

* `consumerReference` | string | *not-null* |: Reference provided by the user to track calls. Not used by Comcorp.
* `consumerBusinessUnitId` | guid | *not-null* |: Unique ID for the Consumer Business Unit. Provided during onboarding.
* `transactionStatusId` | int | *not-null* |: Numeric code of the transaction status. See [Transaction Statuses](#transaction-statuses) for more information
* `transactionStatus` | string | *not-null* |: Text description of the transaction status.
* `matchingScore`| int | *nullable* |: percentage value of the probability/score of matching between Provider/Reference image and Curata image.&#x20;
* `livenessScore`| int | *nullable* |: percentage value of probability/score of liveness of the Curata process.
* `consent` | array | *not-null* | \***only supplied when `verificationType`=1** : List of consent items for the transaction, including:
  * `description` | string | *not-null* |: Description of the consented item (e.g., "Payslip").
  * `consented` | boolean | *not-null* |: Indicates whether consent was given for the item.
* `idRequestedVsIdReturned`  | string | *nullable* |: Status indicating whether the requested ID number matches the ID number extracted from the uploaded document.
* `documentValidationStatus` | string | *nullable* |: Status indicating the result of the Document Validation step.
* `document` | string (Base64) | *nullable* | \***only supplied when `IncludeDocumentData`=true in `generatedynamiclink` request OR configured by Comcorp** : Base64 encoded PDF document for Curata Certificate.
* `hanisReference` | guid | *nullable* |: Unique reference number from the HANIS system. Will be present if the request routes to the DHA Provider for verification, otherwise it will not be present.
* `dhaConsumerReference` | string | *not-null* |: Reference number used by Curata system sent to the Provider.
* `livenessAttempts` | int | *not-null* |: Number of liveness verification attempts made.
* `documentData` | object | *not-null* | \***only supplied when `IncludeDocumentData`=true in `generatedynamiclink` request OR configured by Comcorp** : JSON representation of the data returned from DHA used in creating the PDF certificate. Includes the fields:
  * `curataReference` | int | *not-null* |: Internal reference for the document.
  * `nameRequested` | string | *not-null* |: Name submitted for verification.
  * `nameReturned` | string | *nullable* |: Name returned by Home Affairs.
  * `surnameRequested` | string | *not-null* |: Surname submitted for verification.
  * `surnameReturned` | string | *nullable* |: Surname returned by Home Affairs.
  * `identityNo` | string | *not-null* |: Identity number of the subject/person, as returned by the Provider.
  * `countryOfBirth` | string | *nullable* |: Country where the subject was born.
  * `idCardIssued` | string | *nullable* |: Indicates if an ID card was issued ("Yes" or "No").
  * `idBookDateIssued` | string (date) | *nullable* |: Date when the ID book was issued.
  * `idCardDateIssued` | string (date) | *nullable* |: Date when the ID card was issued.
  * `deceasedStatus` | string | *nullable* |: Indicates if the subject is deceased ("Yes" or "No").
  * `gender` | string | *nullable* |: Gender of the subject (e.g., "Male").
  * `maritalStatus` | string | *nullable* |: Marital status of the subject (e.g., "Married").
  * `dateOfMarriage` | string (date) | *nullable* |: Date of marriage, if applicable.
  * `hanisReference` | guid | *nullable* |: Will be present if the request routes to the DHA provider for verification, otherwise it will not be present..
  * `hanisRetrievalDate` | string (datetime) | *not-null* |: Date and time when the HANIS record was retrieved.
  * `digitalIdStatus` | string | *not-null* |: Status of the digital ID verification process (e.g., "Successful").
  * `enquiryReference` | string | nullable | Will be present if the request routes to the DHA Snapshot provider for verification, otherwise it will not be present
  * `citizenship` | string | nullable | Value of the country of your citizenship according to your issued identity document
  * `dateOfBirth` | string | nullable | Value of your date of birth according to your issued identity document
  * `lastUpdated` | string | nullable | Range of when the data returned was last updated
  * `identityType` | string | nullable | Identity type of the document issued
  * `identityCountry` | string | nullable | Identity country of the document issued
  * `title` | string | nullable | Title of the identity verification process subject
* `extractedDocumentData` | object | not-null | \***only supplied when `IncludeExtractedDocumentData=true` in `generatedynamiclink` request OR configured by Comcorp**: JSON representation of data extracted directly from the provided identity document using OCR, including:
  * `curataReference` | int | not-null |: Internal reference for the extracted document data.
  * `initials`|string | *nullable* |: Initials extracted from a *driver's license*, if available.
  * `initialsWordConfidence` | decimal (0.000 - 1) | *nullable* |: Confidence score for the extracted initials.
  * `names` |string | *nullable* |: First name(s) extracted from the document.
  * `namesWordConfidence` | decimal (0.000 - 1) | *nullable* |: Confidence score for the extracted first name(s).
  * `surname` | string | *nullable* |: Surname extracted from the document.
  * `surnameWordConfidence` | decimal (0.000 - 1)| *nullable* |: Confidence score  for the extracted surname.
  * `identityNumber` | string | *nullable* |: Identity number extracted from the document.
  * `identityNumberWordConfidence` | decimal (0.000 - 1) | *nullable* |: Confidence score  for the extracted identity number.
  * `passportNumber` | string | nullable |: Passport number extracted from *a passport*, if available.
  * `passportNumberWordConfidence` | decimal (0.000 - 1) | nullable |: Confidence score for the extracted passport number.
  * `licenseNumber`| string | nullable |: License number extracted from a *driver's license*, if available.
  * `licenseNumberWordConfidence` | decimal (0.000 - 1) | nullable |: Confidence score for the extracted license number.
  * `dateOfBirth` | string (date) | *nullable* |: Date of birth extracted from the document.
  * `dateOfBirthWordConfidence` | decimal (0.000 - 1) | *nullable* |: Confidence score  for the extracted date of birth.
  * `nationality` | string | not-null |: Nationality extracted from the document (ISO 3166-1 alpha-3 code).
  * `nationalityWordConfidence` | decimal (0.000 - 1) | *nullable* |: Confidence score for the extracted nationality.
  * `sex` | string | *nullable* |: Gender extracted from the document (e.g., "M" or "F").
  * `sexWordConfidence` | decimal (0.000 - 1) | *nullable* |: Confidence score for the extracted gender.
  * `dateOfIssue` | string (date) | *nullable* l |: Date when the document was issued.
  * `dateOfIssueConfidence` | decimal (0.000 - 1) | *nullable*  |: Confidence score for the extracted date of issue.
  * `dateOfExpiry` | string (date) | *nullable*  |: Expiry date of the document.
  * `dateOfExpiryConfidence` | decimal (0.000 - 1) | *nullable*  |: Confidence score for the extracted expiry date.
  * `countryOfIssue`| string | *nullable*  |: Country of issue for the extracted *driver's license*, if available.
  * `countryOfIssueConfidence` | decimal (0.000 - 1) | *nullable*  |: Confidence score for the extracted driver's license.
  * `digitalIdStatus`  | string | *nullable* |: Status of the digital ID verification process (e.g., "Successful").
* `documentValidationResults` | object | *nullable* | Contains the results of validation checks performed on the uploaded document. \***Note:** In most cases below, the isValid field should not be used verbatim, rather, the probability should be used and interpreted.&#x20;

  * `metadataCheckPass` | object | *nullable* | Indicates whether the metadata check passed.
    * `isValid` | boolean | *nullable* | Indicates whether the document passed the metadata check.
    * `status` | string | *nullable* | Descriptive interpretation of check results, forwarded from Comcorp's provider.
  * `greyScaleCheckPass` | boolean | *nullable* | **\*Deprecated.** Indicates whether the grayscale check passed.
  * `photocopyCheckPass` | object | *nullable* | Indicates probability of the document being a photocopy of an original.
    * `isValid` | boolean | *nullable* | Indicates whether the document passed the photocopy check.
    * `status` | string | *nullable* | Descriptive interpretation of probability, forwarded from Comcorp's provider.
    * `probability` | int | *nullable* | Represents the probability (percentage) that the document is a photocopy of an original.
  * `recapturedCheckPass` | object | *nullable* | Indicates the probability of the document being a screencapture or photo-of-a-photo of the original.
    * `isValid` | boolean | *nullable* | Indicates whether the document passed the recaptured check.
    * `status` | string | *nullable* | Descriptive interpretation of probability, forwarded from Comcorp's provider..
    * `probability` | int | *nullable* | Represents the probability (percentage) that the document is a screencapture or photo-of-a-photo of the origina.
  * `spliceDetectionCheckPass` | object | *nullable* | Indicates probability of image being spliced.
    * `isValid` | boolean | *nullable* | Indicates whether the document passed the splice detection check.
    * `status` | string | *nullable* | Descriptive interpretation of probability, forwarded from Comcorp's provider..
    * `probability` | int | *nullable* | Represents the probability (percentage) that the document is spliced.
    * `spliceMap`| string | *nullable* | Represents the probability (percentage) that the document is spliced.
  * `securityZoneCheckPass` | object | *nullable* | Contains result of security zone checks.
    * `isValid` | boolean | *nullable* | Indicates whether the document passed the security zone check.
    * `status` | string | *nullable* | Descriptive interpretation of security zone check results, forwarded from Comcorp's provider.
    * `probability` | int | *nullable* | Represents the probability (percentage) that the document didn't pass security zone checks.

  `documentValidationError` | string | *nullable* | Contains any error message related to the document validation process. Null if no errors occurred.
* `documentTypeSelected` | string - enumerated | *nullable* | Text value of the type of document to be uploaded, selected by the user during the Curata process. See section [Document Types](#documenttype-values) for list of document types.
* `documentTypeDerived`| string - enumerated | *nullable* | Text value of the type of document identified by the document extraction process. See section [Document Types](#documenttype-values) for list of document types.
* `capturedImage` | string (Base64) | *nullable* |: Base64 encoded image captured during the Curata verification process.
* `extractedImage` | string (Base64) | *nullable* | \***only supplied when `IncludeExtractedImage`=true in `generatedynamiclink` request** : Base64 encoded image extracted from the ID Document photo.
* `uploadedDocumentImage` | string (Base64) | *nullable* | \***only supplied when `IncludeUploadedDocumentImage`=true in `generatedynamiclink` request** : Base64 encoded image of the original uploaded document.
* `matchingImageUsed` | string | *not-null* |: Base64 encoded image of the image used to match against the `capturedImage`. Used by consumer to differentiate between `referenceImage` or `extractedImage` used for matching if both was supplied.
* `backImage`| string (Base64) | *nullable* | \***only supplied when `IncludeUploadedDocumentImage`=true in `generatedynamiclink` request** : Base64 encoded image of the back of the original uploaded document.
* `spliceMapImage`| string (Base64) | *nullable* | Base64 encoded image of the splice map returned from the document Validation step, indicating splicing issues in a visual manner.

### Transaction statuses

One of he following transaction statuses will be returned in the `transactionStatusId` and `transactionStatus` fields respectively.

| Status ID | Message                                               |
| --------- | ----------------------------------------------------- |
| 1         | Successful                                            |
| 2         | Liveness Failed                                       |
| 3         | No Image available at Source Image Provider           |
| 4         | Source Image Provider Unavailable                     |
| 5         | One to One Match Failed                               |
| 6         | Validation Error                                      |
| 7         | Internal System Error                                 |
| 8         | Partial Match                                         |
| 9         | Consent Declined for Source Image Provider (Liveness) |
| 10        | Consent Declined for Data/Documents                   |
| 11        | Provider System Error                                 |
| 12        | No Camera Detected                                    |
| 13        | No Camera Access Provided                             |
| 14        | Face Extraction Failed                                |
| 15        | Link Expired - Liveness Failed                        |
| 16        | Link Expired - Face Extraction Failed                 |

> **Status ID 15 & 16** are returned when a user accesses a link, fails the liveness check or document fail face extraction, and does not complete the process within the configured expiration time.  Note that these status are only processed at 15 minute intervals. So the maximum time to wait for such a response will be:  configured-expiration-time + 15 minutes.

### Document Type values

<table><thead><tr><th>Value</th><th width="194">Numeric Significance</th><th>Description</th></tr></thead><tbody><tr><td>other</td><td>0</td><td>Unidentified or not yet supported document type</td></tr><tr><td>license</td><td>1</td><td>RSA drivers license</td></tr><tr><td>passport</td><td>2</td><td>Passport</td></tr><tr><td>idcard</td><td>3</td><td>RSA ID card</td></tr><tr><td>greenbook</td><td>4</td><td>RSA ID book</td></tr></tbody></table>

## Configuration concepts

The response received by the Consumer may be customised by one, or both, of the following ways:

1. Comcorp managed configuration.
2. Request-time configuration.

### 1. Comcorp managed configuration

Comcorp can configure your response to always be returned in a certain way. The following is a list of fields that can be returned or omitted. Note that this configuration will always be maintained unless overridden by the `responseFields` field in the `generatedynamiclink` request.

* PDF Document: `document` field is present in Curata response payload. \***Note:** This field will always be configured to return by default during the onboarding process
* Document Data: `documentData` field is present in Curata response payload.
* Captured Image: `capturedImage` field is present in Curata response payload.

### 2. Request-time configuration

At any time the response can be customised when making a request to the `generatedynamiclink` endpoint. See [Curata API](/biometric-authentication/curata-api.md) for more information when requesting this way. Specifying the response fields in this way will override any configuration managed by Comcorp. Note that at this time, the only way to receive certain fields will be to specify them during this step, as this feature extends on the configuration offered by Comcorp.

The following fields may be present based on the configuration issued when requesting:

* `IncludeCapturedImage` = true : `capturedImage` field is present in Curata response payload.
* `IncludeDocument` = true : `document` (PDF Document) field is present in Curata response payload.
* `IncludeDocumentData` = true : `documentData` field is present in Curata response payload.
* `IncludeExtractedImage` = true : `extractedImage` field is present in Curata response payload. \**Only if `UseDocUpload` flag was specified during request*
* `IncludeUploadedDocumentImage` = true : `uploadedDocumentImage` field is present in Curata response payload. \**Only if `UseDocUpload` flag was specified during request*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.comcorp.co.za/biometric-authentication/curata-response-service.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
