This specification creates a standardized way of referencing, dereferencing, and fetching digital resources. This includes associating digital resources with Decentralized Identifiers (DIDs), where each individual resource is identifiable through its own DID URL.

This document is a Draft Community Group Report produced by the W3C Credentials Community Group. It is an experimental specification undergoing regular revisions and is not yet fit for production deployment.

Comments and contributions are welcome via the GitHub issue tracker or the public-credentials mailing list.

Introduction

DID-Linked Resources (DLRs) are digital files that can be retrieved and referenced using a persistent and unique DID URL.

This specification defines common requirements, patterns, algorithms including their request formats and response formats, architectural options, and various considerations for how [=DID-Linked Resources=] SHOULD act as persistent identifiers for referencing and retrieving digital resources (such as data schemas, status lists, trust registries, governance documents, or policy definitions). This specification complements the [[DID-RESOLUTION]] specification, including its patterns and algorithms for DID URL resolution and dereferencing.

By using DID URLs which remain conformant with the W3C [[DID-CORE]] Recommendation and [[DID-RESOLUTION]], existing DID Resolvers will be able to dereference these DID URLs to retrieve the identified resources using the DID URL query syntax defined in this specification.

While this specification defines some base-level functionality for DID URL dereferencing, the actual steps required to communicate with a DID's verifiable data registry are defined by the applicable DID method specification.

Context for Specification

The [[DID-CORE]] specification defines an interoperable standard for DID documents and associated core properties; however, it does not currently have a standardized way to specify properties of resources associated with DIDs, nor how to consistently reference or retrieve them.

Digital resources are generally stored on traditional centralized-storage endpoints, but this comes with certain drawbacks:

  1. Digital resources could be tampered with by compromising the hosting provider. Resources stored at a centralized web endpoint can be replaced by malicious actors.
  2. Hosting providers could unilaterally cease to host particular clients. Providers may terminate accounts due to non-payment, violation of Terms of Service, or other factors.
  3. Single point of failure (SPOF). Even with highly-trusted hosting providers, a service outage can make a resource inaccessible.

Despite these issues, many decentralized identity and digital credential implementations, even those that use ledgers or other distributed systems for DIDs, often use centralized storage. Using traditional web endpoints to store digital resources that are critical for a Verifiable Credential to function detracts from the utility that persistently-accessible Decentralized Identifiers offer.

{
  "@type": "http://schema.org/Person",
  "http://schema.org/address": {
    "@type": "http://schema.org/PostalAddress",
    "http://schema.org/streetAddress": "123 Main St.",
    "http://schema.org/addressLocality": "Blacksburg",
    "http://schema.org/addressRegion": "VA",
    "http://schema.org/postalCode": "24060",
    "http://schema.org/addressCountry": "US"
  }
}
    

A Simple Example

To understand [=DID-Linked Resources=], it is important to grasp the foundational concept of a parent-child relationship between a DID and the resources associated with it.

A DID serves as a persistent, authoritative identifier for an entity, for example a person, organization, device, or agent. In the context of [=DID-Linked Resources=], the DID acts as the parent, and the resources published under that DID are considered its children. These resources might include schemas, status lists, visual assets, trust registries, or any other type of digital object relevant to verifiable credentials and decentralized identity ecosystems.

For example, suppose Entity A controls the DID:

did:example:entity123

This DID SHOULD serve as the root under which various resources are published. A specific resource MAY (if UUIDs are used for resource IDs) be accessible at:

did:example:entity123/resources/41c0f0fe-cd4e-45aa-aec5-754db4a63865

The DID controller (Entity A) controls the DID and has the ability to create, update, or deactivate these resources. While each resource is independently addressable, they remain logically and cryptographically bound to the DID under which they are published.

This structure provides several benefits:

Architecture Overview

The relationship between DIDs and [=DID-Linked Resources=] is shown in the diagram below.

DID-Linked Resources architecture diagram showing parent DID and child resources
DID-Linked Resources — Architecture Overview

Design Principles

The following design principles SHOULD be taken into consideration. [=DID-Linked Resources=] SHOULD:

  1. Use existing and familiar [[DID-CORE]] patterns where possible.
  2. Support existing DID Resolvers and principles of DID URL dereferencing.
  3. Protect against link-rot for long-term retrieval.
  4. Enable resources to be versioned and organized, with individual versions being able to be fetched.
  5. Include semantic linkage between DID documents and associated resources (via metadata or otherwise).
  6. Be method-agnostic: the specification SHOULD be implementable by any DID method, whether backed by a distributed ledger, a web server, a peer-to-peer protocol, or any other verifiable data registry.

Conformance

A conforming DLR Producer is a system that creates, updates, or deactivates [=DID-Linked Resources=]. A conforming DLR Producer MUST:

A conforming DLR Consumer is a system that resolves, dereferences, or verifies [=DID-Linked Resources=]. A conforming DLR Consumer MUST:

Terminology

The following terms are used throughout this specification. Terms defined in [[DID-CORE]] are used as defined there.

DID Controller
As defined in [[DID-CORE]].
DID Document
As defined in [[DID-CORE]].
DID URL
As defined in [[DID-CORE]].
DID URL dereferencing
As defined in [[DID-CORE]].
Resource Collection
An organized and structured set of digital resources, collectively and individually identifiable using persistent and unique DID URLs.
Resource Identifier
A unique identifier for a specified [=DID-Linked Resource=].
Binding Verification Mechanism
A process by which a [=conforming DLR Consumer=] can confirm that a [=DID-Linked Resource=] was authorized by the DID controller. Different DID methods employ different binding verification mechanisms (see ).

DID-Linked Resource URL Syntax

The following ABNF defines the structure of a DID-Linked Resource URL, which is a specific type of DID URL that refers to a resource published under a DID. While the overall syntax is compatible with [[DID-CORE]], this profile defines expected structure and semantics for paths, query parameters, and fragments used in the [=DID-Linked Resource=] model.

The following is the ABNF definition using the syntax in [[RFC5234]]. All [=DID-Linked Resources=] MUST conform to the DID-Linked Resource URL Syntax ABNF Rules.

; DID-Linked Resource URL
dlr-url            = did path-abempty [ "?" query ] [ "#" fragment ]

; Decentralized Identifier (per W3C DID Core)
did                = "did:" method ":" method-specific-id
method             = 1*method-char
method-char        = ALPHA / DIGIT / "-"
method-specific-id = 1*( idchar / ":" )
idchar             = ALPHA / DIGIT / "." / "-" / "_" / pct-encoded
pct-encoded        = "%" HEXDIG HEXDIG

; Path component
path-abempty       = *( "/" segment )
segment            = *pchar

; Optional query and fragment (RFC 3986)
query              = *( pchar / "/" / "?" )
fragment           = *( pchar / "/" / "?" )

; Core character classes
pchar              = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved         = ALPHA / DIGIT / "-" / "." / "_" / "~"
sub-delims         = "!" / "$" / "&" / "'" / "(" / ")" / "*"
                   / "+" / "," / ";" / "="
HEXDIG             = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
ALPHA              = %x41-5A / %x61-7A
DIGIT              = %x30-39
  

The path-abempty component typically includes structured segments such as /resources/{resourceId}, representing a unique identifier scoped to the DID. The query component may include parameters like resourceName, resourceType, or resourceVersion, enabling flexible filtering and referencing of specific resource variants. The optional fragment can refer to a sub-section within the resource, such as a field in a schema or an anchor in a document.

