This example showcases a Credential Issuer for ACK-ID and ACK-Pay Verifiable Credentials. This API is built with Hono.
The API allows for the issuance, verification, and revocation of the following credential types:
ControllerCredential: ACK-ID credentials that prove DID ownership hierarchies.PaymentReceiptCredential: ACK-Pay credentials that provide proof of payment that satisfies a given Payment Request.
This issuer supports credential revocation using Bitstring Status List, which is a privacy-preserving, space-efficient mechanism for maintaining a credential revocation list.
pnpm run setuppnpm run devThe server will be available at http://localhost:3456
To simplify the development experience, this API uses a SQLite database. In a production environment, we recommend using a database with native bitwise operations like PostgreSQL.
All API endpoints require a signed payload to prove ownership of the DIDs involved. This payload is a JWT of the request parameters, signed using your DID.
In local development, each endpoint accepts a X-Payload-Issuer header with a DID-URI as a value. This bypasses the signed payload requirement, and simulates that you signed by the payload. NOTE: This did MUST be resolvable, which makes using the local-did-host server helpful.
All API responses respond as JSON objects with the following format:
{
"ok": true,
"data": <anything>
}or
{
"ok": false,
"error": "string error message"
}Create a new ControllerCredential that proves one DID controls another
Request Payload, signed by the controller
SignedPayload<{
controller: "did:..."
subject: "did:..."
}>Response Body
{
"ok": true,
"data": {
"credential": {
...
}
"jwt": "credential-jwt"
}
}Sample cURL
curl --request POST \
--url http://localhost:3456/credentials/controller \
--header 'Content-Type: application/json' \
--header 'X-Payload-Issuer: did:web:0.0.0.0%3A3458:controller' \
--data '{
"controller": "did:web:0.0.0.0%3A3458:controller",
"subject": "did:web:0.0.0.0%3A3458:agent"
}'Retrieve a credential by its identifier
Response Body
{
"ok": true,
"data": {
"credential": {
...
}
"jwt": "credential-jwt"
}
}Sample cURL
curl --request GET \
--url http://localhost:3456/credentials/controller/abc123Revoke a credential by its identifier
Request Payload, signed by the controller
SignedPayload<{
id: "credential-id"
}>Response Body
{
"ok": true,
"data": null
}Sample cURL
curl --request DELETE \
--url http://localhost:3456/credentials/controller \
--header 'Content-Type: application/json' \
--header 'X-Payload-Issuer: did:web:0.0.0.0%3A3458:controller' \
--data '{
"id": "abc123"
}'Generate a payment receipt credential that proves a payment was made
Request Payload, signed by the wallet that made the payment:
SignedPayload<{
metadata: {
txHash: "0x123..."
}
payerDid: "did:..."
paymentRequestToken: "jwt-token"
paymentOptionId: "option-id"
}>Response Body
{
"ok": true,
"data": {
"credential": {
...
}
"jwt": "credential-jwt"
}
}Sample cURL
curl --request POST \
--url http://localhost:3456/credentials/receipts \
--header 'Content-Type: application/json' \
--header 'X-Payload-Issuer: did:web:0.0.0.0%3A3458:wallet' \
--data '{
"metadata": {
"txHash": "0x123abc456def"
},
"payerDid": "did:web:0.0.0.0%3A3458:wallet",
"paymentRequestToken": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
"paymentOptionId": "option1"
}'Retrieve a payment receipt credential by its identifier
Response Body
{
"ok": true,
"data": {
"credential": {
...
}
"jwt": "credential-jwt"
}
}Sample cURL
curl --request GET \
--url http://localhost:3456/credentials/receipts/abc123Revokes a payment receipt credential by flipping the bit on the credential's Status List.
For demo purposes, we only allow the original payment request token issuer to revoke the receipt.
Request Payload, signed by the original payment request token issuer
SignedPayload<{
id: "receipt-id"
}>Response Body
{
"ok": true,
"data": null
}Sample cURL
curl --request DELETE \
--url http://localhost:3456/credentials/receipts \
--header 'Content-Type: application/json' \
--header 'X-Payload-Issuer: did:web:0.0.0.0%3A3458:payee' \
--data '{
"id": "abc123"
}'Retrieve a Bitstring Status List credential for checking revocation status
Response Body
{
"ok": true,
"data": "jwt-string"
}Sample cURL
curl --request GET \
--url http://localhost:3456/status/1Return the DID document for the issuer
Response Body
{
"@context": [...],
"id": "did:web:...",
"verificationMethod": [...],
"authentication": [...],
"assertionMethod": [...]
}Sample cURL
curl --request GET \
--url http://localhost:3456/.well-known/did.jsonCopyright (c) 2025 Catena Labs, Inc.