Modelling Updated 2026-05-14

PDTF overlays

An overlay is a JSON-Schema artefact that adds one form, search or document to the base PDTF transaction schema. Overlays are the unit of composition the schema package ships in — pick the ones your use case needs, merge them on top of the base, and you get a complete validating schema.

Headline numbers
  • 1 base transaction schema — pdtf-transaction.json (not an overlay)
  • 18 main overlays in v3/overlays/*.json
  • 16 extension overlays in v3/overlays/extensions/*.json (modular NTS2 pieces)
  • 34 overlay files total in PDTF v3

combined.json and skeleton.json at the v3 root aren't overlays — the first is a pre-merged convenience view, the second is a starter template for empty transactions.

What an overlay is — and is not

An overlay is a draft-07 JSON Schema that mirrors the shape of the base transaction but only specifies what it adds or constrains. The merge function turns the base + overlays into a complete schema.

DimensionOverlayBounded context (DDD)
LayerSchema layer — JSON Schema filesDomain layer — language and rules of a business function
GranularityOne form, search or document (BASPI, TA6, CON29R …)An entire industry function (Estate Agency, Conveyancing …)
Lives inv3/overlays/*.json in the schemas repoArchitecture documentation (see Bounded contexts)
Who picks itDeveloper assembling a runtime schemaBusiness architect modelling the domain
CardinalityMany overlays per bounded contextOne bounded context owns several overlays

Overlays predate the DDD analysis — the bounded-context model is a retrofit onto a partition that was already there. So the answer to "are overlays the same as bounded contexts?" is: no, but they map cleanly onto them.

The catalogue

Main overlays (18)

Bounded context is the business domain the overlay belongs to (one of six). Status is the lifecycle state of the overlay file: active means current, superseded / legacy means a newer overlay covers the same form but the older one is still shipped in v3 for backward compatibility. The two are orthogonal — every legacy overlay still belongs to its original bounded context.

Property information forms

What the seller declares about the property.

FormFileVersionBounded contextStatus
Buyers and Sellers Property Informationbaspi5.jsonv5.0Estate Agencyactive
Buyers and Sellers Property Informationbaspi4.jsonv4.0Estate Agencysuperseded by baspi5
NTS Material Information (Sales)nts2.json2025Estate Agencyactive
NTS Material Information (Sales)nts.json2023Estate Agencylegacy — superseded by nts2
NTS Material Information (Lettings)ntsl2.json2025Estate Agencyactive
NTS Material Information (Lettings)ntsl.json2023Estate Agencylegacy — superseded by ntsl2
Property Information Questionnairepiq.jsonv3Surveyingactive

What the conveyancer asks for.

FormFileVersionBounded contextStatus
Property Information Formta6.jsonEdition 4Conveyancingactive
Leasehold Information Formta7.jsonEdition 3Conveyancingactive
Fittings and Contents Formta10.jsonEdition 3Conveyancingactive

Search and survey forms

What the third-party data providers return.

FormFileVersionBounded contextStatus
Local Authority Searchcon29R.json2019Property Data Servicesactive
Drainage and Water Searchcon29DW.jsoncurrentProperty Data Servicesactive
Leasehold Property Enquirieslpe1.jsonEdition 4Conveyancingactive
Freehold Management Enquiriesfme1.jsonEdition 2Mortgage Lendingactive
Local Land Charges Searchllc1.jsonv2Property Data Servicesactive
Optional Enquiries of Local Authorityoc1.jsonv21Property Data Servicesactive

Specialist

Newer overlays covering domain-specific data.

FormFileVersionBounded contextStatus
Residential Development Surveyrds.jsonv3.3.3Property Data Servicesactive
Sustainability Report 2024sr24.json2024Property Data Servicesactive

Extension overlays (16)

Modular sub-pieces of NTS2 — opt into them individually on top of an NTS 2023 base. Each adds one specific feature so adopters can stage their migration from NTS → NTS2 without committing to the entire 2025 spec at once.

GroupKeyDescriptionNTS2 ref
Specialist issues asAsbestosA5.2
drDry-rot treatmentA5.1
jkJapanese knotweedA5.3
sbSubsidence / structural faultsA5.4
hsHealth & safety issuesA5.5
Property features oaOutside areas (garden / balcony / communal)
laLoft access & insulationA4.1
sfSpray-foam insulationA4.2
mcMain construction type
Ownership & financial erEstate rentcharges (freehold)A3.2
maManaging agent (leasehold)A1.5.4
tfTransfer feesA3.5.1.1
Utilities & services slSolar-panel ownershipB3.7.1
hiHeating installation dateB3.4.3.2
fdFlood defences
Transaction ocOther property chain dependency

How an overlay is defined

Every overlay is a draft-07 JSON Schema with this skeletal shape:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://trust.propdata.org.uk/schemas/v3/overlays/baspi5.json",
  "required": ["participants", "propertyPack"],
  "properties": {
    "propertyPack": {
      "baspi5Ref": "B",
      "required": ["priceInformation", "ownership", "..."],
      "properties": {
        "priceInformation": {
          "baspi5Ref": "B.1",
          "properties": { /* … */ }
        }
      }
    }
  }
}

