Skip to content

Credential Service

The Credential Service exposes functionality for issuance, proof generation, verification, and revocation of Verifiable Credentials.

Signature Format

The Credential service currently supports BBS+ Signatures , which enable selective disclosure of credential fields during proof generation.

Credentials are signed, and proofs are created, using a key pair unique to the signing / holding wallet. This key pair is created and managed by Trinsic upon account creation.


Issue Credential from Template

Issues a credential from a previously-defined template.

trinsic vc issue-from-template [OPTIONS] --template-id <ID>

# OPTIONS
# --out <OUTPUT_FILE>     (Optional) Output file to store the issued credential
# --values-data <JSON>    The JSON values of the credential subject
# --values-file <FILE>    The file with JSON values of the credential subject
let request = IssueFromTemplateRequest.fromPartial({
    templateId: templateResponse?.data?.id ?? "",
    valuesJson: JSON.stringify({
        name: "Alice",
        numberOfBags: 2,
        dateOfBirth: new Date("1/1/2000").toISOString(),
        vaccinated: true,
    }),
});

let response = await trinsic.credential().issueFromTemplate(request);
var credentialJson = await trinsic.Credential.IssueFromTemplateAsync(new()
{
    TemplateId = templateId,
    ValuesJson = values
});
values = json.dumps({"firstName": "Jane", "lastName": "Doe", "age": "42"})
issue_response = await trinsic_service.credential.issue_from_template(
    request=IssueFromTemplateRequest(
        template_id=template.data.id, values_json=values
    )
)
issueTemplateResponse, err := trinsic.Credential().IssueFromTemplate(context.Background(),
    &credential.IssueFromTemplateRequest{
        ValuesJson: valuesJson,
        TemplateId: templateId,
    })
var valuesMap = new HashMap<String, Object>();
valuesMap.put("firstName", "Jane");
valuesMap.put("lastName", "Doe");
valuesMap.put("age", 42);
var valuesJson = new Gson().toJson(valuesMap);
var issueResponse =
    trinsic
        .credential()
        .issueFromTemplate(
            IssueFromTemplateRequest.newBuilder()
                .setTemplateId(templateId)
                .setValuesJson(valuesJson)
                .build())
        .get();

Request to create and sign a JSON-LD Verifiable Credential from a template using public key tied to caller
template_id
string
ID of template to use
values_json
string
JSON document string with keys corresponding to the fields of the template referenced by template_id
framework_id
optional string
Governance framework ID to use with issuance of this credential. If specified, the issued credential will contain extended issuer metadata with membership info for the given ecosystem governance framework (EGF)
save_copy
bool
Save a copy of the issued credential to this user's wallet. This copy will only contain the credential data, but not the secret proof value. Issuers may use this data to keep track of the details for revocation status.
expiration_date
string
The ISO8601 expiration UTC date of the credential. This is a reserved field in the VC specification. If specified, the issued credential will contain an expiration date. https://www.w3.org/TR/vc-data-model/#expiration

Response to IssueFromTemplateRequest
document_json
string
Verifiable Credential document, in JSON-LD form, constructed from the specified template and values; signed with public key tied to caller of IssueFromTemplateRequest

Add governance information to issued credential

In order to attach governance information to the credential, issuers must request this explicitly by specifying the parameter framework_id in the above request. The framework identifier references the ecosystem governance framework that the issuer is authorized to issue credentials of the designated type (schema). This identifier has the format urn:egf:<ecosystem>:<type>.

When this parameter is specified, the issued credential will contain extended information in the issuer field to assert authorization in the given governance framework. The framework identifier will be in the issuer.trustRegistry field. Here's an example of a VC with extended issuer information:

"issuer": {
    "id": "did:key:z5TcEFAQPu7RkrBCMCJDGgVziV",
    "type": "AuthoritativeMember"
    "governanceFramework": "https://acme.org/authorized-issuers",
    "trustRegistry": "urn:egf:acme:92f21b4cb3bc48dd8bb19a872f03afca",
  }

See Trust Registry Service for more information on using governance in your ecosystem.


Check Revocation Status

Checks a credential's revocation status by its credential_status_id.

A credential_status_id can be found in a credential's credentialStatus.id field, if present.

trinsic vc get-status --credential-status-id <ID>
let checkStatusResponse = await trinsic
    .credential()
    .checkStatus(CheckStatusRequest.fromPartial({}));
var checkResponse = await trinsic.Credential.CheckStatusAsync(new() { CredentialStatusId = "" });
#     check_response = await trinsic_service.credential.check_status(
#         request=CheckStatusRequest(credential_status_id="")
#     )
status, err := trinsic.Credential().CheckStatus(context.Background(), &credential.CheckStatusRequest{CredentialStatusId: ""})
var checkStatusResponse =
    trinsic.credential().checkStatus(CheckStatusRequest.newBuilder().build()).get();

