● Live transaction-status PrDP + PIC
01

Overview & URLs

ViewMyChain chain-state endpoint — sandbox environment only

VMC provides real-time property chain state data — transaction milestones, chain structure, and participant data — for properties in England and Wales. Each response includes an embedded JWS provenance block (see Section 06) for verification.

PurposeURL
VMC Chain State API https://admin.demo3.viewmychain.com/api/v1/opda/chains
OPDA Participant Directory https://data.directory.pdtf.raidiam.io/participants
Raidiam Directory (web) — create app + certs https://web.sandbox.directory.openpropdata.org.uk
Raidiam token endpoint https://matls-auth.directory.pdtf.raidiam.io/token
VMC JWKS — organisation-level signing key https://keystore.directory.pdtf.raidiam.io/a61256b7-cd47-4103-937c-e9b90bbc0457/application.jwks

Directory Registration

Organisation ID
a61256b7-cd47-4103-937c-e9b90bbc0457
API Family
transaction-status
Signing Key (kid)
D0L7Od06mNdegj8zGHZEV16QKyIJEotU9nvd8qMrP5I
Auth Server ID
eb83e7e7-ab2b-4860-bd80-3f90e41c41ff
02

Authentication

mTLS at transport layer + Bearer token for authorisation
⚠️
Scope not yet live: The transaction-status scope is being configured by Raidiam. Contact Alan Hughes (alan.hughes@raidiam.com) before attempting to connect — he will confirm when it is ready and assign it to your organisation.

If you are not yet onboarded to the OPDA sandbox, follow the official Introduction to the Sandbox Technical Guide (OPDA) — the onboarding flow is identical for all participants.

OAuth Configuration

config
CLIENT_ID = "https://rp.directory.pdtf.raidiam.io/openid_relying_party/<your-app-uuid>"
SCOPES    = "transaction-status"
TOKEN_URL = "https://matls-auth.directory.pdtf.raidiam.io/token"

Token Request

Bash
curl -X POST https://matls-auth.directory.pdtf.raidiam.io/token \
  --cert transport.pem --key transport.key \
  -d "grant_type=client_credentials" \
  -d "scope=transaction-status" \
  -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
  -d "client_assertion=<your_signed_jwt>"
ℹ️
The token is valid for 600 seconds. Cache introspection results — do not call introspection on every request.
03

API Reference

Base URL: https://admin.demo3.viewmychain.com
POST /api/v1/opda/chains Live

Returns chain state for a given address or UPRN. Includes all linked properties, milestones, participants, and JWS provenance.

Request Body — form-data

FieldTypeRequiredDescription
inputType string required address or uprn
value[] string required One or more address strings or UPRN values. Repeat value[] for bulk queries.

Single address — fuzzy search supported

Bash
curl -X POST https://admin.demo3.viewmychain.com/api/v1/opda/chains \
  --cert transport.pem --key transport.key \
  -H "Authorization: Bearer $TOKEN" \
  -F "inputType=address" \
  -F "value[]=1 COBBLESTONE CORNER, LIVERPOOL, L19 9ES"

Single UPRN

Bash
curl -X POST https://admin.demo3.viewmychain.com/api/v1/opda/chains \
  --cert transport.pem --key transport.key \
  -H "Authorization: Bearer $TOKEN" \
  -F "inputType=uprn" \
  -F "value[]=38192980"

Multiple UPRNs — bulk query

Bash
curl -X POST https://admin.demo3.viewmychain.com/api/v1/opda/chains \
  --cert transport.pem --key transport.key \
  -H "Authorization: Bearer $TOKEN" \
  -F "inputType=uprn" \
  -F "value[]=38192980" \
  -F "value[]=30016442" \
  -F "value[]=25101892"

Multiple addresses — bulk query

Bash
curl -X POST https://admin.demo3.viewmychain.com/api/v1/opda/chains \
  --cert transport.pem --key transport.key \
  -H "Authorization: Bearer $TOKEN" \
  -F "inputType=address" \
  -F "value[]=1 COBBLESTONE CORNER, LIVERPOOL" \
  -F "value[]=11 ADBER CLOSE, YEOVIL"