The pieces that make an overlay an overlay:

How overlays are used at runtime

Composition happens via the library entrypoint getTransactionSchema(schemaId, overlays[]) in index.js:

const { getTransactionSchema } = require('@pdtf/schemas');

// Estate-agency product:
const eaSchema = getTransactionSchema(
  "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json",
  ["baspi5", "nts2"]
);

// Conveyancer product:
const cnvSchema = getTransactionSchema(
  "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json",
  ["ta6", "ta7", "ta10", "lpe1"]
);

// Selective NTS → NTS2 migration:
const stagedSchema = getTransactionSchema(
  "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json",
  ["nts2023", "jk", "tf"]  // NTS 2023 + Japanese knotweed + transfer fees
);

Under the hood, the merge pipeline is:

flowchart LR classDef src fill:#eef4f8,stroke:#1a4d80,color:#0b2545; classDef proc fill:#fef3c7,stroke:#b45309,color:#7c2d12; classDef out fill:#dcfce7,stroke:#166534,color:#14532d; BASE[pdtf-transaction.json
base transaction schema]:::src O1[Overlay 1
e.g. baspi5]:::src O2[Overlay 2
e.g. nts2]:::src O3[Overlay n …]:::src MERGE["deepmerge( base, O1, O2, … )
+ custom arrayMerge for
required & oneOf"]:::proc RESULT[Merged schema
complete and validatable]:::out BASE --> MERGE O1 --> MERGE O2 --> MERGE O3 --> MERGE MERGE --> RESULT
deepmerge with a custom arrayMerge: required arrays are unioned, oneOf arrays are concatenated, and the rest follows ordinary object-merge rules.

Names and aliases

Overlays are registered in overlaysMap[schemaId] in index.js under versioned aliases as well as the plain filename stem. Both work:

Alias in overlaysMapFile
baspiV4baspi4.json
baspiV5baspi5.json
ta6ed4ta6.json
ta7ed3ta7.json
ta10ed3ta10.json
lpe1ed4lpe1.json
fme1ed2fme1.json
llc1v2llc1.json
nts2023nts.json
ntsl2023ntsl.json
nts2025nts2.json
ntsl2025ntsl2.json
con29R2019con29R.json
con29DWcon29DW.json
rdsV333rds.json
oc1v21oc1.json
piqV3piq.json
sr24sr24.json

Bounded-context map

Each overlay belongs to exactly one bounded context:

Bounded contextMain overlays
Estate Agency baspi4 (legacy) · baspi5 · nts (legacy) · nts2 · ntsl (legacy) · ntsl2
Conveyancing ta6 · ta7 · ta10 · lpe1
Mortgage Lending fme1
Surveying piq
Property Data Services rds · oc1 · llc1 · con29R · con29DW · sr24
Property Tech The base pdtf-transaction.json + verified-claims wrapper (no overlays of its own)

The extension overlays (jk, tf, …) are all sub-pieces of NTS2, so they belong to Estate Agency.

Where this lives