Introduction
The Legal Entity Credentials Registry (LECR) Framework defines the standards for publishing Legal Entity Verifiable Credentials in an open and interoperable manner.
The framework specifies:
- How to define LECR endpoints.
- How to offer Verifiable Credentials.
Business scenarios
- As an accreditor, I can upload my issued credential to a public registry.
- As a receiver of an accreditation, I can upload the issued credential to a public registry.
- As an unknown user, I can search, browse and read all uploaded credentials.
- After I select a credential, it will be validated in the UI with a disclaimer.
- As an Issuer or Subject of a credential, I can remove the credential from the public registry.
- As a Holder of a credential, I can refer to the URL as proof for my self-issued credentials or presentations.
Functional requirements
- Credentials must be integrity-protected.
- LECR should be discoverable from the DID document.
- LECR should be discoverable from the domain name.
- LECR can be self-hosted.
- LECR can be hosted by a third party.
Non-functional requirements
- Only Legal Entities (LEs) may upload credentials to the public registry.
- The entity must be either the Issuer or Subject of the credential, depending on the credential type.
- Searching, browsing or reading Credentials is public and may be rate-limited.
- As a Holder, I can appoint my preferred Credential Registry in the DID document as a Credential Registry service.
Specifiying LECR endpoints
As an LE, you can publish your public Verifiable Credentials on your website or through an LECR service provider. A list of LECR service providers will be available in the LECR service providers section.
You can specify your LECR endpoints in your DID document or on your website.
Defining and publishing service endpoints in a DID document
Define your service endpoint for your DID document
Below is an example of a simple LECR service:
{
"id": "did:ebsi:123#lecr2024",
"type": "LegalEntityCredentialRegistry2024",
"serviceEndpoint": "website.example/credentials",
// Optional claim:
"fallbackEndpoints": ["website2.example/credentials"]
}
Field | Description |
---|---|
id | REQUIRED. Type is string and the value MUST be your DID. If the DID method used doesn't have a well-defined identifier scheme, use #lecr2024 . For multiple service entries, use the scheme #lecr2024_NN , where "NN" is an integer starting at "00". |
type | REQUIRED. Type is a string and the value MUST be LegalEntityCredentialRegistry2024 . |
serviceEndpoint | REQUIRED. Type is string and the value MUST be a URL with the https scheme. |
fallbackEndpoints | OPTIONAL. Type is list and the values MUST be of type string and have value URL with the https scheme. |
Publish your service endpoints in your DID Document
This section describes how to publish your service endpoints using did:ebsi
.
For other DID methods or LECR service providers, consult the corresponding documentation.
Defining and publishing service endpoints under a .well-known
Define your service endpoint for your .well-known
If you're not working with decentralised identifiers, here is a simple LECR service example:
{
"id": "https://website.example",
"type": "LegalEntityCredentialRegistry2024",
"serviceEndpoint": "website.example/credentials",
// Optional claim:
"fallbackEndpoints": ["website2.example/credentials"]
}
Field | Description |
---|---|
id | REQUIRED. Type is string and the value MUST be your full URL with HTTPS scheme. For multiple service entries of the same type, use the scheme {domain-name}#lecr2024_NN , where "NN" is an integer starting at "00". |
type | REQUIRED. Type is a string and the value MUST be LegalEntityCredentialRegistry2024 . |
serviceEndpoint | REQUIRED. Type is string and the value MUST be a URL with the https scheme. |
fallbackEndpoints | OPTIONAL. Type is list and the values MUST be of type string and have value URL with the https scheme. |
Publish your service endpoints under your .well-known
Create a file .well-known/did/service
and store a JSON array with all the service endpoints relevant to your website. For example:
[
{
"id": "https://website.example",
"type": "LegalEntityCredentialRegistry2024",
"serviceEndpoint": "website.example/credentials"
}
]
The entry MUST be an array, even if it contains a single element.
LECR service endpoint definitions
This section defines the LECR service endpoints.
Resolution
At a minimum, an LECR service MUST implement the following two GET endpoints:
- GET {serviceEndpoint} URL MUST resolve to an array of VCs.
- GET {serviceEndpoint}/configuration: MUST be a valid configuration file as defined below.
Multi-tenent implementations
For multi-tentnat services, the service MUST expose an endpoint as /identifiers/{identifier}/credentials
.
The identifier
MUST be URL encoded.
Credential Registry Endpoint Definitions
The registry MUST support the endpoints marked as Required → Yes, and the endpoints MUST be public.
Path | Public | Required | Verb | Body (Req or Resp) | Description |
---|---|---|---|---|---|
/credentials | No | No | POST | Array [VC with meta] | Add new VCs. DPoP Token as a header. The array of uploaded VCs must be paired with the designated content-type. |
/credentials/{credential-hash} | Yes | Yes | GET | VC as is | Request VC with JCS-based hash of the payload. Return VC as it was registered. Content-type must be carried in the HTTP Header. |
/credentials?ids={credential-hashes} /credentials/{credential-hash} | No | No | DELETE | N/A | Remove one or many VCs. DPoP Token must be included as a header. Multiple IDs are provided as a comma-separated list, where ID represents the credential-hash. |
/credentials?credentialSubject={credentialSubject.id}&{issuer}&type={type} | Yes | Yes | GET | Array [VC as JSON with meta] | Fetch the latest 25 credentials with pagination. (Latest for cursor based polling, optional) [VC with meta] must contain the VC payload as JSON + location reference for the actual VC. Target arrays are matched with "contains", and the query may contain only single item. Indexed properties are:
|
The credential-hash is a JCS-formatted VC Payload that is then SHA-256 hashed.
VC Payload with meta shall look like:
{
"self": <current url>,
"pageSize": <number of items in "items">,
"total": <total number of items matching the request params>,
"links": {
"first": <URI of the first page>,
"prev": <URI of the previous page>,
"next": <URI of the next page>,
"last": <URI of the last page>
}
"items": [{
"id": <Hash of the canonicalized payload>, // <- required, to be used when querying /credentials/{id}
"href": "<origin>/credentials/{id}", // <- full URL
"contentType": "application/jose+json"
"payload": <JSON serialised JWS>
}]
}
Access Management
Registry owners can implement their own access management systems.
All reads from the registry will be open to the public, including filtering capabilities. Altering the content will be protected by Decentralised Access Management, where the caller must be either the Issuer, the controller of the Issuer, or the Subject of the Credential.
Demonstrating Proof of Possession (DPoP) will be used to do the "Holder Binding", where the DPoP Token must contain a client-generated nonce.
Supported Credentials
In the initial release, only JWS signed VCs will be supported.
Supported formats are:
- Compact serialised JWS
- JSON serialised JWS
Security considerations
Clients calling the service endpoint MUST understand the service endpoint type. The service endpoint MUST be TLS protected, and the certificate MUST be valid.
Who can implement LECR?
Any legal entity or organisation can implement or offer LECR as a service.
LECR service providers
Currently, there are no Legal Entity Credentials Registry providers due to the recentness of the specifications. In this section, new LECR providers will be added in the form of a list as they become available.
Open API specification (OAS) - Legal Entity Credentials Registry
openapi: 3.0.3
info:
title: Legal Entity Credentials Registry APIs
description:
APIs for resolving and managing organisation's Verifiable Credentials
We are introducing three sets of APIs.
- single-entity credential service enpoints
- multi-tenant credential service enpoints
- credential registry endpoints
Single-entity credential endpoints can be implemented as a self-hosted service
or by simply putting JSON files on a file server.
Multi-tenant credential service endpoints come with an additional requirement
of providing the organisation's identifier in the path.
Credential service endpoint names MUST be respected, however they can be prefixed with an arbitrary path.
Credential Registry is a service that can be offered to organisations to manage their credentials.
It comes with additional capabilities, such as filtering.
version: 1.0.0
contact:
email: info@ebsi.eu
servers:
- url: localhost:8080
tags:
- name: Credential endpoints
- name: Credential endpoints (multi-tenant)
- name: Credential Registry
paths:
/credential-registry:
post:
summary: Add new VCs
operationId: post/credentials
tags:
- Credential Registry
description: Add new VCs. DPoP Token as a header. The array of uploaded VCs must be paired with the designated content-type.
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/VCWithMeta"
responses:
"200":
description: VCs successfully added
delete:
operationId: delete/credentials
tags:
- Credential Registry
summary: Remove one to many VCs
description: Remove one to many VCs. DPoP Token must be contained as a header. Multiple IDs are provided as a comma-separated list, where ID represents the credential-hash.
parameters:
- name: ids
in: query
required: true
schema:
type: string
example: "hash1,hash2,hash3"
responses:
"200":
description: VCs successfully removed
get:
operationId: get/credential-registry
tags:
- Credential Registry
summary: Fetch latest 25 credentials with pagination
description: >
Fetch latest 25 credentials with pagination. [VC with meta] must contain the VC payload as JSON + location reference for the actual VC.
Target arrays are matched with "contains", and query may contain only single item.
Indexed properties are: credentialSubject.id, issuer, type.
parameters:
- name: credentialSubject
in: query
required: true
schema:
type: string
- name: issuer
in: query
required: true
schema:
type: string
- name: type
in: query
required: true
schema:
type: string
responses:
"200":
description: VCs retrieved successfully
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/VCWithMeta"
/credential-registry/{credential-id}:
get:
operationId: get/credentials/credential-id
summary: Request VC with JCS based hash
description: Request VC with JCS based hash of the payload. Return VC as it was registered. Content-type must be carried in the HTTP Header.
tags:
- Credential Registry
parameters:
- name: credential-id
in: path
required: true
schema:
type: string
responses:
"200":
description: VC retrieved successfully
content:
application/json:
schema:
$ref: "#/components/schemas/VC"
/credentials:
get:
operationId: get/credentials
tags:
- Credential endpoints
summary: Fetch organisation's credentials
description: |
The endpoint returns organisation's Verifiable Credentials as a JSON array.
responses:
"200":
description: Success
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/vcList"
/credentials/configuration:
get:
operationId: get/credentials/configuration
summary: Service endpoint information
description: Contains details about the credetials service endpoint
tags:
- Credential endpoints
responses:
"200":
description: VC retrieved successfully
content:
application/json:
schema:
$ref: "#/components/schemas/configuration"
/identifiers/{identifier}/credentials:
get:
operationId: get/identifiers/identifier/credentials
tags:
- Credential endpoints (multi-tenant)
summary: Fetch organisation's credentials
description: |
The endpoint returns organisation's Verifiable Credentials as a JSON array.
parameters:
- in: path
name: identifier
description: URL encoded Legal Entity identifier.
required: true
schema:
type: string
responses:
"200":
description: Success
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/vcList"
/identifiers/{identifier}/credentials/configuration:
get:
operationId: get/identifiers/identifier/credentials/configuration
summary: Service endpoint information
description: Contains details about the credetials service endpoint
tags:
- Credential endpoints (multi-tenant)
parameters:
- in: path
name: identifier
description: URL encoded Legal Entity identifier.
required: true
schema:
type: string
responses:
"200":
description: VC retrieved successfully
content:
application/json:
schema:
$ref: "#/components/schemas/configuration"
components:
schemas:
vcList:
title: List of Verifiable Credentials
description: A list of Verifiable Credentials. Supported formats are compact serialised JWS, JSON serialised JWS and JSON(-LD).
type: array
items:
oneOf:
- type: string
- type: object
VCWithMeta:
title: Verifiable Credential with metadata
type: object
properties:
payload:
type: object
meta:
type: object
VC:
title: Signed Verifiable Credential
oneOf:
- type: object
- type: string
configuration:
title: Service Endpoint Configuration
type: object
required:
- service_endpoint_type
properties:
service_endpoint_type:
description: Defines the service endpoint type. The type MUST match the type that referenced the endpoint.
const: "LegalEntityCredentialRegistry2024"
registry_endpoints:
description: OPTIONAL. Defines the registry endpoints path, if they exist.
type: string
multi_tenant:
description: OPTIONAL. Defines whether the service is multi-tenant or not. Default value is false
type: boolean
default: false