Semantics

The components of a [=DID-Linked Resource URL=] carry the following semantics:

Core Properties

The following table contains informative references for the core properties defined by this specification, with expected values and whether or not they are required.

Property Required? Value Constraints
resourceUri yes A string or map conforming to [[RFC3986]] URI rules that MUST directly lead to a location where the resource can be accessed.
resourceId yes A string that conforms to a method-specific supported unique identifier format. For example, a UUID: 46e2af9a-2ea0-4815-999d-730a6778227c.
resourceCollectionId no A string that identifies the DID associated with the resource. If omitted, the value SHOULD default to the method-specific-id portion of the parent DID.
resourceName no A string that uniquely names and identifies a resource. Together with resourceType, it can be used to track version changes.
resourceType no A string that identifies the type of resource. Together with resourceName, it can be used to track version changes. Not to be confused with mediaType.
resourceVersion no A string that identifies the version of the resource. This property is provided by the client and can be any value.
alternativeUri no An array that describes alternative URIs for the resource.
mediaType no A string that identifies the IANA media type of the resource.
created no A string identifying the date and time the resource was created, as an XML Datetime.
updated no A string identifying the time the resource was updated, as an XML Datetime.
checksum no A string formatted as <algorithm-id>:<hex-encoded-hash> that may be used to verify the resource has not been tampered with. See .
previousVersionId no A string identifying the previous version of the resource.
nextVersionId no A string identifying the next version of the resource.
proof no An object or array of objects containing cryptographic proof(s) that the resource was authorized by the DID controller. See .

Resource URI

[=DID-Linked Resources=] are content-addressable or identifier-addressable resources associated with a Decentralized Identifier (DID). They are represented as URIs rooted at a valid DID. The full [=DID-Linked Resource URL=] identifying a resource MUST include a DID and a [=Resource Identifier=] (resourceId).

Resource Identifiers

A [=Resource Identifier=], or resourceId, MUST be a unique identifier for a single resource. Two resources under the same DID method MUST NOT share the same resourceId.

Resource Collection ID

The resourceCollectionId property is OPTIONAL. This property identifies the DID under which resources are logically collected. If omitted from the resource metadata, the resourceCollectionId SHOULD default to the method-specific-id portion of the parent DID.

did:example:0a5b94d0-a417-48ed-a6f5-4abc9e95888d

For the DID above, the default Resource Collection ID would be: 0a5b94d0-a417-48ed-a6f5-4abc9e95888d.

If explicitly set, the Collection ID SHOULD take the syntactical form of the DID method that the [=DID-Linked Resource=] is associated with.

Resource Name

The resourceName property is OPTIONAL. If present, the value MUST be expressed as an ASCII string.

Resource Type

The resourceType property is OPTIONAL. If present, the value MUST be expressed as an ASCII string. In order to maximize interoperability, the resource type and its associated properties SHOULD be registered in the DID Specification Registries [[DID-SPEC-REGISTRIES]].

The following resource types are RECOMMENDED for common use cases. Implementations MAY define additional types as needed.

Resource Type String Description Typical Media Type
JSONSchema2020 A JSON Schema (2020-12 draft or later) used to validate credential subjects. application/json
BitstringStatusList A W3C Bitstring Status List [[BITSTRING-STATUS-LIST]] used for credential revocation or suspension. This replaces the deprecated StatusList2021 type; implementers SHOULD migrate to this value. application/json
TrustRegistry A trust registry describing trusted issuers, verifiers, or governance rules. application/json
GovernanceFramework A governance document describing policies, procedures, or rules. application/json or application/pdf
VisualPresentation A visual representation associated with a DID (e.g., logo, icon, branding). image/png, image/svg+xml
CL-Schema A Hyperledger AnonCreds CL-Schema. application/json
CredentialDefinition A Hyperledger AnonCreds Credential Definition. application/json
This table is informative. The authoritative registry for resource types is maintained in [[DID-SPEC-REGISTRIES]]. Implementations SHOULD register new types there to promote interoperability.

Resource Version

The resourceVersion property is OPTIONAL. If present, the value MUST be expressed as an ASCII string. The format of the value is not constrained by this specification; implementations MAY use semantic versioning, date-based strings, or other schemes.

Alternative URI

The alternativeUri property is OPTIONAL. If present, the value MUST be a set where each item is a URI conforming to [[RFC3986]].

Resource Metadata Properties

Resource Metadata Properties are distinct from the core properties defined in in both their purpose and their role in the DLR lifecycle.

The core properties, resourceUri and resourceId, are identity properties. They are required, and together they form the stable, unique address by which a resource is located and unambiguously identified. Without them, a resource cannot be referenced or dereferenced at all.

Resource Metadata Properties, by contrast, are descriptive properties. They are all OPTIONAL and exist to provide consuming systems with the context needed to evaluate, validate, and manage a resource without necessarily fetching its full content. They answer questions such as: what kind of content is this, when was it published, has it been tampered with, and where does it sit in a version history?

In practice, this means resource metadata properties are primarily useful to conforming DLR Consumers; for example, a verifier checking whether a status list was current at the time a credential was issued, or a resolver confirming content integrity before processing a schema. They are not required to locate or retrieve the resource itself, but they significantly strengthen the trust and auditability of the resource once retrieved.

Because resource metadata properties are carried in the linkedResourceMetadata array within didDocumentMetadata rather than in the resource content itself, they are under the control of the DID controller and are subject to the same binding verification mechanisms described in .

Media Type

The mediaType property is OPTIONAL. If present, the value MUST be expressed as an ASCII string and SHOULD match the underlying IANA media type of the resource file identified by the resourceId.

Checksum

The checksum property is OPTIONAL. If present, the value MUST be formatted as follows:

checksum-value  = algorithm-id ":" hex-string
algorithm-id    = 1*( ALPHA / DIGIT / "-" )
hex-string      = 1*HEXDIG
      

The algorithm-id component is a lowercase identifier for the hash algorithm used. The hex-string component is the lowercase hexadecimal encoding of the hash output.

The following algorithm identifiers are defined by this specification:

Algorithm ID Hash Function Output Length Status
sha256 SHA-256 (FIPS 180-4) 256 bits (64 hex characters) RECOMMENDED (baseline)
sha384 SHA-384 (FIPS 180-4) 384 bits (96 hex characters) OPTIONAL
sha512 SHA-512 (FIPS 180-4) 512 bits (128 hex characters) OPTIONAL
sha3-256 SHA3-256 (FIPS 202) 256 bits (64 hex characters) OPTIONAL

[=Conforming DLR Producers=] MUST use sha256 unless the DID method specification or deployment context requires a different algorithm. [=Conforming DLR Consumers=] MUST support sha256 and SHOULD support any additional algorithms listed above.

If a [=conforming DLR Consumer=] encounters an algorithm-id it does not recognize, it MUST NOT treat the checksum as valid and SHOULD report the algorithm as unsupported.

DID methods or communities MAY define additional algorithm identifiers beyond those listed here. Implementations that wish to support content- addressable identifiers (e.g., CIDv1 from IPFS) MAY use the [[MULTIHASH]] self-describing format as an alternative encoding, provided the DID method specification documents this choice.

"checksum": "sha256:a7c369ee9da8b25a2d6e93973fa8ca939b75abb6c39799d879a929ebea1adc0a"