Request to check a credential's revocation status
credential_status_id
string
Credential Status ID to check. This is not the same as the credential's ID.

Response to CheckStatusRequest
revoked
bool
The credential's revocation status


Update Revocation Status

Updates the revocation status of a credential (revoke or unrevoke).

A credential_status_id can be found in a credential's credentialStatus.id field, if present.

# Revoke a credential
trinsic vc update-status --revoked --credential-status-id <ID>

# Unrevoke a credential
trinsic vc update-status --unrevoked --credential-status-id <ID>
let updateStatusResponse = await trinsic
    .credential()
    .updateStatus(UpdateStatusRequest.fromPartial({}));
await trinsic.Credential.UpdateStatusAsync(new() { CredentialStatusId = "", Revoked = true });
#     update_response = await trinsic_service.credential.update_status(
#         request=UpdateStatusRequest(credential_status_id="", revoked=True)
#     )
updateStatusResponse, err := trinsic.Credential().UpdateStatus(context.Background(), &credential.UpdateStatusRequest{CredentialStatusId: "", Revoked: true})
trinsic.credential().updateStatus(UpdateStatusRequest.newBuilder().build());

Request to update a credential's revocation status
credential_status_id
string
Credential Status ID to update. This is not the same as the credential's ID.
revoked
bool
New revocation status of credential

Response to UpdateStatusRequest
This message has no fields


Create Proof

Creates and signs a proof for a valid JSON-LD credential, using the BBS+ Signature Suite.

If the credential is stored in a Trinsic cloud wallet, pass its item_id; otherwise, pass the raw JSON-LD credential via document_json.

Selective Disclosure

BBS+ Signatures support the ability to generate a proof for a subset of a credential's fields, instead of every field.

This enables increased user privacy: fields which aren't included in reveal_document_json will not be present in the generated proof.

  1. If reveal_document_json is passed, a proof will be generated for only the fields specified. This is a JSON-LD frame.
  2. Rather than formulating a complete JSON-LD frame, you can instead provide a list of proof attributes to reveal, and the service will construct the JSON-LD proof frame internally
  3. If neither is provided, the entire proof will be returned.
trinsic vc create-proof --document-id <STRING> --out <OUTPUT_FILE> --reveal-document <JSONLD_FRAME_FILE>
let proof = await trinsic.credential().createProof(
    CreateProofRequest.fromPartial({
        itemId: insertItemResponse.itemId
    })
);
let selectiveProof = await trinsic.credential().createProof(
    CreateProofRequest.fromPartial({
        itemId: insertItemResponse.itemId,
        revealTemplate: {
            templateAttributes: ["firstName", "lastName"],
        },
    })
);
var proof = await trinsic.Credential.CreateProofAsync(new()
{
    DocumentJson = credentialJson.DocumentJson,
    RevealDocumentJson = frame.ToString(Formatting.None)
});
var selectiveProof = await trinsic.Credential.CreateProofAsync(new()
{
    DocumentJson = credentialJson.DocumentJson,
    RevealTemplate = new()
    {
        // The other field, not disclosed, is "age"
        TemplateAttributes = { "firstName", "lastName" }
    }
});
proof_response = await trinsic_service.credential.create_proof(
    request=CreateProofRequest(
        document_json=credential_json
    )
)
selective_proof_response = await trinsic_service.credential.create_proof(
    request=CreateProofRequest(
        document_json=credential_json,
        reveal_template=RevealTemplateAttributes(
            template_attributes=["firstName"]
        ),
    )
)
request := &credential.CreateProofRequest{
    Proof: &credential.CreateProofRequest_DocumentJson{
        DocumentJson: credentialJson,
    },
}

proofResponse, err := trinsic.Credential().CreateProof(context.Background(), request)

selectiveRequest := &credential.CreateProofRequest{
    Proof: &credential.CreateProofRequest_DocumentJson{
        DocumentJson: credentialJson,
    },
    Disclosure: &credential.CreateProofRequest_RevealTemplate{RevealTemplate: &credential.RevealTemplateAttributes{TemplateAttributes: []string{"name"}}},
}

selectiveResponse, err2 := trinsic.Credential().CreateProof(context.Background(), selectiveRequest)
var createProofResponse =
    trinsic
        .credential()
        .createProof(
            CreateProofRequest.newBuilder()
                .setDocumentJson(signedCredentialJson)
                .build())
        .get();

var credentialProof = createProofResponse.getProofDocumentJson();

var selectiveProofResponse =
    trinsic
        .credential()
        .createProof(
            CreateProofRequest.newBuilder()
                .setDocumentJson(signedCredentialJson)
                .setRevealTemplate(
                    RevealTemplateAttributes.newBuilder()
                        .addTemplateAttributes("batchNumber")
                        .build())
                .build())
        .get();

var selectiveProof = selectiveProofResponse.getProofDocumentJson();