ℹ️
Fuzzy search: Address input supports partial matches. Partial street name or postcode is sufficient. Each item in data[] corresponds to one queried value.

Sample Test Data

Use these values to test against VMC's sandbox data. Click any value to copy.

By UPRN

38192980
30016442
25101892
100021200034

By Address

AddressUPRNChain
1 COBBLESTONE CORNER, LIVERPOOL, L19 9ES 38192980 SPLIT chain· 4 properties
11 ADBER CLOSE, YEOVIL, BA21 5XJ 30016442 Part of above chain
54 MOORGATE, LEADENHALL, MILTON KEYNES, MK6 5NA 25101892 Part of above chain
73 MANOR ROAD, TOTTENHAM, LONDON, N17 0JH 100021200034 Part of above chain

Click any address to copy. Fuzzy search works — try "COBBLESTONE LIVERPOOL" or just the postcode.

Errors

HTTPCauseResolution
401Missing or expired Bearer tokenRequest a new token from the Raidiam token endpoint
401Certificate binding mismatch (RFC 8705)Use the same transport certificate that was used when the token was issued
403Missing transaction-status scopeContact Alan Hughes at Raidiam to have the scope assigned
404Address or UPRN not found in VMC's networkTry a different UPRN from the sample list in Section 03
422Invalid inputType or missing value[]inputType must be address or uprn
04

Response Format

Full chain returned — all linked properties, milestones, participants, connections
ℹ️
Provenance block included. The response has two top-level keys: data (an object wrapping the data[] array and pagination) and provenance (the signature block — see Section 06). The signature covers the entire top-level data object. Only milestones with a recorded date are returned.
Full Response — UPRN 38192980 — 4 properties (SPLIT chain)
{
  "data": {
    "data": [
      {
        "queriedAddress": "1 COBBLESTONE CORNER, LIVERPOOL, L19 9ES",
        "chainId": "F9000B97-CEE0-49BC-B482-952EC0C6B7A3",
        "chainSummary": {
          "chainType": "SPLIT_CHAIN",
          "chainLength": 4
        },
        "properties": [

          // Property 1 - queried property (SPLIT node - 2 downward)
          {
            "id": 27516223,
            "uprn": 38192980,
            "address": {
              "line1": "1 COBBLESTONE CORNER", "line2": "",
              "line3": "", "line4": "",
              "postTown": "LIVERPOOL", "postcode": "L19 9ES",
              "displayAddress": "1 COBBLESTONE CORNER, LIVERPOOL, L19 9ES"
            },
            "tenure": "commonhold",
            "transactionType": ["probate", "freehold_enfranchisement"],
            "milestones": [
              { "label": "SSTC",             "date": "2025-12-06" },
              { "label": "Searches Ordered", "date": "2026-05-03" },
              { "label": "Cash Buyer",        "date": "2026-05-04" },
              { "label": "Search Delivered",  "date": "2026-05-01" }
            ],
            "participants": {
              "sellingAgent":      "Branch Test",
              "sellerConveyancer": "Alun Thomas & John",
              "buyerConveyancer":  "Harrison & Co"
            },
            "isTopClosed": false, "isBottomClosed": false,
            "connections": {
              "upwardChain":   [27516226],
              "downwardChain": [27516224, 27516225]
            }
          },

          // Property 2 - downward branch A (reached Exchange)
          {
            "id": 27516224,
            "uprn": 30016442,
            "address": {
              "line1": "11 ADBER CLOSE",
              "postTown": "YEOVIL", "postcode": "BA21 5XJ",
              "displayAddress": "11 ADBER CLOSE, YEOVIL, BA21 5XJ"
            },
            "tenure": "", "transactionType": [],
            "milestones": [
              { "label": "SSTC",             "date": "2026-04-15" },
              { "label": "Searches Ordered", "date": "2026-04-28" },
              { "label": "Search Delivered",  "date": "2026-04-28" },
              { "label": "Mortgage Applied",  "date": "2026-05-02" },
              { "label": "Exchange",          "date": "2026-05-04" }
            ],
            "participants": {
              "sellingAgent":      "Connells - Kenilworth",
              "sellerConveyancer": "Roger Male & Co",
              "buyerConveyancer":  "Ison Harrison & Co"
            },
            "isTopClosed": false, "isBottomClosed": false,
            "connections": {
              "upwardChain": [27516223], "downwardChain": []
            }
          },

          // Property 3 - downward branch B (isTopClosed: true = confirmed no further up)
          {
            "id": 27516225,
            "uprn": 25101892,
            "address": {
              "line1": "54 MOORGATE", "line4": "LEADENHALL",
              "postTown": "MILTON KEYNES", "postcode": "MK6 5NA",
              "displayAddress": "54 MOORGATE, LEADENHALL, MILTON KEYNES, MK6 5NA"
            },
            "tenure": "", "transactionType": [],
            "milestones": [
              { "label": "SSTC", "date": "2026-04-29" }
            ],
            "participants": {
              "sellingAgent":      "Connells - Plymstock",
              "sellerConveyancer": "Wholley Goodings",
              "buyerConveyancer":  "Alun Thomas & John"
            },
            "isTopClosed": true, "isBottomClosed": false,
            "connections": {
              "upwardChain": [27516223], "downwardChain": []
            }
          },

          // Property 4 - upward (isBottomClosed: true = confirmed no further down)
          {
            "id": 27516226,
            "uprn": 100021200034,
            "address": {
              "line1": "73 MANOR ROAD", "line4": "TOTTENHAM",
              "postTown": "LONDON", "postcode": "N17 0JH",
              "displayAddress": "73 MANOR ROAD, TOTTENHAM, LONDON, N17 0JH"
            },
            "tenure": "", "transactionType": [],
            "milestones": [
              { "label": "SSTC", "date": "2026-04-28" }
            ],
            "participants": {
              "sellingAgent":      "Peter Facenna",
              "sellerConveyancer": "Harrison & Co",
              "buyerConveyancer":  "Blazer, Mills, Winter, Taylor"
            },
            "isTopClosed": false, "isBottomClosed": true,
            "connections": {
              "upwardChain": [], "downwardChain": [27516223]
            }
          }

        ]
      }
    ],
    "pagination": {
      "total": 1, "perPage": 15,
      "currentPage": 1, "lastPage": 1
    }
  },
  "provenance": {
    "alg": "RS256",
    "kid": "D0L7Od06mNdegj8zGHZEV16QKyIJEotU9nvd8qMrP5I",
    "signature": "BPGWzgURVfNpvCSh0pxqwk_Ay3lpg...<base64url RS256 over JCS(data)>",
    "signedAt": "2026-06-02T03:18:26Z",
    "payloadHash": {
      "alg": "SHA-256",
      "value": "CTPeW4KCpZEw6SbWi1Y0qFGpbsIzu32HL8gKkaIHf0o"
    }
  }
}