"checksum": "sha3-256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
      
Checksum values that do not include an algorithm prefix (i.e., bare hex strings without a colon separator) are considered non-conforming. Legacy implementations that omit the prefix SHOULD be updated. A [=conforming DLR Consumer=] that encounters a bare hex string MAY attempt to interpret it as SHA-256 for backward compatibility but MUST NOT treat the result as a verified checksum.

Created

The created property is OPTIONAL. If present, the value MUST be a string formatted as an XML Datetime normalized to UTC 00:00:00 and without sub-second decimal precision. For example: 2020-12-20T19:17:47Z.

Updated

The updated property is OPTIONAL. If present, the value MUST be a string formatted as an XML Datetime normalized to UTC 00:00:00 and without sub-second decimal precision.

PreviousVersionId

The previousVersionId property is OPTIONAL. If present, the value SHOULD reference the directly previous version of the resource. The value MUST be an ASCII string.

NextVersionId

The nextVersionId property is OPTIONAL. If present, the value SHOULD reference the directly next version of the resource. The value MUST be an ASCII string.

Proof

The proof property is OPTIONAL. If present, the value MUST be an object or an array of objects, where each object contains a cryptographic proof that the resource was authorized by the DID controller.

This property is particularly important for DID methods that do not rely on a distributed ledger or other verifiable data registry to enforce the binding between a DID and its resources (see ).

When present, the proof object SHOULD conform to the [[VC-DATA-INTEGRITY]] specification and SHOULD include at minimum the following properties:

Property Description
type The type of proof (e.g., DataIntegrityProof).
cryptosuite The cryptographic suite used (e.g., eddsa-jcs-2022, ecdsa-jcs-2019).
verificationMethod A DID URL referencing a verification method in the DID Document of the DID controller.
created The date-time at which the proof was created.
proofPurpose The purpose of the proof (e.g., assertionMethod).
proofValue The encoded proof value.
{
  "resourceUri": "did:web:example.com/resources/abc123",
  "resourceId": "abc123",
  "resourceCollectionId": "example.com",
  "resourceName": "PassportSchema",
  "resourceType": "JSONSchema2020",
  "mediaType": "application/json",
  "created": "2024-06-15T10:30:00Z",
  "checksum": "sha256:a7c369ee9da8b25a2d6e93973fa8ca939b75abb6c39799d879a929ebea1adc0a",
  "previousVersionId": "",
  "nextVersionId": "",
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "eddsa-jcs-2022",
    "verificationMethod": "did:web:example.com#key-1",
    "created": "2024-06-15T10:30:00Z",
    "proofPurpose": "assertionMethod",
    "proofValue": "z3FXQjecWufY46...yVDm1FRCVb"
  }
}
    
For DID methods where the verifiable data registry enforces the binding between DID and resource through its consensus mechanism, the proof property MAY be omitted. In such cases, the ledger transaction itself serves as the proof of authorization. See .

Binding to DIDs

In the context of [=DID-Linked Resources=], binding refers to the relationship between a resource and a Decentralized Identifier (DID). This binding is OPTIONAL but is highly recommended.

A DID acts as the parent that has authority over the resource, which is the child. The DID controller has control over the resource and can modify, update, or deprecate it. In this context, the DID itself becomes a [=Resource Collection=], within which one or multiple resources can be referenced.

Multiple resources MAY be bound to the same DID, and each MUST include a unique resourceId.

Representations

Resources linked to a DID SHOULD be represented in a way that maintains a verifiable association with that DID. The metadata describing each resource SHOULD be included as part of the DID Document Metadata, rather than within the DID Document itself. This allows for clear delineation between identity-related data and externally linked resources.

To ensure the integrity and traceability of resources associated with a DID, the didDocumentMetadata object MAY include a linkedResourceMetadata array. Each entry in this array corresponds to a distinct resource that is logically bound to the DID. Resources MAY be grouped or indexed by name and type, allowing multiple different resources to be managed within a single logical collection.

Representation within DID Document Metadata

The linkedResourceMetadata array is used to track resources, where each entry corresponds to a specific resource within the collection. Each entry SHOULD include the properties defined in , including links to previous and subsequent versions where applicable.

{
  "didDocumentMetadata": {
    "created": "2020-12-20T19:17:47Z",
    "updated": "",
    "deactivated": false,
    "versionId": "bdab59b0-66f5-42d3-b809-1829bdcc0408",
    "previousVersion": "",
    "nextVersion": "",
    "linkedResourceMetadata": [
      {
        "resourceUri": "did:example:13d5ad44-9e99-428f-81e9-274458cefddc/resources/44547089-170b-4f5a-bcbc-06e46e0089e4",
        "resourceCollectionId": "13d5ad44-9e99-428f-81e9-274458cefddc",
        "resourceId": "44547089-170b-4f5a-bcbc-06e46e0089e4",
        "resourceName": "PassportSchema",
        "resourceType": "CL-Schema",
        "resourceVersion": "1.0.1",
        "mediaType": "application/json",
        "created": "2022-07-19T08:40:00Z",
        "checksum": "sha256:7b2022636f6e74656e74223a202274657374206461746122207d0ae3b0c44298",
        "previousVersionId": "",
        "nextVersionId": "bb2118f3-5e55-4510-b420-33ef9e1726d2"
      },
      {
        "resourceUri": "did:example:13d5ad44-9e99-428f-81e9-274458cefddc/resources/bb2118f3-5e55-4510-b420-33ef9e1726d2",
        "resourceCollectionId": "13d5ad44-9e99-428f-81e9-274458cefddc",
        "resourceId": "bb2118f3-5e55-4510-b420-33ef9e1726d2",
        "resourceName": "PassportSchema",
        "resourceType": "JSONSchema2020",
        "resourceVersion": "2.0.0",
        "mediaType": "application/json",
        "created": "2022-08-07T08:40:00Z",
        "checksum": "sha256:9123dcbb0b42652b0e105956c68d3ca2ff34584f324fa41a29aedd32b883e131",
        "previousVersionId": "44547089-170b-4f5a-bcbc-06e46e0089e4",
        "nextVersionId": "0be87654-4a48-4f8e-8789-15ec3589ccdd"
      }
    ]
  }
}
    
The didDocumentMetadata SHOULD NOT be populated with the actual resource content, but instead with only the resource metadata, which contains all metadata about the associated resources.

Resource Representation

[=DID-Linked Resources=] MUST be retrievable either individually (by their full resourceId) or in aggregate (by querying resources linked to a given DID using a particular filter).

When queried individually, the result MUST return the full resource representation associated with the provided resourceId. When queried in aggregate, the result MUST return an array of resource metadata entries, each describing a distinct resource or version of the same resource.

Binding Verification Mechanisms

A critical aspect of [=DID-Linked Resources=] is the ability for a [=conforming DLR Consumer=] to verify that a resource was authorized by the DID controller. Different DID methods provide different infrastructure for this verification.

DID methods that implement [=DID-Linked Resources=] MUST specify which [=Binding Verification Mechanism=](s) they support and what a [=conforming DLR Consumer=] MUST verify before treating a resource as authentic.

Ledger-Validated Binding

In DID methods backed by a distributed ledger or similar consensus-based verifiable data registry (for example did:cheqd, did:indy, did:ebsi [[DID-EBSI]], did:ethr [[DID-ETHR]]) the binding between a DID and its resources is enforced by the ledger's consensus mechanism.

