Status List revocation explained
A verifier that has just received a credential needs to know whether the issuer still stands behind it. Token Status List answers that without the verifier contacting the issuer about that specific credential: a status claim inside the credential points at a compact list, and a single bit in that list carries the answer.
The status claim inside the credential
An issuer that supports Token Status List adds a status claim to the credential at issuance time. It carries two things: idx, the index this credential owns inside the list, and uri, the address of the Status List Token that holds it. Nothing else about the credential changes; the claim is just a pointer.
Issuer
Assigns the credential an index and embeds a status claim
The claim is added once, at issuance, and never changes for the lifetime of the credential
Status claim (inside the credential)
{
"status": {
"status_list": {
"idx": 4271,
"uri": "https://issuer.example/statuslists/employment-2026-q3"
}
}
}Fetching the Status List Token
At presentation time the verifier fetches the uri from the status claim. The response is a signed Status List Token: a JWT with a typ header of statuslist+jwt (or a CWT equivalent), served as application/statuslist+jwt. Its payload carries the compressed bitstring and, usually, a ttl that tells the verifier how long it may cache the result before fetching again.
Verifier
Reads idx and uri from the status claim in the credential just presented
GET uri
Fetches the Status List Token, caching it for up to ttl seconds
Status List Token payload (response)
{
"sub": "https://issuer.example/statuslists/employment-2026-q3",
"iat": 1789200000,
"exp": 1789804800,
"ttl": 43200,
"status_list": {
"bits": 2,
"lst": "eNrbuRgAAhcBXQ"
}
}sub repeats the list’s own URI so a verifier can confirm it fetched the right token. iat and exp bound the token’s own validity. ttl, in seconds, is the maximum time the verifier may reuse a cached copy before it has to fetch the list again.
Decoding the bit
lst is a byte array, base64url-encoded and compressed with DEFLATE in the zlib data format, that the verifier decompresses first. bits says how many bits each credential in the list occupies: 1, 2, 4 or 8. With bits: 2, credential number idx lives at byte idx * 2 / 8, and the verifier reads the two bits at that offset to get the status value.
Worked example: idx 4271, bits: 2
- bit_offset = idx * bits = 4271 * 2 = 8542
- byte_index = bit_offset / 8 = 1067
- bit_in_byte = bit_offset % 8 = 6
The verifier reads byte 1067 of the decompressed array, extracts the two bits starting at bit 6, and compares the result against the value table below.
| Value | Meaning |
|---|---|
| 0x00 | VALID |
| 0x01 | INVALID |
| 0x02 | SUSPENDED |
| 0x03, 0x0C-0x0F | Application-specific / reserved |
Values shown assume bits: 2. With bits: 1 only VALID (0) and INVALID (1) fit; bits: 4 and bits: 8 leave more of the range free for application-specific values.
Why the list stays small
Real-world status lists are mostly zeros, because most credentials an issuer has ever handed out are still valid, and a run of identical bits compresses well. DEFLATE compression over the raw bitstring is what keeps a list covering hundreds of thousands of credentials down to a few kilobytes on the wire, which is what makes fetching the whole list, instead of asking the issuer about one credential, practical.
Aggregation: discovering lists ahead of time
An issuer can optionally add aggregation_uri to a Status List object, pointing at an endpoint that lists the URIs of every Status List Token it publishes. A verifier that wants to pre-fetch and cache lists before it needs them, rather than discovering each one from the first credential that references it, can use that endpoint instead. This is optional; nothing in the core flow above depends on it.
Related terms
Frequently asked questions
Does the verifier fetch a separate list for every credential it checks?
No, one Status List Token covers every credential the issuer put in it, potentially hundreds of thousands. A verifier fetches the same token once and reads a different bit for each credential it checks, then reuses the cached copy for up to ttl seconds before fetching again.
Can the issuer tell which credential a verifier looked up?
No. The verifier downloads the whole compressed bitstring in one request and reads the bit it needs locally, so the request the issuer sees carries no index and no credential identifier, only a GET for the list itself.
What is the difference between suspended and invalid?
INVALID (0x01) is how the specification’s reference registry labels a permanently revoked credential. SUSPENDED (0x02) is a separate, reversible state an issuer can also set and later clear, for example while a dispute is investigated. Telling them apart needs at least two bits per entry (bits: 2), so a Status List Token using bits: 1 can only distinguish valid from invalid.
What is the aggregation_uri for?
It is an optional pointer inside a Status List object to an aggregation endpoint listing the URIs of every Status List Token from that issuer. A verifier that wants to warm its cache ahead of time, or discover lists it has not seen yet, can fetch that endpoint instead of waiting for a credential to name one.
Sources
This page is informational and does not constitute legal advice. For authoritative guidance consult the IETF specification directly.