Key Fields

FieldTypeDescription
chainIdstringUUID identifying the chain group. Stable across requests.
chainTypestringIN_CHAIN — straight sequential chain, one buyer and one seller at each link (A→B→C→D). SPLIT_CHAIN — chain branches at one node; one buyer is simultaneously selling two or more properties (forms a Y shape, higher risk of delays). NOT_IN_CHAIN — standalone single property, not part of any chain.
chainLengthintegerTotal number of properties in this chain.
milestones[].labelstringCanonical milestone identifier. See Section 05. Only milestones with a recorded date are included.
milestones[].datestringDate when milestone was recorded. Format: YYYY-MM-DD.
isTopClosedbooleantrue = VMC has confirmed no further properties exist above this one in the chain.
isBottomClosedbooleantrue = VMC has confirmed no further properties exist below this one in the chain.
connections.upwardChaininteger[]VMC internal IDs of properties above this one. Cross-reference with properties[].id.
connections.downwardChaininteger[]VMC internal IDs of properties below this one. Multiple entries = SPLIT chain.
uprnintegerUnique Property Reference Number for this property. Returned as an integer. Some pre-registration / new-build records may carry a placeholder value.
transactionTypestring[]auction, buy_to_let, freehold_enfranchisement, power_of_attorney, probate, repossession, shared_ownership. Empty array for a standard purchase.
tenurestringfreehold, leasehold, commonhold, shareoffreehold. Empty string if unknown.

Chain Structure — This Example

