Token Status List
In this walkthrough we take a look at how you can create a Token Status List configuration and assign or update status list indexes (statuses for individual SD-JWT VC credentials). Please make sure you have created a credential status service as explained here.
Our implementation follows the Token Status List Standard
The Token Status List is used to enable a status for IETF SD-JWT credentials. If you want to have a status for W3C credentials, please go here.
Create A Token Status List Configuration
Important: Creating the configuration alone does not issue any status list token yet. The signed JWT (Status List Token) becomes available only after you complete the configuration and assigned at least one index in the status list.
When defining the configuration, we decide which key will sign the status list token JWT, the DID of the issuer, and the
config of the token status list itself. The config includes the statusSize
and more.
In the example below we will create a configuration for a classical token status list.
Endpoint: /v1/{target}/credential-status-service-api/status-credential/create
| API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/credential-status-service-api/status-credential/create' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"kid": "waltid.tenant1.kms1.key1",
"did": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5Iiwia2lkIjoiMW1rQnBEYWZqVk9ONm9XVmlIZGREZXNEYXpKaXk1R0NTYko3VDU4QkJ3cyIsIngiOiJzZ1BiZWRPQjl1WEMtVG54LUVhV1IxRmg1Y25JLUxRLU43NUV1UE8wV2VFIn0",
"config": {
"type": "TokenStatusList",
"statusSize": 1,
"statuses": [
{
"status": "0x0",
"message": "VALID"
},
{
"status": "0x1",
"message": "INVALID"
}
],
"format": "JWT"
}
}'
Path Parameters
orgID
: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedtest
, your default Base URL will betest.enterprise-sandbox.walt.dev
when using the sandbox environment.target
: resourceIdentifier - The target indicates the organization + tenant + credential status service in which to execute the status list token creation ({organizationID}.{tenantID}.{credentialStatusServiceID}
), e.g.waltid.tenant1.status-service1
Body
{
"kid": "waltid.tenant1.kms1.key1",
"did": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5Iiwia2lkIjoiMW1rQnBEYWZqVk9ONm9XVmlIZGREZXNEYXpKaXk1R0NTYko3VDU4QkJ3cyIsIngiOiJzZ1BiZWRPQjl1WEMtVG54LUVhV1IxRmg1Y25JLUxRLU43NUV1UE8wV2VFIn0",
"config": {
"type": "TokenStatusList",
"statusSize": 1,
"statuses": [
{
"status": "0x0",
"message": "VALID"
},
{
"status": "0x1",
"message": "INVALID"
}
],
"format": "JWT"
}
}
Body Parameters
kid
: resourceIdentifier - Specifies a key used for singing the status credential. The key must come from a KMS service that lives under the same tenant as the credential status service.did
: String - Specifies that DID related to thekid
.config
: Object - Configuration details for the Status List Token:type
: String - Describes the status list standard. It should beTokenStatusList
.statusSize
: String -Describes the size of each status entry in bits. Allowed values are 1, 2, 4, and 8. Default is 1, meaning each status is represented by a single bit. Larger values allow for more complex status messages, with the number of possible status messages equaling2^statusSiz
.statuses
: Array - This parameter is a JSON array that defines the possible statuses for the Referenced Tokens. Each entry in the array has:status
: String This indicates the bit representation of the status. It uses a hexadecimal representation (e.g., "0x0", "0x1")message
: String This provides a human-readable label for the status (e.g., "VALID", "INVALID")
format
: String This parameter indicates the format of the Status List Token. It must beJWT
.
Response
201
- Credential Status config created successfully.
Assigning a Status Index for a Credential in the Status List
Using our status list token configuration, we can now assign a specific index in the status list for a credential we want to issue. The response will return a JSON structure we can use in the SD-JWT VC issuance request.
Endpoint: /v1/{target}/credential-status-service-api/status-credential/status/create
| API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/credential-status-service-api/status-credential/status/create' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"initialStatus": "0x0"
}'
Path Parameters
orgID
: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedtest
, your default Base URL will betest.enterprise-sandbox.walt.dev
when using the sandbox environment.target
: resourceIdentifier - The target indicates the organization + tenant + credential status service + credential status config ID in which to create a new status list entry.{organizationID}.{tenantID}.{credentialStatusServiceID}.{statusCredentialConfigID}
), e.g.waltid.tenant1.status-service1.revocation-config
Body
{
"initialStatus": "0x0"
}
Body Parameters
initialStatus
: The string representing the hexadecimal value of the status, prefixed with 0x, e.g.0x0
Response
201
- Status index created successfully.
{
"status_list": {
"idx": 23481,
"uri": "https://enterprisetest.blob.core.windows.net/83abcuyiuweiuoyiy8943ir732yjhghj23gdnshuy7623rjh23jhrg23g78hkkk/waltid.tenant1.credential-status-1.f4ce5c992c12216bbe47540c22ee99d7"
}
}
The returned status_list
object that can be added to the status
property of the holder credential (IETF SD-JWT VC).
Example of a holder credential with Status
{
"given_name": "John",
"family_name": "Doe",
"email": "johndoe@example.com",
"phone_number": "+1-202-555-0101",
"address": {
"street_address": "123 Main St",
"locality": "Anytown",
"region": "Anystate",
"country": "US"
},
"is_over_18": true,
"is_over_21": true,
"is_over_65": true,
"id": "urn:uuid:9cd6c1eb-4bb4-4128-82e0-520c527d23ff",
"iat": 1741013911,
"nbf": 1741013911,
"exp": 1772549911,
"iss": "http://waltid.enterprise.localhost:3000/v1/waltid.tenant1.issuer-service-2/issuer-service-api/openid4vc/draft13",
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"kid": "zxIo0ognSmR6GCy9rJblqE7UbvcQnt2vMPMzsuXXBcs",
"x": "KzUaZhZaRqp2C_fEieU1VTUPF1XqJxqTIxSQgxRKJcs"
}
},
"vct": "http://waltid.enterprise.localhost:3000/v1/waltid.tenant1.issuer-service-2/issuer-service-api/openid4vc/draft13/identity_credential",
"_sd": [
"WwLfN74YKWfsPK8jEqDIFESZ-dwhmXWyQeaRfFddZZM"
],
"status": {
"status_list": {
"idx": 23481,
"uri": "https://enterprisetest.blob.core.windows.net/83abcuyiuweiuoyiy8943ir732yjhghj23gdnshuy7623rjh23jhrg23g78hkkk/waltid.tenant1.credential-status-1.f4ce5c992c12216bbe47540c22ee99d7"
}
}
}
Assigning a Status Index for a Credential in the Status List From The Issuer Service
Although we can use the credential status service to assign a status index, it's quite a cumbersome process. That's why the issuer service was build to directly communicate & use the credential status service. This way when you make an IETF SD-JWT VC credential issuance request, you can reference a credential status service config + the initial status in the body of the request. The issuer service then makes the same call we just made above to assign a new status index and the result of the call then gets directly embedded into the credential.
Example Issuance Request Body With Status
{
"issuerKeyId": "waltid.tenant1.key-service-1.FtZSNCOUNcqPhGRX9xkBr5HZEGQbFRwnRtcrgbh-KmI",
"credentialConfigurationId": "identity_credential_vc+sd-jwt",
"credentialData": {
"given_name": "John",
"family_name": "Doe",
"email": "johndoe@example.com",
"phone_number": "+1-202-555-0101",
"address": {
"street_address": "123 Main St",
"locality": "Anytown",
"region": "Anystate",
"country": "US"
},
"birthdate": "1940-01-01",
"is_over_18": true,
"is_over_21": true,
"is_over_65": true
},
"mapping": {
"id": "<uuid>",
"iat": "<timestamp-seconds>",
"nbf": "<timestamp-seconds>",
"exp": "<timestamp-in-seconds:365d>"
},
"selectiveDisclosure": {
"fields": {
"birthdate": {
"sd": true
},
"family_name": {
"sd": false
}
},
"decoyMode": "NONE",
"decoys": 0
},
// STATUS
"status": {
"statusCredentialConfig": "waltid.tenant1.credential-status-1.f4ce5c992c12216bbe47540c22ee99d7",
"initialStatus": "0x0"
},
//
"authenticationMethod": "PRE_AUTHORIZED",
"standardVersion": "DRAFT13",
"expiresInSeconds": 300
}
Body Parameters
status
- Object defining the status service config + initial statusstatusCredentialConfig
: The ID of the status credential config, e.g.waltid.tenant1.credential-status-service1.config1
.initialStatus
: The string representing the hexadecimal value of the status, prefixed with 0x, e.g.0x0
.
To learn about the issuance requests + the other parameters, please go here.
Update A Status List Index
Endpoint: /v1/{target}/credential-status-service-api/status-credential/status/update
| API Reference
Example Request
curl -X 'PUT' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/credential-status-service-api/status-credential/status/update' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"index": "23481",
"status": "0x1"
}'
Path Parameters
orgID
: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedtest
, your default Base URL will betest.enterprise-sandbox.walt.dev
when using the sandbox environment.target
: resourceIdentifier - The target indicates the organization + tenant + credential status service + credential status config ID in which to create a new status list entry.{organizationID}.{tenantID}.{credentialStatusServiceID}.{statusCredentialConfigID}
), e.g.waltid.tenant1.status-service1.revocation-config
Body
{
"index": "11597",
"status": "0x1"
}
Body Parameters
index
: The index of the credential status to update.status
: The string representing the hexadecimal value of the updated status, prefixed with 0x, e.g.0x1
.
Response
200
- Status updated successfully.
{
"successful": true
}