In this model:

  • The DID controller submits a transaction to create or update a resource, signed using a key associated with the DID.
  • The ledger validates the transaction signature against the DID Document's verification methods before accepting the resource.
  • A [=conforming DLR Consumer=] that trusts the ledger can treat the presence of the resource on the ledger as sufficient proof of authorization.

When using ledger-validated binding, the proof property in resource metadata (see ) MAY be omitted.

DID methods using this mechanism SHOULD document which verification relationship (e.g., authentication, assertionMethod) is required for resource transactions.

Signature-Based Binding

For DID methods that do not rely on a ledger (for example did:web [[DID-WEB]], did:webvh [[DID-WEBVH]], did:key, did:peer, did:jwk, did:pkh) the binding between a DID and its resources can be established through a cryptographic proof attached to the resource or its metadata.

When using signature-based binding, the proof property MUST be present in the resource metadata. The verificationMethod referenced in the proof MUST correspond to a verification method in the DID Document at the time the proof was created.

[=Conforming DLR Consumers=] MUST perform the following verification steps:

  1. Resolve the DID to obtain the DID Document.
  2. Locate the verification method referenced in proof.verificationMethod.
  3. Verify that the verification method is listed under an appropriate verification relationship (e.g., assertionMethod).
  4. Validate the cryptographic signature in proof.proofValue against the resource content (or metadata, depending on what was signed).
  5. If the checksum property is present, verify that the fetched resource content matches the checksum.

If any of these steps fail, the [=conforming DLR Consumer=] MUST treat the resource as unverified.

Content-Addressable Binding

In some architectures, the resource content is stored in a content-addressable system (for example, IPFS or Arweave), and the binding is established by anchoring the content identifier (hash) in the DID Document Metadata.

This mechanism provides integrity (proof that the content has not been tampered with) but does not on its own provide authorization (proof that the DID controller approved the resource). For this reason, content-addressable binding SHOULD be combined with either ledger-validated binding or signature-based binding to provide a complete trust chain.

Choosing a Binding Verification Mechanism

Mechanism Provides Integrity? Provides Authorization? Requires Ledger? Requires proof?
Ledger-Validated Yes (via consensus) Yes (via transaction validation) Yes No
Signature-Based Yes (via proof verification) Yes (via proof verification) No Yes
Content-Addressable Yes (via hash comparison) No (must be combined) No No (but SHOULD be combined)

Resource Parameters

Resource parameters are completely independent of any specific DID method and function the same way for all DIDs. See the query component of the [[DID-CORE]] DID URL syntax.

Parameter Type Description
resourceId String (method-specific unique identifier format) The unique identifier of a particular [=DID-Linked Resource=].
resourceCollectionId String (method-specific unique identifier format) Can be used to query all resources associated with a DID if combined with resourceMetadata=true.
resourceName String The specific name of a [=DID-Linked Resource=].
resourceType String The specific type of a [=DID-Linked Resource=].
resourceVersionTime XML Datetime (UTC, no sub-second precision) Used to fetch a version of a resource at a specific point in time.
checksum String Used to specify a particular resource checksum to demonstrate it is untampered.
resourceMetadata Boolean Used to fetch metadata related to a specific resource or group of resources.

Resolution and Dereferencing

Requests to fetch resources are considered a DID URL dereferencing scenario. The process uses DID URL paths to lead to a resource object, rather than a DID Document.

Normal DID URL dereferencing can be understood as a two-step process:

  1. Resolution: The DID is resolved to its corresponding DID Document using the relevant DID method.
  2. Dereferencing: A resource is located using the path, query, and/or fragment components of the DID URL.

Dereferencing a [=DID-Linked Resource URL=] returns the full resource representation. A metadata representation MUST also be obtainable, either alongside the resource itself or via a distinct query mechanism.

{
  "resourceUri": "did:example:13d5ad44-9e99-428f-81e9-274458cefddc/resources/bb2118f3-5e55-4510-b420-33ef9e1726d2",
  "resourceCollectionId": "13d5ad44-9e99-428f-81e9-274458cefddc",
  "resourceId": "bb2118f3-5e55-4510-b420-33ef9e1726d2",
  "resourceName": "PassportSchema",
  "resourceType": "JSONSchema2020",
  "resourceVersion": "1.0.1",
  "mediaType": "application/json",
  "created": "2022-04-20T20:19:19Z",
  "checksum": "sha256:a7c369ee9da8b25a2d6e93973fa8ca939b75abb6c39799d879a929ebea1adc0a",
  "previousVersionId": "67f2df00-0b6e-404b-8c70-1d63200e6412",
  "nextVersionId": "98922424-c214-4439-b52c-f68ddb450b40"
}
  

Dereferencing Algorithm

This section defines the algorithm that a [=conforming DLR Consumer=] MUST follow when dereferencing a [=DID-Linked Resource URL=].

Input: A [=DID-Linked Resource URL=] conforming to the ABNF in .

Output: One of the following: (a) the resource content, (b) an array of resource metadata entries, or (c) a DLR error object (see ).

  1. Parse the [=DID-Linked Resource URL=] into its components: did, path, query, and fragment.
  2. Resolve the did component using the applicable DID method to obtain the DID Document and didDocumentMetadata. If resolution fails, return an error with error set to "notFound".
  3. Check for deactivation. If the DID Document Metadata indicates the DID is deactivated ("deactivated": true), return an error with error set to "deactivated", unless the DID method explicitly permits resource access after deactivation.
  4. Extract the linkedResourceMetadata array from the didDocumentMetadata. If no linkedResourceMetadata is present, return an error with error set to "notFound".
  5. Apply path-based lookup. If the path component contains a resourceId (e.g., /resources/{resourceId}), filter the linkedResourceMetadata array to entries matching that resourceId. If no match is found, return an error with error set to "notFound".
  6. Apply query parameter filters. For each query parameter present (resourceId, resourceCollectionId, resourceName, resourceType, resourceVersion, resourceVersionTime, checksum), further filter the candidate set to entries matching the specified values.
  7. Check the resourceMetadata parameter.
    • If resourceMetadata=true, return the filtered array of resource metadata entries (even if multiple entries match). Skip to step 10.
    • If resourceMetadata=false or not specified, continue.
  8. Evaluate the candidate set.
    • If the candidate set is empty, return an error with error set to "notFound".
    • If the candidate set contains exactly one entry, proceed to step 9.
    • If the candidate set contains multiple entries with the same resourceName and resourceType, select the entry with the latest created timestamp.
    • If the candidate set contains multiple entries that differ in resourceName or resourceType, return an error with error set to "ambiguousQuery". The error SHOULD include a candidates array listing the resourceId values of the matching entries.
  9. Fetch and return the resource. Using the resourceUri of the selected entry, retrieve the full resource content. If a checksum is present, verify the fetched content against the checksum per . If a proof is present, verify it according to the rules in . If a fragment is present in the original URL, extract the sub-component identified by the fragment. Return the resource content.
  10. Return the result along with appropriate dereferencing metadata (e.g., contentType, retrieved timestamp).