ℹ️
This response is a SPLIT chain of 4 properties. Property 27516223 (1 Cobblestone Corner) has two downward connections — meaning the seller is buying two properties simultaneously. To traverse the chain: match connections.upwardChain and connections.downwardChain IDs against properties[].id within the same response.
05

Milestone Codes

The label field is the canonical identifier. Only milestones with a recorded date are returned.
ℹ️
The label values below are the canonical identifiers returned in milestones[].label. Two of them — Completion Date Set and Completion — also map to Pexa/Smoove's completion hub events (completion_set / completion_actioned); that push flow is covered in VMC's separate webhook documentation, not this provider API.
# VMC Milestone (label) Description
01SSTCSold Subject to Contract
02Searches OrderedConveyancer has ordered searches
03Search DeliveredSearch results received
04Cash BuyerCash purchase confirmed
05Mortgage AppliedMortgage application submitted
06Mortgage OfferedMortgage offer received
07ExchangeContracts exchanged — legally binding
08Completion Date SetCompletion date confirmed
09CompletionTransaction completed
10Fall ThroughTransaction collapsed
06

Provenance Verification

Every VMC response includes an embedded JWS provenance block
Verified by Raidiam: VMC's JWS implementation was independently verified by Alan Hughes at Raidiam (May 2026). Algorithm: RS256. Canonicalisation: JCS (RFC 8785). Certificate: organisation-level signing cert.
1
Fetch VMC's JWKS
Bash
curl "https://keystore.directory.pdtf.raidiam.io/a61256b7-cd47-4103-937c-e9b90bbc0457/application.jwks"
Select the key where kid matches provenance.kid.
2
Canonicalise response.data using JCS (RFC 8785)
Here response.data is the entire top-level data object — i.e. { data: [...], pagination: {...} }, the sibling of provenance. Sort all keys by Unicode code point at every nesting level. The resulting bytes are the canonical representation.
3
Verify the payload hash
Compute SHA-256 over the JCS bytes. Compare (base64url) against provenance.payloadHash.value. Must match.
4
Verify the RS256 signature
Verify provenance.signature over the raw JCS bytes using VMC's public key. RS256 hashes internally — pass raw bytes directly, do not pre-hash.
07

Webhooks

Real-time event notifications · Sandbox
Live: VMC's outbound webhook is live and verified end-to-end. Events are delivered as signed JWTs to your registered callback URL. Authentication uses X-Api-Key header — separate from the mTLS chain API auth.

When a milestone event occurs on a VMC-tracked property, VMC POSTs a signed JWT to every registered callback URL subscribed to that event type. The JWT is signed with VMC's RS256 signing key — verifiable against the same JWKS as the chain API.

Event Types

EventDescription
milestone.updatedA milestone has been recorded on a property (any label from Section 05 except Fall Through — which is delivered as the separate fallthrough event)
fallthroughA property transaction has fallen through

Subscribe

POST /api/v1/webhook/subscribe Live

Register your callback URL to receive webhook events. Authenticate with your X-Api-Key header.

Bash
curl -X POST https://admin.demo3.viewmychain.com/api/v1/webhook/subscribe \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "participantName": "Your Organisation Name",
    "callbackUrl": "https://your-endpoint.example.com/webhook",
    "events": ["milestone.updated", "fallthrough"]
  }'

Request Body

FieldTypeRequiredDescription
participantNamestringrequiredYour organisation name — used for identification in VMC's subscriber registry
callbackUrlstringrequiredHTTPS endpoint where VMC will POST webhook events
eventsstring[]requiredEvent types to subscribe to: milestone.updated, fallthrough

Simulate

POST /api/v1/webhook/simulate Live

Trigger a test webhook event to verify your subscription and callback endpoint are working.

Simulate — milestone.updated

Bash
curl -X POST https://admin.demo3.viewmychain.com/api/v1/webhook/simulate \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "eventType": "milestone.updated",
    "propertyId": "p1",
    "uprn": "12345678987",
    "date": "2026-06-04",
    "label": "Searches Ordered"
  }'

Simulate — fallthrough

Bash
curl -X POST https://admin.demo3.viewmychain.com/api/v1/webhook/simulate \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "eventType": "fallthrough",
    "propertyId": "p1",
    "uprn": "12345678987",
    "date": "2026-06-04"
  }'

