PinLetters
Describes the rational behind the “PinLetters” concept, the technicalities to obtain short codes and pins for further processing as well as the integration with the “normal” CrefoTrust process.
Current Version: v4
This document describes how to use the CrefoTrust API as a Verifier.
CrefoTrust at it’s core provides a simple way to retrieve and store certain information about a Digital Identity the Holder and provides the mechanisms to present this information to a third party, the Verifier.
Concise information packages (semantical entities) are called Credentials. They encapsulate either facts about a single natural or legal person (a company) or facts about relationships between people and companies. Furthermore Credentials have differing levels of assurance, depending on their origin (the credential’s issuer)) and implicitely on their collection method.
How CrefoTrust actually works can be best described with an example:
Besides this “normal” process, CrefoTrust provides a second approach, which can be appropriate when the personal data (like name, address and such) are not relevant and you need only a weak level of assurance, that the actor is associated with the company in question. This approach is called “PinLetters” and is detailed here.
To integrate with CrefoTrust as a Verifier you need to get authentication information: a verifier ID and an API key. To acquire those, please contact: support@crefotrust.de.
The process starts with placing an order with the CrefoTrust order service. To do this you call the API endpoint: /orders with the method: POST.
We have different environments with different URLs. For development and integration purposes use:
https://api-cust.crefotrust.de/api/orders
For production use:
https://api.crefotrust.de/api/orders
CAUTION: you must call the API only from your backend, otherwise the authentictation information might get extracted, and potentially abused.
To authenticate with the CrefoTrust order service, place the API key which you received by the CrefoTrust team into the request header under the header key: x-crefotrust-key. Futhermore you have to provider your verifier id for each request. You can either do so by adding the custom header x-verifier-id to your requests or by adding it in the body, see webhook request for details.
With the request body you define the details of the order. This can be (and usually is) different for different business processes.
Here is an example:
{
"requiredCredentials": {
"person": ["name", "nationality", "birthdate"],
"authorizedRepresentative": true,
"org": ["legalName", "address"]
},
"webhook": "https://api.my-backend-system.de/webhook",
"redirect": {
"success": "https://www.my-frontend.de/success.html",
"failure": "https://www.my-frontend.de/error.html"
},
"options": {
"useCase": "UBO",
"verifierName": "My Brand Name",
"verifierRef": {
"referenceId": "my_reference_id",
"correlationId": "my_correlation_id",
"userId": "my_user_id"
}
},
"acceptedIdMethods": ["itm_videoident", "nect_autoident"],
"offeredIdMethods": ["itm_videoident"],
"forOrg": {
"mandatory": true,
"crefoId": "8170295838"
},
"forPerson": {
"mandatory": true,
"crefoId": "8170295838"
}
}
Here you define which information you require from your customer in order to continue in your business process (all currently available credentials are listed under point 5). The credentials are grouped by person and org. Furthermore you can request the relationship credentials: “authorizedRepresentative” and “companyAgent” on the root level. These relationship credentials explicitely define how a person and a organization are connected. Subsequent relationships will be implemented in the future.
You define where the data will be send as soon as it’s available, the orderID will be attached as a path element, e.g.: “https://api.my-backend-system.de/webhook/[orderID]”. You have to establish an endpoint, that can be accessed from the CrefoTrust Backend Systems. If you require to setup an authentication method, you can provide a header name and value, which will be used on every webhook call. If you need to whitelist our IP addresses please feel free to contact us.
Provide an object with the URLs your customer will be sent after they finish the CrefoTrust process. One for the positive (success) and one for the negative (failure) case.
Similar to the webhook, the orderID will be attached at the end of the provided URLs (as an URL parameter with the name orderId), e.g.: https://www.my-frontend.de/success.html?orderId=[orderID] and https://www.my-frontend.de/error.html?orderId=[orderID]. This can be convenient when you want to send your customer into a tailored process.
The useCase property is optional. It enables multiple integration scenarios for a single Verifier. For more information refer the chapter on Use Cases.
With verifierName you may customize the name that will be displayed to the customer in the CrefoTrust frontend during the verification process.
With verifierRef you can provide your own IDs (for example a userID or correlationID) that will be sent back unaltered as part of the webhook request’s data.
The following limitations will be enforced:
Here you can define which of the possible identification methods you do accept as part of your business process. Currently we are supporting Video Ident by IdNow (originally ITM), Auto Ident by Nect and the new PinLetter Ident method.
To be backwards compatible, the default is set to Video Ident only. To enable Auto Ident which doesn’t involve an agent, add “nect_autoident” to the array of accepted ID methods, e.g.:
{
...
acceptedIdMethods: ["nect_autoident", "itm_videoident"]
...
}
If your customer already is a registered and identified CrefoTrust user acceptedIdMethods decides, if the identification process the customer has already successfully partaken in, is acceptable for you; or if the customer needs to go through another one.
Here you can define which of the possible identification methods you do offer your customers as part of your business process.
The same options and rules as with accepted ID methods apply here.
Offered ID methods becomes relevant when the customer is new to CrefoTrust. So here you decide which of the available ID methods the customer can choose from, while going through the CrefoTrust process.
Monetary considerations might play a role here, since the different ID methods usually inflict different costs (depending on your contract).
Here you can define which company will be preselected in CrefoTrust. Either unchangeable for the user (“mandatory”: true) or preselected but editable.
In order to use this option you need the Crefonummer for the company in question. If you don’t know what that is or how to get it, please get in touch with us (support@crefotrust.de).
Here you can define which person will be preselected in CrefoTrust. This works only in conjunction with forOrg. It can be defined as unchangeable for the user (“mandatory”: true) or preselected but editable. If forPerson is mandatory forOrg has to be mandatory as well.
Furthermore has the Person-Crefonummer to be known in the context of the company defined in forOrg.
Failing to adhere to this rule will result in a rejected order.
In order to use this option you need the Crefonummer for the person in question. If you don’t know what that is or how to get it, please get in touch with us (support@crefotrust.de).
When the order is successfully placed the request responds with an orderId and an URL to which your customer needs to get forwarded to, to start the CrefoTrust process for that customer and that order. If you have provided more information with your order by using the verifierRef field, this value is also returned.
{
"orderId": "[SOME_UUID]",
"url": "https://crefotrust.de/[SOME_UUID]",
"verifierRef": {
"referenceId": "my_reference_id",
"correlationId": "my_correlation_id",
"userId": "my_user_id"
}
}
You can do this client side, e.g. via an anchor tag or a button. Or you might want to redirect directly from your server.
In case your user is unable to provide all the information that you require, the user is redirected to your “failure” redirect URL.
In case the user has successfully acquired all information and is willing to present them to you, the user will be redirected to your “success” redirect URL.
In either case, the URL will be expanded with an oderId query parameter, so that you can relate the outcome of the CrefoTrust process with the order that initiated it, e.g.:
https://your.frontend.com/success.html?orderId=[ORDER_ID]
Currently three identification methods of three different ID providers can be used with CrefoTrust. These are:
To support distinct business processes a Verifier might need different information from the business partner in question. Therefor we have extended the CrefoTrust API to support use cases. A use case
The Verifier can setup different
Every Verifier must have a default use case. It is used as a fallback, when an order is created that doesn’t explicitely defines a use case. During the onboarding process of new Verifiers this will be setup for them.
When you as a Verifier need additional use cases please contact us. We will happily help you out with the details.
We are planning to openly provide and support API endpoints that can be used to manage use cases yourself. There already exists a crude alpha version. You can find the Swagger specs for creating additional use cases here:
https://pin-cust.crefotrust.de/docs#/OrderPresets/PinOrderPresetsUseCaseController_addPinOrderPresetUseCase
And updating existing use cases here:
https://pin-cust.crefotrust.de/docs#/OrderPresets/PinOrderPresetsUseCaseController_updatePinOrderPresetUseCase
ATTENTION: Both endpoints are NOT ready for production use and will likely change in future versions.
After finishing the CrefoTrust process - and consenting to present the information to you - your webhook is called, with the HTTP POST method. The request body is JSON encoded and contains the orderId from order response as well as the requested information about your customer.
Additionally, the orderId will be attached to the path of your webhook. Like so:
https://your.webhook.com/ordersIncoming/[ORDER_ID]
For security reasons you might want to give us an API and Header key during onboarding to authenticate the webhook request at your backend. You can provide usa with a header name and value, which will then be used on every webhook call. If you need to whitelist our IP addresses please feel free to mention this as well.
Here is an example of a request body send to the webhook (matching the order from above):
{
"orderId": "[THE_ORDER_ID_FROM_2c]",
"meta": {... see below ...},
"person":{
"crid": "somenumber",
"name":{
"familyName":"Mustermann",
"givenName":"Erika"
},
"birthdate":"1964-05-03",
"nationality":"DE"
},
"authorizedRepresentative": true,
"verifiedAgent": true,
"org":{
"legalName":"Test-Firma",
"address":{
"streetAddress":"Teststraße 1a",
"postalCode":"12345",
"addressLocality":"Teststadt",
"addressCountry":"DE"
}
}
(all options and their structure are in 4)
Meta Data
Along with the actually requested data we are providing meta information. On the top level the meta data has the following fields
For each credential the following set of meta data will be provided:
Besides this meta data available for every credential, the authorizedRepresentative and the verfiedAgent credential have got two more properties, essentially semantically joining the company and person by their relationship:
{
...
"meta": {
"verifier": "[VERIFIER-ID]",
"verifierRef": {
"referenceId": "my_reference_id",
"correlationId": "my_correlation_id",
"userId": "my_user_id"
},
"person": {
"id": "did:web:api.crefotrust.de:user:cb3e2e60-a8f8-4bdd-9fe1-fb490e0edefc",
"credentials": {
"name": {
"issuedAt": 1658400571,
"status": "https://api.crefotrust.de/api/credentials/abc1a061-7cba-43f8-ad23-800b6f993dda/status",
"issuer": "did:web:api.crefotrust.de"
},
"birthdate": {
"issuedAt": 1658400571,
"status": "https://api.crefotrust.de/api/credentials/abc1a061-7cba-43f8-ad23-800b6f993dda/status",
"issuer": "did:web:api.crefotrust.de"
},
"nationality": {
"issuedAt": 1658400571,
"status": "https://api.crefotrust.de/api/credentials/abc1a061-7cba-43f8-ad23-800b6f993dda/status",
"issuer": "did:web:api.crefotrust.de"
}
}
},
"authorizedRepresentative": {
"issuedAt": 1658400571,
"person": "did:web:api.crefotrust.de:user:cb3e2e60-a8f8-4bdd-9fe1-fb490e0edefc",
"org": "did:web:crefotrust.de:org:1234567890",
"status": "https://api.crefotrust.de/api/credentials/abc1a061-7cba-43f8-ad23-800b6f993dda/status",
"issuer": "did:web:api.crefotrust.de"
},
"verifiedAgent": {
"issuedAt": 1658400571,
"person": "did:web:api.crefotrust.de:user:cb3e2e60-a8f8-4bdd-9fe1-fb490e0edefc",
"org": "did:web:crefotrust.de:org:1234567890",
"status": "https://api.crefotrust.de/api/credentials/abc1a061-7cba-43f8-ad23-800b6f993dda/status",
"issuer": "did:web:api.crefotrust.de"
},
"org": {
"id": "did:web:crefotrust.de:org:1234567890",
"credentials": {
"legalName": {
"issuedAt": 1658400571,
"status": "https://api.crefotrust.de/api/credentials/abc1a061-7cba-43f8-ad23-800b6f993dda/status",
"issuer": "did:web:api.crefotrust.de"
},
"address": {
"issuedAt": 1658400571,
"status": "https://api.crefotrust.de/api/credentials/abc1a061-7cba-43f8-ad23-800b6f993dda/status",
"issuer": "did:web:api.crefotrust.de"
}
}
}
},
...
}
To get the current state of a previously successfully placed [order], you issue an GET request against the /orders/[ORDER_ID] endpoint.
You have to submit your API key in the header x-crefotrust-key, like you did when placing the order.
The request itself is a simple GET call to the /orders/[ORDER_ID] endpoint. With an empty body. Your verifier ID will be deferred from the order ID.
You will receive the current state of the order in the response body, json encoded. Here is an example response:
{
"orderId": "[THE_ORDER_ID]",
"verifierId": "[THE_VERIFIER_ID_GIVEN_TO_YOU]",
"requiredCredentials": {
"person": ["name", "address"],
"org": ["legalName", "address"]
},
"webhook": "https://your.backend.service/customerdata",
"redirect": {
"success": "https://your.frontend.after.process.succeeded",
"failure": "https://your.frontend.after.process.failed"
},
"options": {
"verifierName": "[YOUR BRAND]",
"verifierRef": {
"referenceId": "my_reference_id",
"correlationId": "my_correlation_id",
"userId": "my_user_id"
}
},
"state": [
{
"code": 0,
"timestamp": "2021-03-04T19:33:01.002Z",
"comment": "order created"
},
{
"code": 2,
"timestamp": "2021-03-04T19:33:02.102Z",
"comment": "logged in"
}
//see full list of states below
]
}
The states in the state history are not guaranteed to be ordered in any way. You can’t defer the order from their code, also. If you need a chronological order of states, you might want to sort by timestamp.
Not all states have to be present in the order state history. For example the Account Created state will only show up when your customer registers with CrefoTrust for the first time.
States are not unique: for example, when your customer first logs in via a web browser, but later decides to finish the process via smartphone, there will be two distinct logged-in events and therefore states, that show up in the state history.
Every state has a timestamp, which is a RFC3339 timestamp string at Zulu time.
If a state represents an error or failure case it has an additional field named error, giving some details about the situation; so that you might be able to solve the issue. These error states have a code greater than 100.
Every successfully placed order has this state exactly once in its state history.
{
"code": 0,
"timestamp": "2021-08-06T12:23:45.156Z",
"comment": "order created"
}
The customer has successfully created an CrefoTrust account. This state exists only once, for every CrefoTrust user account. And naturally will be missing in subsequent orders.
{
"code": 1,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "account created"
}
The customer has successfully logged into her CrefoTrust account. This state can exist multiple times even for a single order.
{
"code": 2,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "logged in"
}
The customer has successfully initiated a request to get her identity verified by our identification partner.
The request with our identification partner has a limited lifespan and will be deleted after 14 days. If an order is not progressing past this state, it will be deleted after 14 days as well.
When the customer is unable to successfully complete the identification process for whatever reason, this state will not be left, until the order times out.
{
"code": 3,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "request created"
}
When the customer successfully finishes, the identification process this state is set. In the default case, this state can only be reached once per user account. In edge cases, for example, when the user changes her name, the identification process has to be done again. So, this state and the prior state are not guaranteed to be unique per user account (probably even not unique per order).
{
"code": 4,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "person verified"
}
When your customer data collected during the identification process matches the data of the company representative she selected, this state will be set.
{
"code": 5,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "person is authorized representative"
}
When your webhook could be reached and responded with a 200 HTTP code upon sending the requested information, the Data Sent state will be reached, which also marks the successful end of the process. No further states should be expected.
{
"code": 6,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "data sent"
}
When the customer didn’t proceed with the order for more than 14 days, the order will be (soft) deleted and the final state Timed Out will be reached.
{
"code": 101,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "timed out",
"error": "customer didn't proceed for 14 days"
}
Next step: if this case happens, it’s probably advisable to contact your customer and ask for details (if this is appropriate in your business context).
When CrefoTrust is unable to connect to your webhook or when your webhook responds with a something other than the 200 HTTP code, then this state will be set.
{
"code": 102,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "delivery error",
"error": "received: 500 - Internal Server Error"
}
Next step: When this happens please verify that your webhook is working correctly and can be accessed from the outside of your network. A common gotcha might be a self-signed certificate. In case you need to update the webhook, you need to place a new order with CrefoTrust, contact your customer and ask her to send the data again. If the webhook is correct and there was a temporary outage, the customer can pickup the old order and try to send the data again.
When the customer actively cancels (for whatever reason) the CrefoTrust process at any time, this state will be set. This can happen multiple times. As a result the order remains open (until it times out after 14 days) and the customer might pick up the CrefoTrust process later, using the initial link (including the OrderID).
{
"code": 103,
"timestamp": "2021-08-06T12:24:25.256Z",
"comment": "process canceled",
"error": "customer actively canceled the process"
}
Next step: This usually happens when the customer realizes she is not listed as a representative. Or eventually when she feels uncomfortable sharing the information that is requested. Active user research is underway to pinpoint reasons for cancelling the process. No action is required from your side.
An object with the full name of that person, according to the ID document presented during the CrefoTrust process.
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"person": ["name"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
//...
"person": {
"name": {
"familyName": "Musterfrau",
"givenName": "Alexa"
}
}
//...
}
An object with the postal address of that person, according to the ID document presented during the CrefoTrust process.
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"person": ["address"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
//...
"person": {
"address": {
"streetAddress": "Goethestraße 45",
"postalCode": "43113",
"addressLocality": "Bochum",
"addressCountry": "Deutschland"
}
}
//...
}
A string with the person’s birthdate, according to the ID document presented during the CrefoTrust process.
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"person": ["birthdate"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
"person": {
"birthdate": "DD.MM.YYYY"
}
}
(when parsing with moment.js)
A string with the person’s Crefonummer (an identifier used by Creditreform).
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"person": ["crefoId"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
//...
"person": {
"crefoId": "2010034122"
}
//...
}
A string with the person’s nationality (short country code in caps), according to the ID document presented during the CrefoTrust process, e.g.:
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"person": ["nationality"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
//...
"person": {
"nationality": "DE"
}
//...
}
This credential represents a special relationship between a person and a company. It’s meaning is basically that the person might act for that company in certain legal matters or the other way around, that the company is represented by the person in such cases.
Post Order Data
You signal that your require this credential via:
{
//...
"requiredCredentials": {
"authorizedRepresentative": true
}
//...
}
If you don’t want this credential, you may leave it out completely or explicitly set the value to false. Please bear in mind that the value is actually a boolean. Other value types will lead to a rejection of the order request.
Webhook Request Data
The data will be delivered to your webhook as:
{
//...
"authorizedRepresentative": true
//...
}
This credential represents a special relationship between a person and a company. It’s meaning is basically that the person is an agent of the company. This relationship is verified by a PIN letter that was sent to the company’s legal address.
Post Order Data
You signal that your require this credential via:
{
//...
"requiredCredentials": {
"verifiedAgent": true
}
//...
}
If you don’t want this credential, you may leave it out completely or explicitly set the value to false. Please bear in mind that the value is actually a boolean. Other value types will lead to a rejection of the order request.
Webhook Request Data
The data will be delivered to your webhook as:
{
//...
"verifiedAgent": true
//...
}
An object with the postal address of the company, according to the information that Creditreform has researched.
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"org": ["address"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
//...
"org": {
"address": {
"streetAddress": "Schillerstraße 22",
"postalCode": "31333",
"addressLocality": "Bielefeld",
"addressCountry": "Deutschland"
}
}
//...
}
A string with the company’s legal form. Typical values would be:
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"org": ["legalForm"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
//...
"org": {
"legalForm": "GmbH"
}
//...
}
A string with the company’s legal name.
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"org": ["legalName"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
//...
"org": {
"legalName": "BetterBrot GmbH"
}
//...
}
A string with the company’s “Crefonummer” (an identifier used by Creditreform).
Post Order Data
You signal that you require this credential via:
{
//...
"requiredCredentials": {
"org": ["crefoId"]
}
//...
}
Webhook Request Data
And will get the data delivered to your webhook as:
{
//...
"org": {
"crefoId": "2051200045"
}
//...
}
Describes the rational behind the “PinLetters” concept, the technicalities to obtain short codes and pins for further processing as well as the integration with the “normal” CrefoTrust process.
Key concepts and terms explanation.
Given an initial setup with specific usecases the “SelfService” gives the opportunity to easily integrate with CrefoTrust without the need to develop a webhook.
How to approach testing your CrefoTrust integration.