The W3C DID Resolution specification is actively developing a formal algorithm for DID URL path handling, including a PathService service type that provides a general-purpose mechanism for routing DID URL paths to HTTP endpoints. Implementers SHOULD monitor the relevant work in progress in the DID Resolution repository and expect a future revision of this specification to align the dereferencing algorithm in with the normative path handling defined there once ratified. DID-Linked Resources and PathService are complementary at different layers. PathService provides transport routing, mapping a DID URL path to an HTTP location. linkedResourceMetadata provides the control plane: integrity verification, version traversal, and controller authorisation. A DID method MAY declare both a PathService with basePath: "/resources/" and publish linkedResourceMetadata for the same path space. In that case, resolvers that understand only PathService can still route to the resource, while DLR-aware resolvers gain the full metadata and verification layer. This provides a graceful degradation path for implementations adopting DLR semantics incrementally.

Rules and Logic for Handling Ambiguous Queries

Ambiguity Triggers Errors

If a query results in multiple matching resources and does not include sufficient parameters to disambiguate between them, the resolver MUST return an error.

Multiple Versions of the Same Resource

If multiple versions of a single resource exist (resources with the same resourceType and resourceName but different versionId values) and no specific version is requested, the resolver MUST default to returning the latest version. This situation is not considered ambiguous, as the resource identity is clear; only the version is unspecified.

Ambiguous Query with resourceMetadata=true

When a query is ambiguous but includes the resourceMetadata=true parameter, the resolver SHOULD return metadata for all matching resources.

did:example:c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0?resourceType=String&resourceMetadata=true
    
{
  "@context": "https://w3id.org/did-resolution/v1",
  "dereferencingMetadata": {
    "contentType": "application/did+ld+json",
    "retrieved": "2023-04-26T15:38:26Z",
    "did": {
      "didString": "did:example:c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0",
      "methodSpecificId": "c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0",
      "method": "example"
    }
  },
  "contentStream": {
    "created": "2023-01-25T11:58:10Z",
    "versionId": "e5615fc2-6f13-42b1-989c-49576a574cef",
    "linkedResourceMetadata": [
      {
        "resourceUri": "did:example:c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0/resources/9ba3922e-d5f5-4f53-b265-fc0d4e988c77",
        "resourceCollectionId": "c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0",
        "resourceId": "9ba3922e-d5f5-4f53-b265-fc0d4e988c77",
        "resourceName": "exampleResourceName1",
        "resourceType": "exampleResourceType",
        "mediaType": "application/json",
        "resourceVersion": "",
        "created": "2023-01-25T12:08:39Z",
        "checksum": "sha256:e1dbc03b50bdb995961dc8843df6539b79d03bf49787ed6462189ee97d27eaf3",
        "previousVersionId": null,
        "nextVersionId": null
      },
      {
        "resourceUri": "did:example:c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0/resources/e733ebb7-c8dd-41ed-9d42-33bceea70952",
        "resourceCollectionId": "c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0",
        "resourceId": "e733ebb7-c8dd-41ed-9d42-33bceea70952",
        "resourceName": "exampleResourceName2",
        "resourceType": "exampleResourceType",
        "mediaType": "application/json",
        "resourceVersion": "",
        "created": "2023-01-25T12:04:52Z",
        "checksum": "sha256:cffd829b06797f85407be9353056db722ca3eca0c05ab0462a42d30f19cdef09",
        "previousVersionId": null,
        "nextVersionId": null
      }
    ]
  },
  "contentMetadata": {}
}
    

HTTP Accept Headers

Clients MAY use the Accept HTTP header to express a preference for the media type of the dereferenced resource. The resolver MUST respect the Accept header if possible.

Error Format

When a [=conforming DLR Consumer=] encounters an error during dereferencing, it MUST return an error object within the dereferencingMetadata. The error object MUST include the following property:

PropertyRequired?Description
error yes A string identifying the error type.
message no A human-readable string describing the error.
candidates no An array of resourceId strings for matching entries, included when the error type is "ambiguousQuery".
Error TypeDescription
"notFound" No resource matching the query was found.
"ambiguousQuery" The query matched multiple resources that could not be disambiguated.
"deactivated" The parent DID has been deactivated.
"integrityError" The fetched resource content did not match the expected checksum.
"proofVerificationFailed" The proof on the resource metadata could not be verified.
"methodNotSupported" The DID method does not support [=DID-Linked Resources=].
{
  "@context": "https://w3id.org/did-resolution/v1",
  "dereferencingMetadata": {
    "error": "ambiguousQuery",
    "message": "Multiple resources matched the query. Specify additional parameters to disambiguate.",
    "candidates": [
      "9ba3922e-d5f5-4f53-b265-fc0d4e988c77",
      "e733ebb7-c8dd-41ed-9d42-33bceea70952"
    ]
  },
  "contentStream": null,
  "contentMetadata": {}
}
    

Resolution and Dereferencing Examples

This section contains non-normative examples illustrating the request format and expected response for each query parameter.

ResourceMetadata and Filter

A composite query requesting the resourceName, resourceType, and resourceMetadata=true. This filter returns the metadata of ALL resources of this name and type.

did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c?resourceType=exampleResourceType&resourceName=exampleResourceName&resourceMetadata=true
    
{
  "@context": "https://w3id.org/did-resolution/v1",
  "dereferencingMetadata": {
    "contentType": "application/did+ld+json",
    "retrieved": "2023-04-27T11:10:17Z",
    "did": {
      "didString": "did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c",
      "methodSpecificId": "d8ac0372-0d4b-413e-8ef5-8e8f07822b2c",
      "method": "example"
    }
  },
  "contentStream": {
    "created": "2023-02-21T14:28:47Z",
    "versionId": "44f49254-8106-40ee-99ad-e50ac9517346",
    "linkedResourceMetadata": [
      {
        "resourceUri": "did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c/resources/bae5cb6c-564a-4ed4-8c0e-d5c3b0f8ae0a",
        "resourceCollectionId": "d8ac0372-0d4b-413e-8ef5-8e8f07822b2c",
        "resourceId": "bae5cb6c-564a-4ed4-8c0e-d5c3b0f8ae0a",
        "resourceName": "exampleResourceName",
        "resourceType": "exampleResourceType",
        "mediaType": "application/json",
        "resourceVersion": "1.14.41",
        "created": "2023-02-22T08:57:23Z",
        "checksum": "sha256:93ba6f3c55ee073e6278f98e820776e73cfd9d3e32dc5882507ee8effbdbfadd",
        "previousVersionId": "40829caf-b415-4b1d-91a3-b56dfb6374f4",
        "nextVersionId": null
      },
      {
        "resourceUri": "did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c/resources/40829caf-b415-4b1d-91a3-b56dfb6374f4",
        "resourceCollectionId": "d8ac0372-0d4b-413e-8ef5-8e8f07822b2c",
        "resourceId": "40829caf-b415-4b1d-91a3-b56dfb6374f4",
        "resourceName": "exampleResourceName",
        "resourceType": "exampleResourceType",
        "mediaType": "application/json",
        "resourceVersion": "1.45.24",
        "created": "2023-02-22T08:55:07Z",
        "checksum": "sha256:2a6af570635ed49a39eae9a9c60ccb40d61466839d4ab2f17432a8ac705da489",
        "previousVersionId": "547abdb3-99f8-4040-b030-3296c4668846",
        "nextVersionId": "bae5cb6c-564a-4ed4-8c0e-d5c3b0f8ae0a"
      },
      {
        "resourceUri": "did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c/resources/547abdb3-99f8-4040-b030-3296c4668846",
        "resourceCollectionId": "d8ac0372-0d4b-413e-8ef5-8e8f07822b2c",
        "resourceId": "547abdb3-99f8-4040-b030-3296c4668846",
        "resourceName": "exampleResourceName",
        "resourceType": "exampleResourceType",
        "mediaType": "application/json",
        "resourceVersion": "1.42.26",
        "created": "2023-02-22T08:54:14Z",
        "checksum": "sha256:4524f2193da6e5cc28d8a71f268d097891d053d4f206b045347ae117ce70d8ac",
        "previousVersionId": null,
        "nextVersionId": "40829caf-b415-4b1d-91a3-b56dfb6374f4"
      }
    ]
  },
  "contentMetadata": {}
}
    

