Skip to content
Proposed specification for review. We are seeking feedback on key architectural choices in the industry consultation.

Schemas

PDTF 2.0 models transaction data as an entity graph. The development artifact is a v4 combined schema with ID-keyed maps. Standalone entity schemas are extracted from that combined schema and become the expected credentialSubject shapes for W3C Verifiable Credentials.

EntityIdentifierSchema roleDescription
Transactiondid:web:{host}:transactions:{id}Root entitySale metadata, milestones, chain, sale context, completion, seller confirmations
Propertyurn:pdtf:uprn:{uprn}Logbook entityPhysical property facts that travel with the property across transactions
Titleurn:pdtf:titleNumber:{number} or urn:pdtf:unregisteredTitle:{id}Legal title entityRegister extract, title extents, ownership type, leasehold terms, encumbrances
Persondid:key:{...}Identity entityNatural person, role-free, referenced by relationship entities
Organisationdid:web:{domain}Identity entityLaw firm, estate agent, lender, surveyor, etc. Outside the v3 round trip
SellerCapacityurn:pdtf:capacity:{id}Relationship credentialThe capacity in which a party sells; implies Seller
Offerurn:pdtf:offer:{id}Relationship credentialBuyer linkage to transaction, amount, status, conditions; implies Buyer
Gifturn:pdtf:gift:{id}Relationship credentialGift of funds towards an offer; implies Giftor
Representationurn:pdtf:representation:{id}Relationship credentialOne party instructed by another, with the kind of representation
TransactionRoleurn:pdtf:role:{id}Relationship credentialA role with no more specific relationship

The v4 combined schema uses ID-keyed collections rather than arrays. The Transaction keeps an ordered roster of parties; every relationship credential references the transaction and lives in its own collection.

{
"$schema": "https://trust.propdata.org.uk/schemas/v4/combined.json",
"id": "did:web:platform.example.com:transactions:abc123",
"transactionId": "abc123",
"status": "Active",
"saleContext": {},
"milestones": {},
"contracts": [],
"chain": {},
"offers": { "o1": {} },
"enquiries": {},
"property": "urn:pdtf:uprn:100023456789",
"titlesToBeSold": ["urn:pdtf:titleNumber:AB12345"],
"participants": [
{ "participant": "did:key:z6Mkh...", "participantId": "s1" },
{ "participant": "did:key:z6Mkj...", "participantId": "c1", "organisation": "Smith & Co Law", "organisationReference": "R1" }
],
"persons": { "did:key:z6Mkh...": {} },
"organisations": { "did:web:smithandco.law": {} },
"properties": { "urn:pdtf:uprn:100023456789": {} },
"titles": { "urn:pdtf:titleNumber:AB12345": {} },
"sellerCapacities": { "urn:pdtf:capacity:own-1": {} },
"offerCredentials": { "urn:pdtf:offer:off-1": {} },
"gifts": { "urn:pdtf:gift:gf-1": {} },
"representations": { "urn:pdtf:representation:rep-1": {} },
"transactionRoles": { "urn:pdtf:role:tr-1": {} }
}

The roster carries only what stays true of a party regardless of any relationship: DID, transaction-local id, and firm. Role and every relationship live on the credentials, so that revoking a credential removes what it asserts (see 01 — Entity Graph).

Identifier: did:web

Contains:

  • transactionId, externalIds, metadata
  • status
  • saleContext (residual sale-level ownership facts: outstanding mortgage, Help to Buy, number of sellers, legal owners)
  • milestones
  • contracts
  • chain
  • offers, enquiries
  • valuationComparisonData
  • property and titlesToBeSold references
  • participants[] roster: participant DID, participantId, organisation, organisationReference

Does not contain: embedded property logbook data, title register data, or any party’s role. Roles live only on the relationship credentials.

Identifier: urn:pdtf:uprn:{uprn}

Rule: if the next buyer needs to know it, it belongs on Property.

Typical sections:

  • address
  • location
  • localAuthority
  • priceInformation
  • lettingInformation
  • summaryDescription
  • marketingTenure
  • media
  • buildInformation
  • residentialPropertyFeatures
  • nearbyFacilities
  • delayFactors
  • parking
  • listingAndConservation
  • typeOfConstruction
  • energyEfficiency
  • councilTax
  • disputesAndComplaints
  • alterationsAndChanges
  • notices
  • specialistIssues
  • fixturesAndFittings
  • electricity
  • waterAndDrainage
  • heating
  • connectivity
  • insurance
  • rightsAndInformalArrangements
  • environmentalIssues
  • otherIssues
  • additionalInformation
  • consumerProtectionRegulationsDeclaration
  • legalBoundaries
  • servicesCrossing
  • electricalWorks
  • smartHomeSystems
  • guaranteesWarrantiesAndIndemnityInsurances
  • occupiers
  • localSearches
  • searches
  • documents
  • surveys
  • valuations

Explicitly moved elsewhere:

v3 areaNew entity
titlesToBeSoldTitle
ownership.ownershipsToBeTransferredTitle (tenure details, correlated by titleNumber)
the rest of ownership, and legalOwnersTransaction.saleContext

Identifier:

  • Registered: urn:pdtf:titleNumber:{number}
  • Unregistered: urn:pdtf:unregisteredTitle:{id}

Contains:

  • titleExtents
  • registerExtract
  • additionalDocuments
  • ownershipType
  • leaseholdInformation, managedFreeholdOrCommonholdInformation, estateRentcharges, wholeFreeholdForSale where relevant
  • titleRestrictions, keyFacts, covenantAnalysis

Important: tenure details such as freehold or leasehold belong here, not on SellerCapacity.

Identifier: did:key