Request to create a proof for a Verifiable Credential using public key tied to caller. Either item_id or document_json may be provided, not both.
reveal_document_json
string
A valid JSON-LD frame describing which fields should be revealed in the generated proof. If unspecified, all fields in the document will be revealed
reveal_template
Information about what sections of the document to reveal
Show child attributes
item_id
string
ID of wallet item stored in a Trinsic cloud wallet
document_json
string
A valid JSON-LD Verifiable Credential document string with an unbound signature. The proof will be derived from this document directly. The document will not be stored in the wallet.
use_verifiable_presentation
bool
Wrap the output in a verifiable presentation
nonce
optional bytes
Nonce value used to derive the proof. If not specified, a random nonce will be generated. This value may be represented in base64 format in the proof model.

Response to CreateProofRequest
proof_document_json
string
Valid JSON-LD proof for the specified credential


Verify Proof

Verifies a proof for validity and authenticity. Only supports BBS+ Signatures at present.

# The JSONLD_FILE refers to the proof document obtained from a CreateProofResponse
trinsic vc issuer verify-proof --proof-document <JSONLD_FILE>
let verifyResponse = await trinsic.credential().verifyProof({
    proofDocumentJson: proof.proofDocumentJson,
});



    proofDocumentJson: selectiveProof.proofDocumentJson,
var valid = await trinsic.Credential.VerifyProofAsync(new()
    { ProofDocumentJson = proof.ProofDocumentJson });
verify_result = await trinsic_service.credential.verify_proof(
    request=VerifyProofRequest(proof_document_json=credential_proof)
)
selective_verify_result = await trinsic_service.credential.verify_proof(
    request=VerifyProofRequest(
        proof_document_json=selective_proof_response.proof_document_json
    )
)
verifyResponse, err := trinsic.Credential().VerifyProof(context.Background(), &credential.VerifyProofRequest{
    ProofDocumentJson: proofJson,
})
var verifyProofResponse =
    trinsic
        .credential()
        .verifyProof(
            VerifyProofRequest.newBuilder().setProofDocumentJson(credentialProof).build())
        .get();

boolean isValid = verifyProofResponse.getIsValid();

Request to verify a proof
proof_document_json
string
JSON-LD proof document string to verify

Response to VerifyProofRequest
is_valid
bool
Whether all validations in validation_results passed
validation_results
map(string -> ValidationMessage)
Results of each validation check performed, such as schema conformance, revocation status, signature, etc. Detailed results are provided for failed validations.
Show child attributes

Validation Results

The verification process performs a number of validations, each of which may fail independently of the others.

For example, a credential may be expired or revoked, but otherwise perfectly valid.

validation_results contains an entry for each of the following verification steps:

Name Description
SignatureVerification The cryptographic proof over the entire Verifiable Credential, specifically using BBS+ Proof of Signature
CredentialStatus (if supported by credential) Checks if credential has been revoked
SchemaConformance Ensures credential conforms with its schema. It is possible to issue a credential omitting a required field (as captured in the credential template). If your use case allows this kind of omission, you can ignore this validation entry.
TrustRegistryMembership (if relevant) Verifies that credential issuer is an authorized member of the credential's governing Trust Registry
IssuerIsSigner Document issuer is same DID as document signer. If false, it is not safe to assume that the claimed issuer actually issued the credential.

Exchange Credentials

Send via Email

Sends a credential to a user via email.

The specified email address must be tied to an existing account in the same ecosystem.

trinsic vc send --email <EMAIL_ADDRESS> --item <FILE>
await trinsic.credential().send(SendRequest.fromPartial({
    email: "",
    documentJson: JSON.stringify({}),
}));
var sendResponse = await trinsic.Credential.SendAsync(new() { Email = "[email protected]" });
send_response = await trinsic_service.credential.send(
    request=SendRequest(
        document_json=credential_json, email="[email protected]"
    )
)
sendResponse, err := trinsic.Credential().Send(context.Background(), &credential.SendRequest{
    DeliveryMethod: &credential.SendRequest_Email{
        Email: "[email protected]",
    },
    DocumentJson: credentialJson,
})
trinsic
    .credential()
    .send(
        SendRequest.newBuilder()
            .setDocumentJson(signedCredentialJson)
            .setEmail(recipientEmail)
            .build());

Request to send a document to another user's wallet
email
string
Email address of user to whom you'll send the item
wallet_id
string
Wallet ID of the recipient within the ecosystem
did_uri
string
DID URI of the recipient
phone_number
string
SMS of user to whom you'll send the item
send_notification
bool
Send email notification that credential has been sent to a wallet
document_json
string
JSON document to send to recipient

Response to SendRequest
This message has no fields

Alternative Exchange Protocols

Credentials may only be sent to a wallet via email address or with the InsertItem call.

There are a number of ongoing industry efforts to standardize exchange protocols, such as:

We aim to provide support for these methods as they mature.