Delivery Format

VMC delivers events as signed JWTs via HTTP POST. Content-Type is application/jwt. JWTs expire 300 seconds after issuance.

JWT Header

JSON
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "D0L7Od06mNdegj8zGHZEV16QKyIJEotU9nvd8qMrP5I"
}

Decoded JWT — milestone.updated

JSON — verified 5 June 2026
{
  "iss":            "https://admin.demo3.viewmychain.com",
  "iat":            1780647593,
  "exp":            1780647893,
  "eventId":        "evt_01KTBDW1TGRBS6YVM057JZ0R2A",
  "eventType":      "milestone.updated",
  "eventTimestamp": "2026-06-05T08:19:53Z",
  "propertyId":    "p1",
  "uprn":          "12345678987",
  "data": {
    "milestone": {
      "label": "Searches Ordered",
      "date":  "2026-06-04"
    }
  }
}

Decoded JWT — fallthrough

JSON
{
  "iss":            "https://admin.demo3.viewmychain.com",
  "iat":            1780647593,
  "exp":            1780647893,
  "eventId":        "evt_01KTBDW1TGRBS6YVM057JZ0R2A",
  "eventType":      "fallthrough",
  "eventTimestamp": "2026-06-05T08:19:53Z",
  "propertyId":    "p1",
  "uprn":          "12345678987",
  "data": {
    "fallThroughDate": "2026-06-04"
  }
}

Common JWT Fields

FieldTypeDescription
issstringIssuer — always https://admin.demo3.viewmychain.com
iatintegerIssued at — Unix timestamp
expintegerExpiry — Unix timestamp (300 seconds after iat)
eventIdstringUnique event identifier. Use for deduplication.
eventTypestringmilestone.updated or fallthrough
eventTimestampstringISO 8601 UTC timestamp of when the event occurred
propertyIdstringVMC internal property identifier
uprnstringUnique Property Reference Number
dataobjectEvent-specific payload — see event types above
🔑
Sandbox API Key: Your sandbox API key is issued individually and sent to you by email — use it in the X-Api-Key header for all webhook requests.

For sandbox or production access, contact Huy Nguyen (huy.nguyen@viewmychain.com).

Verifying JWT Signatures

The JWKS for verifying webhook signatures is the same as the chain API (see Section 06). Use the kid in the JWT header to select the correct key.

Bash — fetch JWKS
curl "https://keystore.directory.pdtf.raidiam.io/a61256b7-cd47-4103-937c-e9b90bbc0457/application.jwks"
Node.js — jose
import * as jose from 'jose';

const JWKS_URL = 'https://keystore.directory.pdtf.raidiam.io/a61256b7-cd47-4103-937c-e9b90bbc0457/application.jwks';
const jwks = jose.createRemoteJWKSet(new URL(JWKS_URL));

// jwtString is the raw POST body received at your callback URL
const { payload } = await jose.jwtVerify(jwtString, jwks);

console.log(payload.eventType); // "milestone.updated" | "fallthrough"
console.log(payload.uprn);      // property UPRN
console.log(payload.data);      // event-specific data
C# — Microsoft.IdentityModel.Tokens
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;

var jwksUrl = "https://keystore.directory.pdtf.raidiam.io/a61256b7-cd47-4103-937c-e9b90bbc0457/application.jwks";
var jwksJson = await new HttpClient().GetStringAsync(jwksUrl);
var jwks = new JsonWebKeySet(jwksJson);

var handler = new JwtSecurityTokenHandler();
var validationParams = new TokenValidationParameters {
    ValidateIssuer   = false,
    ValidateAudience = false,
    IssuerSigningKeys = jwks.GetSigningKeys()
};

var principal = handler.ValidateToken(jwtString, validationParams, out _);
// Access claims via principal.Claims
ℹ️
Tips:
  • Use eventId to deduplicate events — future versions may retry delivery on failure.
  • The kid in the JWT header identifies which key in the JWKS to use for verification.
  • JWTs expire 300 seconds after issuance — verify promptly.
  • Your callbackUrl must use HTTPS.
08

Support

Contacts for technical, commercial and sandbox support

ViewMyChain

OPDA Sandbox Programme