ResourceId Parameter

The resourceId parameter can be used to filter a particular resource version by its unique ID.

did:example:b5d70adf-31ca-4662-aa10-d3a54cd8f06c?resourceId=5e16a3f9-7c6e-4b6b-8e28-20f56780ee25
    
{
  "title": "Example Verifiable Credential Schema",
  "description": "Example schema for DID-Linked Resources spec",
  "type": "object",
  "properties": {
    "@context": {
      "description": "Defines semantic context of the Example Credential",
      "type": "array",
      "items": { "type": "string", "format": "uri" }
    }
  }
}
    

ResourceCollectionId Parameter

The resourceCollectionId parameter filters all resources linked to a particular DID by the collectionId property. It is recommended that this query is only used when there is one resource linked to a DID. If it is used with multiple resources, it is recommended to be combined with another query parameter such as resourceMetadata=true. Otherwise, it is likely to result in an ambiguous query.

did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c?resourceCollectionId=d8ac0372-0d4b-413e-8ef5-8e8f07822b2c
    
{
  "title": "Example Verifiable Credential Schema",
  "description": "Example schema for DID-Linked Resources spec",
  "type": "object",
  "properties": {
    "@context": {
      "description": "Defines semantic context of the Example Credential",
      "type": "array",
      "items": { "type": "string", "format": "uri" }
    }
  }
}
    

ResourceType Parameter

This parameter filters by the resourceType property. This SHOULD only be used if there is one resource associated with the DID. Otherwise additional filters MAY be added to avoid ambiguous queries.

did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c?resourceType=exampleResourceType
    
{
  "title": "Example Verifiable Credential Schema",
  "description": "Example schema for DID-Linked Resources spec",
  "type": "object",
  "properties": {
    "@context": {
      "description": "Defines semantic context of the Example Credential",
      "type": "array",
      "items": { "type": "string", "format": "uri" }
    }
  }
}
    

ResourceName Parameter

This parameter filters by the resourceName property. This SHOULD only be used if there is one resource associated with the DID. Otherwise additional filters MAY be added to avoid ambiguous queries.

did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c?resourceName=exampleResourceName
    
{
  "title": "Example Verifiable Credential Schema",
  "description": "Example schema for DID-Linked Resources spec",
  "type": "object",
  "properties": {
    "@context": {
      "description": "Defines semantic context of the Example Credential",
      "type": "array",
      "items": { "type": "string", "format": "uri" }
    }
  }
}
    

ResourceName and ResourceType Parameters

This combined filter SHOULD fetch the latest version of the resource with the given name and type.

did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c?resourceName=exampleResourceName&resourceType=exampleResourceType
    
{
  "title": "Example Verifiable Credential Schema",
  "description": "Example schema for DID-Linked Resources spec",
  "type": "object",
  "properties": {
    "@context": {
      "description": "Defines semantic context of the Example Credential",
      "type": "array",
      "items": { "type": "string", "format": "uri" }
    }
  }
}
    

ResourceVersion Parameter

This parameter filters by the resourceVersion field.

did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c?resourceVersion=1.14.41
    
{
  "title": "Example Verifiable Credential Schema",
  "description": "Example schema for DID-Linked Resources spec",
  "version": "1.14.41",
  "type": "object",
  "properties": {
    "@context": {
      "description": "Defines semantic context of the Example Credential",
      "type": "array",
      "items": { "type": "string", "format": "uri" }
    }
  }
}
    

ResourceVersionTime Parameter

This parameter SHOULD always be accompanied by another resource query qualifier.
did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c?resourceVersionTime=2023-02-22T06:58:18Z&resourceVersion=1.14.41
    
{
  "title": "Example Verifiable Credential Schema",
  "description": "Example schema for DID-Linked Resources spec",
  "version": "1.14.41",
  "type": "object",
  "properties": {
    "@context": {
      "description": "Defines semantic context of the Example Credential",
      "type": "array",
      "items": { "type": "string", "format": "uri" }
    }
  }
}
    

Checksum Parameter

This parameter can be used to check that the checksum matches the resource's metadata. If the fetched resource content does not match, the resolver MUST return an "integrityError".

did:example:d8ac0372-0d4b-413e-8ef5-8e8f07822b2c?checksum=sha256:27ad51a49f079a6634b18bbc3ac08dd2d91f13fabf72ea8e5d83692fe4820058
    
{
  "title": "Example Verifiable Credential Schema",
  "description": "Example schema for DID-Linked Resources spec",
  "version": "1.14.41",
  "type": "object",
  "properties": {
    "@context": {
      "description": "Defines semantic context of the Example Credential",
      "type": "array",
      "items": { "type": "string", "format": "uri" }
    }
  }
}
    

Practical Considerations

Creation of a Resource

The creation of a [=DID-Linked Resource=] is defined by the specific capabilities and constraints of the corresponding DID Method. Each method MAY define its own procedures and required parameters for resource creation, provided that the resulting metadata includes the required core properties represented in a valid form of linkedResourceMetadata.

Recommendations for constructing linkedResourceMetadata

DID Methods that support [=DID-Linked Resources=] SHOULD define how linkedResourceMetadata entries are constructed and maintained. Resources with the same resourceName and resourceType MAY be grouped as different versions of the same logical resource, while resources with distinct names and types MAY coexist within the same resourceCollectionId.

Applicability for Non-Ledger DID Methods

This section provides guidance for implementing [=DID-Linked Resources=] in DID methods that do not use a distributed ledger as their verifiable data registry. This includes (but is not limited to) did:web [[DID-WEB]], did:webvh [[DID-WEBVH]], did:key, did:peer, did:jwk, and did:pkh.

Does a DID Method Need to Explicitly Support DLRs?

A common question for implementers is whether a DID method must explicitly support [=DID-Linked Resources=] before a DID controller can begin publishing them. The answer depends on the type of DID method in use.

For ledger-based DID methods, the answer is yes. The ledger controls what is written to didDocumentMetadata, so the method infrastructure must explicitly support [=DID-Linked Resources=] in order for linkedResourceMetadata to be written, stored, and surfaced through resolution.

For non-ledger DID methods such as did:web [[DID-WEB]] and did:webvh [[DID-WEBVH]], a DID controller can adopt [=DID-Linked Resources=] entirely on their own initiative. Publishing linkedResourceMetadata in didDocumentMetadata is itself the act of supporting [=DID-Linked Resources=]. No method-level changes are required. In this sense, DLR support for non-ledger methods is controller-driven rather than method-driven.

The binding verification mechanism in use determines the level of trust a [=conforming DLR Consumer=] can place in the resource. For non-ledger methods, signature-based binding (see ) MUST be used to establish authorization, meaning each linkedResourceMetadata entry MUST include a proof signed by a verification method in the DID Document.

