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

Status Codes

PDTF 2.0 uses W3C Bitstring Status List v1.0 for credential revocation and suspension. Every credential issued within the ecosystem MUST include a credentialStatus field. Credentials without one MUST be rejected.

This reference covers:

  • Bitstring Status List structure and index allocation
  • Status purposes (revocation and suspension)
  • The verification algorithm
  • URL patterns for status list endpoints
  • Status state matrix
  • Caching requirements

Every PDTF credential MUST include:

{
"credentialStatus": {
"id": "https://adapters.propdata.org.uk/status/epc/list-042#18293",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "18293",
"statusListCredential": "https://adapters.propdata.org.uk/status/epc/list-042"
}
}
FieldTypeRequiredDescription
idURIrequiredunique identifier for this status entry; {statusListCredential}#{statusListIndex}
typestringrequiredMUST be BitstringStatusListEntry
statusPurposeenumrequiredrevocation or suspension
statusListIndexstringrequirednon-negative integer as string, bit position in the list
statusListCredentialURIrequiredHTTPS URL of the status list VC

A credential MAY include two credentialStatus entries — one for revocation, one for suspension — each referencing separate status lists.

The status list is itself a Verifiable Credential.

{
"@context": ["https://www.w3.org/ns/credentials/v2"],
"id": "https://adapters.propdata.org.uk/status/epc/list-042",
"type": ["VerifiableCredential", "BitstringStatusListCredential"],
"issuer": "did:web:adapters.propdata.org.uk:epc",
"validFrom": "2026-01-01T00:00:00Z",
"credentialSubject": {
"id": "https://adapters.propdata.org.uk/status/epc/list-042#list",
"type": "BitstringStatusList",
"statusPurpose": "revocation",
"encodedList": "H4sIAAAAAAAAA..."
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"verificationMethod": "did:web:adapters.propdata.org.uk:epc#key-1",
"proofPurpose": "assertionMethod",
"created": "2026-03-24T12:00:00Z",
"proofValue": "z..."
}
}
FieldRequirement
idMUST match the URL at which the status list is hosted
typeMUST include BitstringStatusListCredential
issuerMUST match the issuer of the credentials this list covers
credentialSubject.typeMUST be BitstringStatusList
credentialSubject.statusPurposeMUST match statusPurpose in referencing credentials
credentialSubject.encodedListgzip-compressed, base64-encoded bitstring
minimum list size131,072 bits (16 KB uncompressed)
1. Start with a bitstring of at least 131,072 bits, all zeros
2. Set bit at each revoked credential's statusListIndex to 1
3. Compress using gzip
4. Base64-encode the compressed bytes (no padding)
→ encodedList value

Decoding:

1. Base64-decode encodedList
2. Gzip-decompress
3. Read bit at statusListIndex
RuleDetail
Sequential allocationindices are assigned in order from 0 up
Unique per listeach credential gets exactly one index
Never reusedonce assigned, an index is never reassigned, even after revocation
Capacitystandard list holds 131,072 indices
Overflowwhen full, create a new list and reset counter to 0
statusPurposeMeaningReversible
revocationpermanent invalidationno — bit is never unset
suspensiontemporary holdyes — bit may be unset to reinstate
Revocation bitSuspension bitStateVerifier action
00Activeaccept
01Suspendedreject, temporary
10Revokedreject, permanent
11Revokedreject, permanent — revocation takes precedence
For each credentialStatus entry in the credential:
1. Resolve issuer DID → get signing key
2. Fetch statusListCredential from the URL
- use cached copy if within TTL
3. Verify status list credential proof
- status list issuer MUST match the credential issuer
4. Base64-decode and gzip-decompress encodedList
5. Read bit at statusListIndex
- byteIndex = floor(index / 8)
- bitIndex = index % 8
- bit = (bitstring[byteIndex] >> (7 - bitIndex)) & 1
6. If bit == 1:
- statusPurpose == "revocation" → credential is REVOKED
- statusPurpose == "suspension" → credential is SUSPENDED
If any entry is revoked → reject
If any entry is suspended → reject (or warn, per policy)
If all entries are 0 → credential status is active

