Getting started
Introduction
The CAMARA KYC Match API offers a standardized way for service providers (SP) to compare their user information with the verified KYC records held by the user's operator. This process helps the SP confirm the accuracy of the information and deliver specific services to the user.
API Scope
The current API implementation is applicable for Live Trials with Orange Belgium (preselected list of MSISDN).
Subscribe to the API
You get the Authorization header credentials when you register your application on the Orange Developer Console.
API Authentication
HTTPS requests to the REST API are protected with CIBA 3-Legged OAuth.
In short, the API Invoker (e.g. Application Backend or Aggregator) before requesting KYC match, needs to request a Three-Legged Access Token from Orange Authorization Server. The process follows the OpenID Connect Client-Initiated Backchannel Authentication (CIBA) flow.
Step 1: request the OAuth authorization code from the user device
The API Invoker provides in the authorization request (/bc_authorize) a login_hint with a valid User identifier together with the application credentials (client_assertion & client_assertion_type) and indicates the Purpose for processing Personal Data. The Orange implementation follows the CAMARA scope definition. The scope must be set to: opendid dpv:<dpvValue> <technicalParameter>
. dpv
stands for Data Privacy Vocabulary.
Note on JWT usage via client assertion: client_assertion
is a JWT used by a client to authenticate itself to an authorization server, while client_assertion_type
specifies the type of assertion being used, typically indicating it is a JWT. Together, they facilitate secure client authentication in OAuth 2.0 and OpenID Connect protocols. API consumer as to define JWK keystore in settings tab of the application in Orange Developer
For current implementation, only FraudDetectionAndPrevention
dpv value is managed, which means that to execute the KYC match process the scope in the bc-authorize
must be set to openid dpv:FraudPreventionAndDetection kyc-match
Orange Authorization Server will check if the owner of the phone number did not opted-out to authorize access to this data. If this is not the case a response 200 is sent back with a authorization request identifier (auth_req_id
). If the resource owner or OpenID Provider denied the request an error 403 Forbidden is sent back. Note: This is not yet available.
Request:
curl -X 'POST' \
'https://api.orange.com/openidconnect/ciba/be/v1/bc-authorize' \
-H 'accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'scope=openid%20dpv%3AFraudPreventionAndDetection%20kyc-match&login_hint=tel%3A%2B32493456721&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJraWQiOiJzYW...8jK9lM0nPqRstUvwXYZ'
Response:
200
Content-Type: application/json
{
"auth_req_id": "3f7b2e8a-9cde-4f3b-8b12-1a2b3c4d5e6f",
"expires_in": 120,
"interval": 2
}
Step 2: Request the OAuth access token
Once the client application gets the authorization code, the API Invoker polls the token endpoint by making an "HTTP POST" request by sending the grant_type (urn:openid:params:grant-type:ciba), auth_req_id (OperatorAuthReqId) and the the application credentials (client_assertion & client_assertion_type) parameters
If the transaction succeeds, in the POST
response, the acccess_token
is provided.
Request:
curl -X 'POST' \
'https://api.orange.com/openidconnect/ciba/be/v1/token' \
-H 'accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=urn%3Aopenid%3Aparams%3Agrant-type%3Aciba&auth_req_id=3f7b2e8a-9cde-...-1a2b3c4d5e6f&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJraWQiOiJzYW1wbGU...K9lM0nPqRstUvwXYZ'
Response:
200
Content-Type: application/json
{
"access_token": "G5kXH2wHvUra0sHlDy1iTkDJgsgUO1bN",
"token_type": "Bearer",
"refresh_token": "4bwc0ESC_IAhflf-ACC_vjD_ltc11ne-8gFPfA2Kx16",
"expires_in": 120,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6...rGvsIIwk1uExynJIv_tgZGE0eZI7MtVb2UlCwDQrVlg"
}
Step 3: Access protected resources using OAuth access token
In order to call our API, the access_token
is mandatory.
Specific documentation about KYC match resources is provided below.
API Description
This API is based on version 0.2 of the API kyc-match.
Summary of resources
This API has one resource match. This operation verifies matching of a number of attributes related to a customer identity against the verified data bound to their phone number in the Operator systems.
Summary of methods and URL
Use case of operation | URL method | required scope |
---|---|---|
I want to confirm (using my application server/backend service) the identity of a customer by comparison to MNO user's information. Information which could be provided are phone number, given name, family name, street address, city, country, region, postal code, birthdate, email address, etc. | POST "https://api.orange.com/camara/obe/kyc-match/v0.2/match" | openid dpv:FraudPreventionAndDetection kyc-match:match |
Summary of request body parameters
In bold parameters currently available in Orange Belgium KYC Match API:
Name | Type | Description | Mandatory |
---|---|---|---|
phoneNumber | string | Subscriber number in E.164 format (starting with country code). Optionally prefixed with '+' | No |
idDocument | string | Id number associated to the official identity document in the country. It may contain alphanumeric characters | No |
name | string | Complete name of the customer, usually composed of first/given name and last/family/sur- name in a country. Depending on the country, the order of first/give name and last/family/sur- name varies, and middle name could be included. It can use givenName, middleNames, familyName and/or familyNameAtBirth. For example, in Belgium, it is givenName + familyName | No |
givenName | string | First/given name or compound first/given name of the customer | No |
familyName | string | Last name, family name, or surname of the customer | No |
nameKanaHankaku | string | Complete name of the customer in Hankaku-Kana format (reading of name) for Japan | No |
nameKanaZenkaku | string | Complete name of the customer in Zenkaku-Kana format (reading of name) for Japan | No |
middleNames | string | Middle name/s of the customer | No |
familyNameAtBirth | string | Last/family/sur- name at birth of the customer | No |
address | string | Complete address of the customer. For some countries, it is built following the usual concatenation of parameters in a country. For Example in Belgium, it is streetName + streetNumber + houseNumberExtension | No |
streetName | string | Name of the street of the customer's address. It should not include the type of the street | No |
streetNumber | string | The street number of the customer's address. Number identifying a specific property on the 'streetName' | No |
postalCode | string | Zip code or postal code | No |
region | string | Region/prefecture of the customer's address | No |
locality | string | Locality of the customer's address | No |
country | string | Country of the customer's address. Format ISO 3166-1 alpha-2 | No |
houseNumberExtension | string | Specific identifier of the house needed depending on the property type. For example, number of apartment in an apartment building | No |
birthdate | string | The birthdate of the customer, in ISO 8601 calendar date format (YYYY-MM-DD) | No |
string | Email address of the customer in the RFC specified format (local-part@domain) | No | |
gender | string | Gender of the customer (Male/Female/Other) | No |
Example of Body value:
{
"phoneNumber": "+32495131517",
"givenName": "Maeva",
"familyName": "Huart",
"locality": "Evere",
"address": "Av. du Bourget 3 a, 1140 Evere",
"postalCode": "1140",
"country": "be",
"email": "maeva.huart@orange.be",
"birthdate": "1978-08-22"
}
Summary of response parameters
In bold parameters currently available in "KYC Match - CAMARA - Belgium - Client credentials" API
Name | Type | Description | Mandatory |
---|---|---|---|
idDocumentMatch | string | Indicates whether Id number associated to the id_document of the customer matches with the one on the Operator's system | No |
nameMatch | string | Indicates whether the complete name of the customer matches with the one on the Operator's system | No |
nameMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the name stored in the operator's system | No |
givenNameMatch | string | Indicates whether the complete given name of the customer matches with the one on the Operator's system | No |
givenNameMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the given name stored in the operator's system | No |
familyNameMatchMatch | string | Indicates whether last name/ family name/ surname of the customer matches with the one on the Operator's system | No |
familyNameMatchMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the family name stored in the operator's system | No |
nameKanaHankakuMatch | string | Indicates whether complete name of the customer in Hankaku-Kana format (reading of name) for Japan matches with the one on the Operator's system | No |
nameKanaHankakuMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the name in Hankaku-Kana format stored in the operator's system | No |
nameKanaZenkakuMatch | string | Indicates whether complete name of the customer in Zenkaku-Kana format (reading of name) for Japan matches with the one on the Operator's system | No |
nameKanaZenkakuMatchScore | float | Indicat es the similarity score assigned to the input value when it does not exactly match the name in Zenkaku-Kana format stored in the operator's system | No |
middleNamesMatch | string | Indicates whether the middle names of the customer matches with the one on the Operator's system | No |
middleNamesMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the middle names stored in the operator's system | No |
familyNameAtBirthMatch | string | Indicates whether the Family Name At Birth of the customer matches with the one on the Operator's system | No |
familyNameAtBirthMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the family name at birth stored in the operator's system | No |
addressMatch | string | Indicates whether complete address of the customer matches with the one on the Operator's system | No |
addressMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the address stored in the operator's system | No |
streetNameMatch | string | Indicates whether the street name of the customer matches with the one on the Operator's system | No |
streetNameMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the street name stored in the operator's system | No |
streetNumberMatch | string | Indicates whether the street number of the customer matches with the one on the Operator's system | No |
streetNumberMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the street number stored in the operator's system | No |
postalCodeMatch | string | Indicates whether the postal code / zip code of the customer matches with the one on the Operator's system | No |
regionMatch | string | Indicates whether the region of the customer's address matches with the one on the Operator's system | No |
regionMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the region stored in the operator's system | No |
localityMatch | string | Indicates whether the locality of the customer's locality matches with the one on the Operator's system | No |
localityMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the locality stored in the operator's system | No |
countryMatch | string | Indicates whether the country of the customer's address matches with the one on the Operator's system | No |
houseNumberExtensionMatch | string | Indicates whether the house number extension of the customer's address with the one on the Operator's system | No |
birthdateMatch | string | Indicates whether the birthdate of the customer matches with the one on the Operator's system | No |
emailMatch | string | Indicates whether the email address of the customer matches with the one on the Operator's system | No |
emailMatchScore | float | Indicates the similarity score assigned to the input value when it does not exactly match the email stored in the operator's system | No |
genderMatch | string | Indicates whether the gender of the customer matches with the one on the Operator's system | No |
Note that the algorithm applies normalization rules regarding spaces, special characters, and case for comparison purposes.
kyc match operation description
Request
curl -X POST "https://api.orange.com/camara/obe/kyc-match/v0.2/match"
-H "Authorization: Bearer {your access token}"
-H "Cache-Control: no-cache"
-H 'accept: application/json'
-H 'Content-Type: application/json'
-d {
"phoneNumber": "+32495131517",
"givenName": "Maeva",
"familyName": "Hurt",
"address": "Av. du Bourget 3 a, 1140 Evere",
"locality": "Evere",
"email": "maeva.huart@orange.be"
}
Response
200 Match successful
Content-Type: application/json
{
"giventNameMatch": "True",
"familyNameMatch": "False",
"familyNameMatchScore": 90,
"addressMatch": "True",
"localityMatch": "False",
"localityMatchScore": 95,
"emailMatch": "True"
}
Fields description
The response contains
- MatchResult attributes valued to
true
when user's information matches exactely with information held by the Operator,false
when it doesn't match exactly ornot_available
when the MNO doesn't hold user's information. - MatchScore, a numerical value that quantifies the similarity between two pieces of text based on the words they contain for some MatchResult attributes in case of value is equal to
false
.
Most frequent errors
If invalid or incomplete input are provided a 400 error is triggered.
HTTP/1.1 400 Error: bad Request
Content-Type: application/json
{
"status": 400,
"code": "INVALID_ARGUMENT",
"message": "Client specified an invalid argument, request body or query param"
}
If missing, invalid, or expired credentials an error 401 is send back
HTTP/1.1 401 Error: Unauthorized
Content-Type: application/json
{
"status": 401,
"code": "UNAUTHENTICATED",
"message": "Request not authenticated due to missing, invalid, or expired credentials."
}
If the service is not supported for the phone number, error code 422 is retrieved.
HTTP/1.1 422 Error: Unprocessable Content
Content-Type: application/json
{
"status": 422,
"code": "NOT_SUPPORTED",
"message": "Service not supported for this phoneNumber"
}
If the service is not up and running, a 503 error is sent.
HTTP/1.1 503 Service unavailable
Content-Type: application/json
{
"code": "UNAVAILABLE",
"status": 503,
"message": "Service unavailable"
}
History of document
Version of the document | modification date | description of modifications |
---|---|---|
1.0 | 08/01/2025 | initialization by Orange CAMARA APIs team |
2.0 | 13/01/2025 | change access to CIBA flow |
2.1 | 12/02/2025 | open id connect urls |