Web-Based DID Methods (did:web)

Web-based DID methods such as did:web [[DID-WEB]] present unique constraints due to the stateless and document-centric nature of HTTP infrastructure.

  • The DID Document and its didDocumentMetadata (including linkedResourceMetadata) SHOULD be published as a JSON or JSON-LD file at the well-known URI defined by the did:web specification.
  • When a new [=DID-Linked Resource=] is created or modified, the published didDocumentMetadata file MUST be updated.
  • Because did:web does not have a built-in consensus mechanism, implementations MUST use signature-based binding (see ). Each resource metadata entry MUST include a proof property.
  • Implementers SHOULD use HTTPS with valid TLS certificates and SHOULD set appropriate cache headers to balance freshness with availability.

Verifiable Web-Based DID Methods (did:webvh)

did:webvh [[DID-WEBVH]] (Web + Verifiable History) extends did:web by adding a cryptographically verifiable, append-only log of DID Document versions. This provides stronger integrity guarantees while retaining web-based hosting.

  • The verifiable log maintained by did:webvh provides a tamper-evident history for the DID Document. [=DID-Linked Resource=] metadata SHOULD be anchored in log entries so that the binding can be verified against the log history.
  • When a new resource is created or superseded, a new log entry SHOULD be published that includes the updated linkedResourceMetadata.
  • Because did:webvh does not rely on a distributed ledger, implementations MUST use signature-based binding (see ). Each resource metadata entry MUST include a proof.
  • The resourceVersionTime parameter (see ) is particularly well-suited to did:webvh deployments because the verifiable log permits exact reconstruction of the DID Document state at any historical timestamp.

Static DID Methods (did:key, did:jwk)

Static DID methods derive the DID Document deterministically from the DID itself and do not support DID Document updates.

  • The linkedResourceMetadata cannot be stored in didDocumentMetadata (since the DID Document is not mutable). Instead, the resource metadata and proof SHOULD be stored alongside the resource itself and provided to the [=conforming DLR Consumer=] by the same channel that delivers the resource URI.
  • The [=conforming DLR Consumer=] MUST verify the proof by resolving the DID and validating the proof signature against the deterministic DID Document.

Peer DID Methods (did:peer)

Peer DID methods are designed for pairwise or small-group interactions and typically do not publish DID Documents to a public registry.

  • [=DID-Linked Resources=] and their metadata are exchanged directly between peers, typically over DIDComm or a similar secure messaging protocol.
  • Signature-based binding (see ) MUST be used to establish authorization.
  • The resource metadata (including the proof) SHOULD be transmitted alongside the resource content, rather than being fetched from a public endpoint.

Cross-Method Resource Resolution

A [=DID-Linked Resource=] does not need to be stored on the same infrastructure as the DID that references it. Because the resourceUri and alternativeUri properties are standard URIs conforming to [[RFC3986]], they can point to any addressable location, including a DID URL belonging to a different DID method. This applies equally to ledger-based and non-ledger DID methods.

The key principle is that linkedResourceMetadata is the trust anchor, regardless of where it is published. The resource itself can live anywhere addressable. This decouples where the resource is stored from where the trust anchor lives, enabling a range of practical deployment patterns:

  {
    "resourceUri": "did:web:example.com/resources/f3d9a1bc-4e2f-4c7a-b895-1234567890ab",
    "resourceCollectionId": "example.com",
    "resourceId": "f3d9a1bc-4e2f-4c7a-b895-1234567890ab",
    "resourceName": "AccreditationSchema",
    "resourceType": "JSONSchema2020",
    "mediaType": "application/json",
    "created": "2024-09-01T09:00:00Z",
    "checksum": "sha256:b94d27b9934d3e08a52e52d7da7dabfa...",
    "alternativeUri": [
      "did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J/resources/f3d9a1bc-4e2f-4c7a-b895-1234567890ab"
    ],
    "proof": {
      "type": "DataIntegrityProof",
      "cryptosuite": "eddsa-jcs-2022",
      "verificationMethod": "did:web:example.com#key-1",
      "created": "2024-09-01T09:00:00Z",
      "proofPurpose": "assertionMethod",
      "proofValue": "z4Q8..."
    }
  }
    

In this example, a did:web controller publishes linkedResourceMetadata with an alternativeUri pointing to a did:cheqd resource. A [=conforming DLR Consumer=] that supports both DID methods can dereference either URI to retrieve the resource. The did:cheqd URI provides ledger-backed immutability and consensus validation; the did:web linkedResourceMetadata provides the index, version chain, and controller-signed proof.

This pattern is particularly well-suited to did:webvh [[DID-WEBVH]] deployments. The verifiable append-only log provides a tamper-evident history of the linkedResourceMetadata entries, meaning a [=conforming DLR Consumer=] can verify both that the metadata was present at a specific point in time and that the resource content has not been modified, by combining the log history with the checksum in the metadata and the integrity guarantees of the ledger-based alternativeUri.
A [=conforming DLR Consumer=] resolving a cross-method resource MUST support the DID methods of both the DID and the alternativeUri in order to fully verify the resource. Implementations SHOULD clearly communicate to relying parties which URIs were successfully resolved and verified, and which were not, so that the level of assurance can be correctly understood.

Resolver-Driven DLR Support

The DLR model described in this specification assumes that linkedResourceMetadata is published in didDocumentMetadata, providing a standardised index of resources associated with a DID. However, there is an alternative deployment model in which the resolver itself takes on responsibility for locating, fetching, and verifying resources, without requiring the DID method to surface linkedResourceMetadata at all.

In this model:

This approach is practically viable and may already reflect how some implementations work, particularly in closed or well-defined ecosystems where resource locations are predictable and the resolver is under the control of the consuming application.

The primary trade-off compared to the standard DLR model is discoverability. Without linkedResourceMetadata, there is no standardised way for a [=conforming DLR Consumer=] to ask what resources exist under a given DID, traverse version history, or filter by resourceName or resourceType. The resolver must have out-of-band knowledge of where to look, which works well in constrained ecosystems but limits interoperability in open ones.

Property Standard DLR Model Resolver-Driven Model
Resource discovery Via linkedResourceMetadata index in didDocumentMetadata Resolver has prior knowledge of resource locations
Integrity verification Checksum and proof anchored in linkedResourceMetadata Proof travels with the resource itself
Method dependency Method must surface linkedResourceMetadata through resolution Method only needs to resolve the DID Document
Version traversal Supported via previousVersionId and nextVersionId chain Not supported without additional out-of-band convention
Openness Any [=conforming DLR Consumer=] can discover and verify resources Requires resolver awareness of the specific ecosystem
Resolver-driven DLR support is a valid deployment model and is not precluded by this specification. Implementations adopting this model SHOULD ensure that each resource carries a proof conforming to [[VC-DATA-INTEGRITY]], signed by a verification method in the DID Document, so that a [=conforming DLR Consumer=] can independently verify the resource without relying solely on the resolver's prior knowledge. Where possible, implementations SHOULD also consider publishing linkedResourceMetadata to support discoverability and interoperability with consumers that do not have resolver-specific knowledge.

Access Control and Provenance

Each DID Method or implementation MAY define mechanisms to ensure the authenticity, authorization, and integrity of linked resources. This MAY include cryptographic proofs within the metadata, DID-based access control lists, or binding to verifiable credentials. Provenance and auditability of resource updates SHOULD be considered, particularly when supporting mutable resources or collaborative workflows.

