Retrieve Credentials
Once a property transaction is underway, the resulting Verifiable Credentials (VCs) do not live in a central database. They reside in the digital wallets or encrypted data hubs of the participating parties (like a conveyancer’s CMS or a data hub like LMS).
To access this data, consumers must know:
- Where to ask (Discovered via the Transaction’s DID Document)
- How to authenticate (Using the relationship credential that ties you to the transaction, such as
RepresentationorTransactionRole) - What protocol to use (OID4VP for systems, MCP for agents)
1. Discovering the Service Endpoint
Section titled “1. Discovering the Service Endpoint”Every property transaction has a Decentralised Identifier (e.g., did:web:platform.example.com:transactions:abc123).
Before requesting credentials, you must resolve this DID to find the correct data hub.
The Request
Section titled “The Request”import { DidResolver } from '@pdtf/core';
const resolver = new DidResolver();const didDocument = await resolver.resolve('did:web:platform.example.com:transactions:abc123');use pdtf_core::did::resolver::DidResolver;
let resolver = DidResolver::new()?;let did_doc = resolver.resolve( "did:web:platform.example.com:transactions:abc123").await?;from pdtf_core import DidResolver
resolver = DidResolver()did_document = resolver.resolve("did:web:platform.example.com:transactions:abc123")using Pdtf.Core;
var resolver = new DidResolver();var didDocument = await resolver.Resolve( "did:web:platform.example.com:transactions:abc123");The Response
Section titled “The Response”The DID document contains a service array declaring where requests should be sent:
{ "id": "did:web:platform.example.com:transactions:abc123", "service": [ { "id": "#oid4vp", "type": "OID4VP", "serviceEndpoint": "https://platform.example.com/api/v1/transactions/abc123/present" }, { "id": "#mcp", "type": "ModelContextProtocol", "serviceEndpoint": "wss://platform.example.com/mcp/v2/transactions/abc123" } ]}You now know the exact URLs for both system-to-system (OID4VP) and agentic (MCP) access.
2. Discovery Mechanism — Public vs Authenticated Data
Section titled “2. Discovery Mechanism — Public vs Authenticated Data”Not all property data requires authentication. PDTF distinguishes between public property data and transaction-specific data, and they have different access patterns.
Public data: query by Property URN
Section titled “Public data: query by Property URN”Public property information — such as EPC certificates, HM Land Registry title summaries, and local authority planning data — can be queried from a platform’s public API or MCP endpoint using only the Property URN (e.g., urn:pdtf:uprn:100023336956).
No Representation or TransactionRole credential is needed. The data is already public record, and the VCs wrapping it serve to prove provenance and issuer trust, not to restrict access.
# Query public credentials for a propertycurl https://platform.example.com/api/v1/properties/urn:pdtf:uprn:100023336956/credentialsThe response contains signed VCs from authorised adapters — EPC data signed by the EPC adapter, title register summaries signed by the HMLR adapter, and so on. A consumer can verify these credentials using VcValidator to confirm they are genuine and unrevoked, without needing any relationship to the transaction.
How to discover a property
Section titled “How to discover a property”Discovery starts with a Property URN. In England and Wales this is typically a UPRN (Unique Property Reference Number). If you don’t have the UPRN, platforms may offer a search endpoint:
# Address-based property lookupcurl "https://platform.example.com/api/v1/properties/search?postcode=SW1A+2AA"This returns matching Property URNs, which you can then use to fetch public credentials.
Transaction-specific data: requires graph traversal with auth
Section titled “Transaction-specific data: requires graph traversal with auth”Transaction data — status, agreed price, conditions, chain position, legal pack documents — is not public. Accessing it requires:
- A valid
Representation,TransactionRoleorOffercredential proving your relationship to the transaction - The Transaction DID (not just the Property URN)
- Authentication via OID4VP or MCP as described in sections 3 and 4 below
The platform traverses the entity graph to verify that the requesting party has a legitimate role before returning any transaction-scoped credentials.
Summary
Section titled “Summary”| Data type | Identifier needed | Auth required | Example |
|---|---|---|---|
| Public property data | Property URN | None | EPC, title summary, flood risk |
| Transaction-specific data | Transaction DID | Representation, TransactionRole or Offer VC | Price, status, legal pack |
This separation means read-only consumers (property portals, market analysts, valuation tools) can access public property intelligence without being party to any transaction, while sensitive transaction data remains protected by the entity graph’s access control model.
3. API Access (OID4VP)
Section titled “3. API Access (OID4VP)”Traditional data consumers (like a lender’s automated underwriting system) use the OpenID for Verifiable Presentations (OID4VP) protocol.
In PDTF 2.0, authorisation is based entirely on the entity graph. You cannot access a transaction unless you hold a capability token (such as a Representation or TransactionRole credential) that proves you have the right to see it.
The Request
Section titled “The Request”You send a POST request to the discovered OID4VP endpoint. The payload contains a W3C Presentation Exchange definition detailing what you need, along with the Verifiable Presentation proving your right to access it.
curl -X POST https://platform.example.com/api/v1/transactions/abc123/present \ -H "Content-Type: application/json" \ -d '{ "presentation_definition": { "id": "lender_request_1", "input_descriptors": [ { "id": "property_data", "constraints": { "fields": [ { "path": ["$.type"], "filter": { "contains": "PropertyCredential" } }, { "path": ["$.type"], "filter": { "contains": "TitleCredential" } } ] } } ] }, "vp_token": { "@context": ["https://www.w3.org/ns/credentials/v2"], "type": ["VerifiablePresentation"], "verifiableCredential": [ { "... TransactionRole VC ..." } ], "proof": { "... Your signature over the request ..." } } }'The Response
Section titled “The Response”The platform validates your TransactionRole, traverses the transaction graph, and returns the requested credentials bundled into a Verifiable Presentation.
{ "vp_token": { "@context": ["https://www.w3.org/ns/credentials/v2"], "type": ["VerifiablePresentation"], "verifiableCredential": [ { "type": ["VerifiableCredential", "PropertyCredential"], "credentialSubject": { "id": "urn:pdtf:uprn:123", "..." : "..." } }, { "type": ["VerifiableCredential", "TitleCredential"], "credentialSubject": { "id": "urn:pdtf:titleNumber:ABC", "..." : "..." } } ] }}4. Agentic Access (MCP)
Section titled “4. Agentic Access (MCP)”AI Agents (like a conveyancer’s copilot) access the exact same data using the Model Context Protocol (MCP). The authorisation logic is identical, but the transport and interface are designed for LLMs rather than traditional APIs.
The Connection
Section titled “The Connection”The agent connects to the WebSocket endpoint discovered in the DID Document. During the MCP handshake, the agent authenticates by signing a challenge using the firm’s did:key or did:web private key.
The Request (Tool Call)
Section titled “The Request (Tool Call)”Once connected, the agent asks for the data using the get_credentials tool.
{ "jsonrpc": "2.0", "id": "req_1", "method": "tools/call", "params": { "name": "get_credentials", "arguments": { "id": "did:web:platform.example.com:transactions:abc123" } }}The Validation
Section titled “The Validation”The MCP server intercepts this tool call. It knows the identity of the connected agent (e.g., did:web:smithandco.law). It traverses the transaction graph to see if smithandco.law holds a valid Representation credential for the seller. Because the graph proves the relationship, access is granted.
The Response
Section titled “The Response”The server returns the credentials directly into the LLM’s context window.
{ "jsonrpc": "2.0", "id": "req_1", "result": { "content": [ { "type": "text", "text": "{\"type\": [\"PropertyCredential\"], \"credentialSubject\": {\"address\": \"10 Downing Street\"}}" } ] }}From there, the agent can use the @pdtf/core state assembly tools to resolve the raw credentials into a flat, readable v4 entity state or v3 JSON object to continue its reasoning.