Contains:

  • name
  • dateOfBirth
  • phone, email
  • address
  • verification (identity, anti-money-laundering, source of funds)
  • participantStatus
  • externalIds

Does not contain: transaction role. Roles are conveyed via SellerCapacity, Offer, Gift, Representation and TransactionRole. A Person’s did:key is stable across transactions.

Identifier: did:web

Contains:

  • name, tradingName
  • organisationType
  • companiesHouseNumber, vatNumber, regulatoryIds
  • registeredAddress, phone, email, website
  • externalIds

Usage note: organisations are first-class graph entities and the one entity outside the v3 round trip. A participant’s firm is recorded by name and reference on the Transaction roster; resolving the participant’s DID gives the Organisation.

Identifier: urn:pdtf:capacity:{id}

Shape: thin relationship schema. Implies the Seller role; issued for every seller.

{
"id": "urn:pdtf:capacity:own-a1b2c3",
"seller": "did:key:z6Mkh...",
"transaction": "did:web:platform.example.com:transactions:tx-789",
"sellersCapacity": { "capacity": "Legal Owner" },
"dateBecameOwnerOrAuthority": "2014-06-01"
}

title is optional: v3 does not tie a seller’s capacity to a particular title, so a sale of several titles yields a capacity scoped to the transaction.

Identifier: urn:pdtf:offer:{id}

Implies the Buyer role. Always identifies exactly one buyer.

{
"id": "urn:pdtf:offer:off-j1k2l3",
"buyer": "did:key:z6Mkh...",
"transaction": "did:web:platform.example.com:transactions:tx-789",
"offerId": "o1",
"amount": 450000,
"currency": "GBP",
"status": "Accepted",
"conditions": ["Subject to survey"],
"buyerCircumstances": {
"isFirstTimeBuyer": true,
"mortgageRequired": true
}
}

Identifier: urn:pdtf:gift:{id}

Implies the Giftor role. Carries the giftor’s link to the offer, so that Offer always means buyer.

{
"id": "urn:pdtf:gift:gf-m4n5o6",
"donor": "did:key:z6Mkp...",
"transaction": "did:web:platform.example.com:transactions:tx-789",
"offerId": "o1",
"giftDetails": {
"amount": 50000,
"currency": "GBP",
"relationshipToBuyer": "Parent",
"fundsTransferred": "None",
"repayable": false,
"confersBeneficialInterest": false,
"willOccupyProperty": false
}
}

Identifier: urn:pdtf:representation:{id}

One per (representative, represented party) pair. The represented party is a person or organisation, never an offer. The representative’s firm is on the Transaction roster.

{
"id": "urn:pdtf:representation:rep-d4e5f6",
"representative": "did:key:z6Mkj...",
"representedParty": "did:key:z6Mkh...",
"role": "Seller's Conveyancer",
"transaction": "did:web:platform.example.com:transactions:tx-789"
}

Role enum (shared with TransactionRole and the v3 participant roles): Seller, Seller's Conveyancer, Prospective Buyer, Buyer, Buyer's Conveyancer, Giftor, Estate Agent, Buyer's Agent, Surveyor, Mortgage Broker, Lender, Landlord, Tenant, Platform Support.

Identifier: urn:pdtf:role:{id}

A party’s role where no more specific relationship credential applies. Asserts participation in a role, not a relationship to another named party.

{
"id": "urn:pdtf:role:tr-g7h8i9",
"participant": "did:web:bigbank.co.uk",
"role": "Lender",
"transaction": "did:web:platform.example.com:transactions:tx-789"
}
Collectionv3 formv4 formKey source
Participantsarrayparticipants[] roster + persons{} / organisations{}DID
Titles to be soldarraytitles{}title URN
Offersobjectoffers{}offer URN
SearchesarrayID-keyed mapprovider reference or generated ID
DocumentsarrayID-keyed mapgenerated ID
SurveysarrayID-keyed mapgenerated ID
ValuationsarrayID-keyed mapvaluationId
ContractsarrayID-keyed mapgenerated ID
Chain onward purchasearrayID-keyed maptransactionId

Entity schemas are generated from the v3 combined schema by npm run generate:v4 in the schemas repository, not hand-maintained separately. The same run emits a mapping manifest (v3 pointer → entity + pointer, and the inverse) and decompose / recompose helpers, and fails if any v3 field has no home in v4.

Extracted schemaSource in v4 combined
Transaction.jsontop-level fields excluding entity collections
Property.jsonproperties[*]
Title.jsontitles[*]
Person.jsonpersons[*]
Organisation.jsonorganisations[*]
SellerCapacity.jsonprojected from participants[*] on the Seller branch
Offer.jsonprojected from participants[*] carrying an offerId, merged with offers[offerId]
Gift.jsonprojected from participants[*] on the Giftor branch
Representation.jsonprojected from participants[*] with actingFor
TransactionRole.jsonprojected from participants[*] with a role and no other role-bearing credential
  • State assembly starts from Transaction.
  • Property and title entities are merged by identifier.
  • Relationship credentials populate graph links and carry role; they do not duplicate canonical source data.
  • Sparse credential payloads are deep-merged during composition.
  • Dependency pruning is applied after merge to remove schema-invalid subtrees when discriminators change.
  • Arrays that are true value lists remain arrays.
  • Arrays that identify graph nodes or mutable collections become ID-keyed maps.
  • SellerCapacity is intentionally thin. Title evidence remains on Title.registerExtract.
  • Representation, SellerCapacity, Offer, Gift and TransactionRole are part of the round trip: dropping one and recomposing gives a v3 instance in which that party has no role and no relationship.
  • Property is governed by the logbook test, Transaction by this sale only, Title by legal title intrinsic facts.