A guide to Documents
What is a document?
Any data entered into Linckr is stored in a document. This can include information from user-filled forms, data
obtained from external systems, or PDFs shared between consumers and providers.
Documents can be classified as either structured or unstructured:
- Structured data is stored in JSON format and conforms to a specific JSON schema.
- Unstructured data, such as photos and PDFs, is stored as binary files.
Documents are stored in pods
In Linckr, all personal data of a consumer is stored in a Solid data pod, a secure, decentralized storage solution
that
functions like a "digital safe." You don’t need to worry about the technical details of the Solid protocol; Linckr
manages everything for you. Each piece of information is stored as a document within the pod.
A key point to remember: when a service provider gains read access to specific data in a consumer's pod, that access is temporary. If the provider needs the document for a longer period, they should download a copy, as access might not be permanent.
Each organization also has a pod, currently used in the following scenario: When a member shares a document with a consumer, the document is first uploaded to the organization’s pod and then copied to the consumer's pod. We are planning to add functionality that enables documents to be stored in the organizational pod for longer-term retention. If this feature is important to you, please reach out to us at support@linckr.com.
What is a document type?
Each document has a specific document type. The name of the document type describes what the data represents.
The naming convention for a document type is as follows:
- The name must be a lowercase string.
- Spaces are not allowed; underscores are used instead.
A few examples: imx_completed_json, proof_inheritance, other_document
Why do we need document types?
Having a clear and consistent way to identify the type of data in a document enables the Linckr platform to support document reuse across different interactions.
A little example
A provider (Provider A) sends a document of type proof_inheritance to a consumer, then this data stored in the
consumer’s pod. Later, when another provider (Provider B) requests a proof_inheritance, Linckr checks the document
types already stored in the consumer’s pod. Seeing that there is an existing proof_inheritance document, Linckr can
suggest this document to the consumer, who can choose to share it or select an alternative.
Categories of documents
As every piece of information is stored in a document. We can determine different categories:
- Forms
- Data filled in by the user or data provided by an external system.
- Always conforms to a JSON schema defined by document type.
- Uploaded Files
- Files uploaded by either the consumer or the provider.
- The format is not predefined.
- Each file has a document type indicating the kind of data it contains; for example, a document with document
type
proof_inheritancecould be a signed PDF or an image.
- Generated by Linckr
- At the end of each info mediation exchange, Linckr collects information from all forms and generates an overview. More information about these documents is provided below.
IMX completed documents
When an info mediation is completed, at least two documents become available:
imx_completed_json, which contains the structured dataimx_completed_pdf, a human-readable version with the same content.
Some info mediation requests require the consumer or provider to upload one or more files. These files will also be made
available here.
The document types depend on the specific template and configuration used. Please note that the media type and format of
these documents are not predetermined. The API exposes the property nameDuringUpload for these documents.
IMX completed json
Every completed infomediation contains at least one document with documentType imx_completed_json
This document has the following json-schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"metadata": {
"type": "object",
"properties": {
"connectionId": {
"type": "string"
},
"organisationName": {
"type": "string"
},
"organisationWebId": {
"type": "string"
},
"consumerFirstname": {
"type": "string"
},
"consumerLastname": {
"type": "string"
},
"consumerWebId": {
"type": "string"
},
"journeyReference": {
"type": "string"
},
"journeyType": {
"type": "string"
},
"consumerRole": {
"type": "string"
},
"validTillDate": {
"type": "array",
"items": [
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
}
]
},
"consentDate": {
"type": "array",
"items": [
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
},
{
"type": "integer"
}
]
},
"providerMessage": {
"type": "string"
},
"templateTypeMetaData": {
"type": "object",
"properties": {
"documentTypeNames": {
"type": "object",
"properties": {
"nl_NL": {
"type": "string"
},
"en_EN": {
"type": "string"
}
},
"required": [
"nl_NL",
"en_EN"
]
},
"providerMessage": {
"type": "string"
}
},
"required": [
"documentTypeNames",
"providerMessage"
]
}
},
"required": [
"connectionId",
"organisationName",
"organisationWebId",
"consumerFirstname",
"consumerLastname",
"consumerWebId",
"journeyReference",
"journeyType",
"consumerRole",
"validTillDate",
"consentDate",
"providerMessage",
"templateTypeMetaData"
]
},
"data": {
"type": "object"
}
},
"required": [
"metadata",
"data"
]
}
In this case, the data object serves as a container that can hold none, one, or multiple items, each representing data from a separate document. A typical example of such 'separate' document is a form the consumer completed as part of a task.
The infomediation template id determines which information is available in the data object. Let's illustrate this
with an example.
Example for imx of type PERSON_IDENTIFICATION_DATA
Let's assume the infoMediations query returns the following response:
{
"data": {
"infoMediations": [
{
"id": "6f0cb271-b163-4f00-9416-4e6abb5f7469",
"template": {
"__typename": "InformationRequestInfoMediationTemplate",
"id": "PERSON_IDENTIFICATION_DATA",
"type": "INFORMATION_REQUEST_TEMPLATE",
"name": "Persoonsgegevens"
},
"status": "COMPLETED",
"documents": [
{
"id": "941fd20a-3467-46d3-a5ef-f4145beab908",
"documentType": "imx_completed_pdf",
"mediaType": "application/pdf"
},
{
"id": "327db463-f068-4741-87aa-4abb1e2a6fef",
"documentType": "imx_completed_json",
"mediaType": "application/json"
}
]
}
]
}
}
We can read that the templateId is PERSON_IDENTIFICATION_DATA.
It is defined that this template exposes the data from the document digidentity_user_info.
The list of supported templates is continually expanding. If you need information on templates not yet covered in this developer portal, please reach out to support@linckr.com, and we’ll be happy to provide additional details.
The document digidentity_user_info complies with the following json schema:
{
"schema": {
"properties": {
"given_name": {
"type": "string"
},
"family_name": {
"type": "string"
},
"birthdate": {
"type": "string"
},
"gender": {
"type": "string"
},
"email": {
"type": "string"
},
"identity_document": {
"oneOf": [
{
"type": "object",
"properties": {
"type": {
"type": "string"
},
"number": {
"type": "string"
},
"expiration_date": {
"type": "string"
},
"state": {
"type": "string"
}
}
},
{
"type": "null"
}
]
}
},
"required": []
}
}
Let's assume that the document with id 941fd20a-3467-46d3-a5ef-f4145beab908 and shape imx_completed_json that
conforms
to the json schema defined above contains the following values:
{
"metadata": {
"connectionId": "8ee0c676-cd71-46d3-9b81-647c0fe2499d",
"organisationName": "Immo Hengelen",
"organisationWebId": "https://sandbox.use.id/hengelen",
"consumerFirstname": "Michael",
"consumerLastname": "Cornelis",
"consumerWebId": "https://sandbox.use.id/michaelcornelis",
"journeyReference": "8373ab_7_b",
"journeyType": "RESIDENCE_JOURNEY",
"consumerRole": "BUYER",
"validTillDate": [
2023,
7,
17,
6,
39,
36,
922227154
],
"consentDate": [
2023,
4,
18,
6,
39,
36,
922263709
],
"providerMessage": "Hey Michael\n\nZou ik je persoonlijke informatie mogen?\n\nMet vriendelijke groeten\n\nMichael",
"templateTypeMetaData": {
"providerMessage": "Hey Michael<br><br>Zou ik je persoonlijke informatie mogen?<br><br>Met vriendelijke groeten<br><br>Michael"
}
},
"data": {
"digidentity_user_info": {
"given_name": "Michael",
"family_name": "Cornelis",
"identity_document": {
"type": "ID_CARD",
"number": "IMJ6D1234",
"expiration_date": "2028-01-01",
"state": "accepted"
},
"email": "michael+postman@lemon.be",
"gender": "m",
"birthdate": "1972-07-26"
}
}
}
The data container contains one object called digidentity_user_info which complies with the agreed-upon json schema.
This data can be parsed by an ERP system to reuse the data and automate tasks.