The status list credential’s issuer MUST match the original credential’s issuer. A mismatch is a hard failure.

Credential issuer: did:web:adapters.propdata.org.uk:epc
Status list issuer: did:web:adapters.propdata.org.uk:epc ✅ OK
Credential issuer: did:web:adapters.propdata.org.uk:epc
Status list issuer: did:web:evil.example.com ❌ REJECT
https://adapters.propdata.org.uk/status/{adapter}/{listId}

Examples:

https://adapters.propdata.org.uk/status/epc/list-001
https://adapters.propdata.org.uk/status/hmlr/list-001
https://adapters.propdata.org.uk/status/ea-flood/list-001
https://platform.example.com/status/{category}/{listId}

Examples:

https://platform.example.com/status/ownership/list-001
https://platform.example.com/status/representation/list-001
https://platform.example.com/status/consent/list-001
HTTP/1.1 200 OK
Content-Type: application/vc+ld+json
Cache-Control: public, max-age=300
ETag: "a1b2c3d4"
Access-Control-Allow-Origin: *
  • MUST respond over HTTPS
  • MUST include CORS headers
  • SHOULD include Cache-Control: public, max-age=300
  • SHOULD include ETag for conditional request support
Credential typeRevocation trigger
SellerCapacityCredentialtitle transfers on sale completion
RepresentationCredentialmandate withdrawn, conveyancer replaced, transaction completed or cancelled
PropertyCredentialunderlying data superseded by new issue (e.g. new EPC)
TransactionRoleCredentialparty no longer holds the role, transaction completed
GiftCredentialgift withdrawn or terms changed
OfferCredentialoffer withdrawn or rejected
user identity credentialaccount disabled, suspended, or deleted

Suspension is appropriate for:

  • pending fraud investigation
  • temporary access hold during case review
  • disputed ownership not yet resolved
  • account under review but not confirmed disabled

Suspension is not appropriate for permanent invalidation — use revocation.

ScenarioRecommended TTL
Normal status list fetchCache-Control from server (typically 5 min)
High-sensitivity credentials (ownership, representation)shorter TTL recommended, e.g. 60s
On verification failurebypass cache, re-fetch once
Origin unreachableserve stale for up to 60s, then fail

Verifiers SHOULD store the ETag alongside each cached status list and use If-None-Match on subsequent requests.

When multiple credentials must be revoked simultaneously (e.g. on transaction completion):

  1. Group credentials by status list.
  2. For each affected list: set all target bits, re-encode, re-sign, publish.
  3. Record all revocations atomically.

Batch revocation within a single list is atomic. Revocations spanning multiple lists are eventually consistent.

{
"credentialStatus": [
{
"id": "https://adapters.propdata.org.uk/status/epc/rev/list-042#18293",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "18293",
"statusListCredential": "https://adapters.propdata.org.uk/status/epc/rev/list-042"
},
{
"id": "https://adapters.propdata.org.uk/status/epc/sus/list-042#18293",
"type": "BitstringStatusListEntry",
"statusPurpose": "suspension",
"statusListIndex": "18293",
"statusListCredential": "https://adapters.propdata.org.uk/status/epc/sus/list-042"
}
]
}

Revocation and suspension lists are separate. Same index may be used in both.

When a list reaches capacity (131,072 indices allocated):

  • create a new list with the next sequential list ID
  • old list remains hosted and accepts revocation updates indefinitely
  • new credentials are allocated from the new list
  • status URLs are stable for the life of any credential that references them

List IDs are sequential and scoped per issuer and purpose:

list-001 (full)
list-002 (full)
list-003 (active)
  • Index allocation MUST be atomic. Use a database-level transaction or atomic increment.
  • Revocation bit flips MUST be atomic within a single list.
  • The status list credential id MUST exactly match its hosting URL.
  • Status lists MUST be accessible to any verifier over the public internet.
  • Status lists should be served from CDN-backed infrastructure for availability and low latency.