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 Credential Template

Issues a credential from a previously-defined credential template.

import { TrinsicService } from "@trinsic/trinsic";

const trinsic = new TrinsicService({ authToken: "<auth token>" });

const request = {
    templateId: "https://schema.trinsic.cloud/default/example-credential",
    include_governance: true,
    valuesJson: JSON.stringify({
        "name": "John Doe",
        "email": "john.doe@example.com"
    })
};
const 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
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
include_governance
bool
If true, the issued credential will contain an attestation of the issuer's membership in the ecosystem's Trust Registry.
signature_type
The type of signature to use when signing the credential. Defaults to EXPERIMENTAL.
Show enum values

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 Trust Registry information to issued credential

In order to attach governance information to the credential, issuers must request this explicitly by specifying the parameter include_governance to true in the above request. This will reference the ecosystem's Trust Registry that the issuer is authorized to issue credentials of the designated type (schema).

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

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

See Trust Registry Service for more information on managing your ecosystem's governance.


Create Credential Offer

The purpose of the "Create Offer" endpoint is to initiate interactive issuance and facilitate the issuance of a verifiable credential. This endpoint serves as the starting point for the interactive issuance process, allowing the issuing party to generate an offer to issue a credential to a specific user or entity.

By utilizing the "Create Offer" endpoint, the issuing party can initiate a request for the user's consent to issue a verifiable credential on their behalf. This interactive process ensures that the user actively participates in the credential issuance and has the opportunity to review and provide their consent before the credential is issued.

Furthermore, the "Create Offer" endpoint enables the issuing party to define and configure the holder binding properties of the credential. This means that the issued VC will be bound to the intended holder, making it non-transferable and restricted for use solely by the authorized holder. When holder_binding is set to true, upon acceptance of the credential offer, the resulting VC will have credentialSubject.id set to the holder's wallet DID. Otherwise, it defaults to a static value urn:vc:subject:0. During proof creation, if the VC includes a holder DID within the credentialSubject field, the resulting proof will also include a proof of ownership associated with the holder DID. This serves to authenticate to the verifier that the presenter of the proof indeed possesses the DID designated by the issuer within the credentialSubject field of the credential.

let createCredentialOfferResponse = await trinsic.credential().createCredentialOffer(
    CreateCredentialOfferRequest.fromPartial({
        templateId: templateId,
        valuesJson: issueResponse.documentJson,
        holderBinding: true,
        includeGovernance: true,
        generateShareUrl: true,
        signatureType: SignatureType.EXPERIMENTAL,
    })
);

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
holder_binding
optional bool
If true, the credential will be issued with holder binding by specifying the holder DID in the credential subject
include_governance
optional bool
If true, the issued credential will contain an attestation of the issuer's membership in the ecosystem's Trust Registry.
generate_share_url
optional bool
If true, a short URL link will be generated that can be used to share the credential offer with the holder. This link will point to the credential offer in the wallet app.
signature_type
optional SignatureType
The type of signature to use when signing the credential. Defaults to EXPERIMENTAL.
Show enum values

document_json
string
The JSON document that contains the credential offer
share_url
string
If requested, a URL that can be used to share the credential offer with the holder. This is a short URL that can be used in a QR code and will redirect the holder to the credential offer using the wallet app.


Accept Credential

The purpose of the "Accept Offer" method is for the user to formally accept the offered verifiable credential. It enables the user to provide explicit consent and indicate their willingness to receive and possess the credential. By using this method, the user confirms their agreement to become the rightful holder of the credential.

The "Accept Offer" method is a mandatory step in the issuance process, as it solidifies the user's commitment to acquiring the verifiable credential. During this step, if the issuer requested binding information, the user's wallet will submit a proof of DID ownership bind the credential to the user and make it non-transferable. The verifiable credential is then securely generated and delivered to the user, officially establishing their possession and ownership of the credential.

let acceptCredentialResponse = await trinsic.credential().acceptCredential(
    AcceptCredentialRequest.fromPartial({
        documentJson: createCredentialOfferResponse.documentJson,
    })
);

document_json
string
The JSON document that contains the credential offer
item_id
optional string
The ID of the credential offer (Parameter ID inside the JSON document)

item_id
string
The ID of the item in the wallet that contains the issued credential
document_json
string
The JSON document that contains the issued credential. This item is already stored in the wallet.


Reject Credential

This endpoint allows users to decline or reject an offered verifiable credential. By utilizing this endpoint, users can explicitly communicate their decision not to accept the credential being offered to them. By offering this option in your application, your platform promotes user empowerment and supports a transparent workflow for the acceptance or rejection of verifiable credentials.   

let rejectCredentialResponse = await trinsic.credential().rejectCredential(
    RejectCredentialRequest.fromPartial({
        documentJson: createCredentialOfferResponse.documentJson,
    })
);

document_json
string
The JSON document that contains the credential offer
item_id
optional string
The ID of the credential offer (Parameter ID inside the JSON document)

This message has no fields


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 via reveal_template.template_attributes, 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({
        documentJson: issueResponse.documentJson,
        itemId: insertItemResponse.itemId,
    }),
);
let selectiveProof = await trinsic.credential().createProof(
    CreateProofRequest.fromPartial({
        documentJson: issueResponse.documentJson,
        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
verification_template_id
string
Id of verification template with which to construct the JSON-LD proof document
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. If the credential used in the proof is bound to the holder DID, the output will always use a verifiable presentation and this field will be ignored.
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,
});

let selectiveVerifyResponse = await trinsic.credential().verifyProof({
    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({
    documentJson: issueResponse.documentJson,
    email: "<EMAIL>",
    sendNotification: true,
}));
var sendResponse = await trinsic.Credential.SendAsync(new() {
    Email = "<EMAIL>",
    DocumentJson = issueResponse.DocumentJson,
    SendNotification = true,
    });
send_response = await trinsic_service.credential.send(
    request=SendRequest(
        document_json=credential_json, email="example@trinsic.id"
    )
)
sendResponse, err := trinsic.Credential().Send(context.Background(), &credential.SendRequest{
    DeliveryMethod: &credential.SendRequest_Email{
        Email: "example@trinsic.id",
    },
    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
optional 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.