Resource Lifecycle

Lifecycle Stage Description Expected Behavior
Creation A new resource is published under a DID for the first time. A new linkedResourceMetadata entry is added. previousVersionId is empty. The [=conforming DLR Producer=] MUST generate a unique resourceId.
Update A new version of an existing resource is published. A new linkedResourceMetadata entry is added with a new resourceId. The previousVersionId of the new entry SHOULD reference the previous version's resourceId. The resourceName and resourceType SHOULD remain the same.
Deprecation A resource is marked as no longer recommended for use, but remains accessible. The resource metadata MAY include a deprecated: true flag (see ). [=Conforming DLR Consumers=] SHOULD still be able to dereference the resource.
Deactivation A resource is permanently removed from active use. The DID method defines whether the resource is purged or retained in an archived state.

Surfacing a VC DLR as a Linked Verifiable Presentation

When a [=DID-Linked Resource=] contains a Verifiable Credential (VC), that credential MAY also be publicly discoverable through the DIF [[LINKED-VP]] specification. This section describes how the two specifications can be composed.

[[LINKED-VP]] enables a DID controller to advertise publicly accessible Verifiable Presentations via a LinkedVerifiablePresentation service endpoint in the DID Document. When a DLR holds a VC that the controller wishes to make publicly discoverable, the controller MAY wrap that VC in a Verifiable Presentation and expose it through both mechanisms simultaneously:

  1. The underlying VC (or the VP wrapping it) is published as a [=DID-Linked Resource=] and assigned a resourceUri in the usual way.
  2. A LinkedVerifiablePresentation service endpoint is added to the DID Document. The serviceEndpoint value SHOULD be set to the DLR URL (the resourceUri) of the resource, making the DLR URL the canonical retrieval address.
{
  "service": [
    {
      "id": "did:web:example.com#accreditation-vp",
      "type": "LinkedVerifiablePresentation",
      "serviceEndpoint": [
        "did:web:example.com/resources/f3d9a1bc-4e2f-4c7a-b895-1234567890ab"
      ]
    }
  ]
}
    
{
  "resourceUri": "did:web:example.com/resources/f3d9a1bc-4e2f-4c7a-b895-1234567890ab",
  "resourceCollectionId": "example.com",
  "resourceId": "f3d9a1bc-4e2f-4c7a-b895-1234567890ab",
  "resourceName": "AccreditationCredential",
  "resourceType": "VerifiableCredential",
  "mediaType": "application/vc+ld+json",
  "created": "2024-09-01T09:00:00Z",
  "checksum": "sha256:b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
  "previousVersionId": "",
  "nextVersionId": "",
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "eddsa-jcs-2022",
    "verificationMethod": "did:web:example.com#key-1",
    "created": "2024-09-01T09:00:00Z",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4Q8..."
  }
}
    

This composition provides several benefits:

Implementers SHOULD be aware of the privacy implications noted in the [[LINKED-VP]] specification: linked VPs are publicly accessible and potentially indexable. This pattern is appropriate for organizational or institutional credentials (e.g., accreditations, licences, registrations) where public discoverability is desirable. It is NOT appropriate for personal, sensitive, or selective-disclosure credentials.

Security Considerations

Proving Control and Binding

To ensure that a [=DID-Linked Resource=] is legitimately associated with a DID, DID methods MUST specify which [=Binding Verification Mechanism=](s) (see ) are supported and what a [=conforming DLR Consumer=] MUST verify.

DID Methods SHOULD specify which verification relationship (e.g., authentication, assertionMethod, capabilityInvocation) is required for resource operations. If a DID method does not specify a verification relationship, [=conforming DLR Consumers=] SHOULD default to requiring assertionMethod.

Alternative Resource Locations

[=DID-Linked Resources=] MAY reside at locations different from the storage or resolution infrastructure used by the DID itself. In such cases, the external location SHOULD be clearly specified in the resourceUri field within linkedResourceMetadata.

Parent DID Deactivation

If a parent DID is deactivated, the status of its associated [=DID-Linked Resources=] SHOULD be clearly defined by the DID Method. It is RECOMMENDED that child resources automatically inherit the deactivated status of the parent DID.

Integrity Verification

[=Conforming DLR Consumers=] SHOULD verify the integrity of fetched resources whenever a checksum is present in the resource metadata:

  1. Fetch the resource content from the resourceUri.
  2. Parse the checksum value to extract the algorithm-id (the portion before the colon) and the hex-string (the portion after the colon). If the value does not contain a colon separator, the checksum is non-conforming; see the backward-compatibility note in .
  3. Compute the cryptographic hash of the fetched content using the algorithm identified by algorithm-id.
  4. Compare the computed hash (hex-encoded, lowercase) with the hex-string from the checksum value.
  5. If the hashes do not match, the [=conforming DLR Consumer=] MUST treat the resource as untrusted and SHOULD return an error with error set to "integrityError".

sha256 is RECOMMENDED as a baseline hash algorithm. See for the full list of defined algorithm identifiers.

Privacy Considerations

Linkability and Pseudonymity

Resources SHOULD NOT contain personally identifiable information. This is particularly important for ledger-based DID methods, where resource content may be publicly visible and immutable. Even when resource content does not contain PII directly, the metadata itself (such as resource names, types, and creation timestamps) can reveal patterns about the DID controller's activities.

Immutability

For DID methods that store resources on immutable infrastructure (e.g., blockchains, content-addressable storage), resource content cannot be deleted or modified after publication. DID controllers SHOULD carefully consider what data is included in resources before publishing.

Encrypted Data in Resources

DID Methods MAY introduce encryption for their resources, to protect the information contained in the resource or to gate access to the resource.

Architectural Considerations

Resource Versioning

Multiple resources can be stored within a collection and linked to the same DID. Resources that contain both a resourceName and a resourceType SHOULD be treated as part of a versioning sequence. DID methods SHOULD treat resources with identical resourceName and resourceType as sequential versions when accompanied by differing resourceId values.

Resources in Service Endpoint versus DID Document Metadata

[=DID-Linked Resources=] are not defined through service endpoints; the authoritative binding, metadata, and version history for every resource lives in linkedResourceMetadata within the didDocumentMetadata section of the DID Document. Service endpoints MUST NOT be used as the primary mechanism for expressing or managing [=DID-Linked Resources=].

However, a DLR URL MAY be referenced from a service endpoint for the purpose of discoverability by external specifications. For example, the [[LINKED-VP]] specification allows a DID controller to advertise publicly accessible Verifiable Presentations via a LinkedVerifiablePresentation service endpoint. When a DLR contains a credential or presentation that should be discoverable in this way, the serviceEndpoint value MAY point to the resourceUri of the corresponding DLR (see ). In such cases:

Resource Deactivation or Deprecation

DID Methods MAY support additional metadata properties that indicate the deactivation or deprecation status of a resource. For example, a deprecated: true or deactivated: true flag within the resource metadata can alert consuming systems not to rely on the resource without requiring immediate deletion.

Implementations SHOULD continue to support dereferencing of deprecated resources for archival and verification purposes, unless policy or security requirements dictate otherwise.

Resource Extensions

The base structure of linkedResourceMetadata is intentionally flexible to support evolving use cases. Future specifications or community registries MAY define extensions. Examples include: