Skip to content

Credential Template Service

The Credential Template Service allows you to manage and search Credential Templates.


Create Credential Template

Creates a new credential template.

The name of a credential template must be unique within your ecosystem, and cannot be changed -- it is used to derive the URI of the template itself.

The title and description parameters (for the credential template itself, as well as for any of its fields) should be human-readable strings. They should describe the credentials issued by the template, not the template itself (for example, a good title for a medical license template would simply be "Medical License", not "Medical License Template").

field_ordering may be used to specify the order in which fields are rendered when displaying a credential, and to categorize fields into logical sections. This is used for display only, and has no bearing on working with credentials as an issuer or verifier.

trinsic template create --name 'My Credential' --fields-data '{\"field1\":{}}'
const createRequest: CreateCredentialTemplateRequest = {
    name: `An Example Credential-${uuid()}`,
    title: "Example Credential",
    description: "A credential for Trinsic's SDK samples",
    allowAdditionalFields: false,
    fields: {
        firstName: {
            title: "First Name",
            description: "Given name of holder",
        },
        lastName: {
            title: "Last Name",
            description: "Surname of holder",
            optional: true,
        },
        age: {
            title: "Age",
            description: "Age in years of holder",
            type: FieldType.NUMBER,
        },
    },
    fieldOrdering: {
        firstName: { order: 0, section: "Name" },
        lastName: { order: 1, section: "Name" },
        age: { order: 2, section: "Miscellaneous" },
    },
    appleWalletOptions: {
        primaryField: "firstName",
        secondaryFields: ["lastName"],
        auxiliaryFields: ["age"],
    },
};

const createResponse = await trinsic.template().create(createRequest);
CreateCredentialTemplateRequest createRequest = new() {
    Name = "An Example Credential",
    Title = "Example Credential",
    Description = "A credential for Trinsic's SDK samples",
    AllowAdditionalFields = false,
    Fields =
    {
        { "firstName", new() { Title = "First Name", Description = "Given name of holder" } },
        { "lastName", new() { Title = "Last Name", Description = "Surname of holder", Optional = true } },
        { "age", new() { Title = "Age", Description = "Age in years of holder", Type = FieldType.Number } }
    },
    FieldOrdering =
    {
        { "firstName", new() { Order = 0, Section = "Name" } },
        { "lastName", new() { Order = 1, Section = "Name" } },
        { "age", new() { Order = 2, Section = "Miscellanous" } }
    },
    AppleWalletOptions = new() {
        PrimaryField = "firstName",
        SecondaryFields = { "lastName" },
        AuxiliaryFields = { "age" }
    }
};

var template = await trinsic.Template.CreateAsync(createRequest);
create_request = CreateCredentialTemplateRequest(
    name=f"An Example Credential-{random.Random().randint(0,100)}",
    title="Example Credential",
    description="A credential for Trinsic's SDK samples",
    allow_additional_fields=False,
    fields={
        "firstName": TemplateField(
            title="First Name", description="Given name of holder"
        ),
        "lastName": TemplateField(
            title="Last Name", description="Surname of holder", optional=True
        ),
        "age": TemplateField(
            title="Age", description="Age in years of holder", type=FieldType.NUMBER
        ),
    },
    field_ordering={
        "firstName": FieldOrdering(order=0, section="Name"),
        "lastName": FieldOrdering(order=1, section="Name"),
        "age": FieldOrdering(order=2, section="Miscellaneous"),
    },
    apple_wallet_options=AppleWalletOptions(
        primary_field="firstName",
        secondary_fields=["lastName"],
        auxiliary_fields=["age"],
    ),
)
create_response = await trinsic_service.template.create(request=create_request)
templateRequest := &template.CreateCredentialTemplateRequest{
    Name:                  "An Example Credential",
    Title:                 "Example Credential",
    Description:           "A credential for Trinsic's SDK samples",
    AllowAdditionalFields: false,
    Fields: map[string]*template.TemplateField{
        "firstName": {
            Title:       "First Name",
            Description: "Given name of holder",
        },
        "lastName": {
            Title:       "Last Name",
            Description: "Surname of holder",
            Optional:    true,
        },
        "age": {
            Title:       "Age",
            Description: "Age in years of holder",
            Type:        template.FieldType_NUMBER,
        },
    },
    FieldOrdering: map[string]*template.FieldOrdering{
        "firstName": {Order: 0, Section: "Name"},
        "lastName":  {Order: 1, Section: "Name"},
        "age":       {Order: 2, Section: "Miscellaneous"},
    },
    AppleWalletOptions: &template.AppleWalletOptions{
        PrimaryField:    "firstName",
        SecondaryFields: []string{"lastName"},
        AuxiliaryFields: []string{"age"},
    },
}

templateResponse, err := trinsic.Template().Create(context.Background(), templateRequest)
var templateRequest =
    CreateCredentialTemplateRequest.newBuilder()
        // Set metadata
        .setName("An Example Credential" + UUID.randomUUID())
        .setTitle("Example Credential")
        .setDescription("A credential for Trinsic's SDK samples")
        .setAllowAdditionalFields(false)
        // Construct fields
        .putFields(
            "firstName",
            TemplateField.newBuilder()
                .setTitle("First Name")
                .setDescription("Given name of holder")
                .build())
        .putFields(
            "lastName",
            TemplateField.newBuilder()
                .setTitle("Last Name")
                .setDescription("Surname of holder")
                .setOptional(true)
                .build())
        .putFields(
            "age",
            TemplateField.newBuilder()
                .setTitle("Age")
                .setDescription("Age in years of holder")
                .setType(FieldType.NUMBER)
                .build())
        // Specify ordering and categorization of fields for rendering of credential
        .putFieldOrdering(
            "firstName", FieldOrdering.newBuilder().setOrder(0).setSection("Name").build())
        .putFieldOrdering(
            "lastName", FieldOrdering.newBuilder().setOrder(1).setSection("Name").build())
        .putFieldOrdering(
            "age", FieldOrdering.newBuilder().setOrder(2).setSection("Miscellaneous").build())
        // Specify Apple Wallet configuration
        .setAppleWalletOptions(
            AppleWalletOptions.newBuilder()
                .setPrimaryField("firstName")
                .addSecondaryFields("lastName")
                .addAuxiliaryFields("age")
                .build())
        .build();
var template = trinsic.template().create(templateRequest).get();

Request to create a new template
name
string
Name of new template. Must be a unique identifier within its ecosystem.
fields
map(string -> TemplateField)
Fields which compose the template
Show child attributes
allow_additional_fields
bool
Whether credentials may be issued against this template which have fields not specified in fields
title
string
Human-readable name of template
description
string
Human-readable description of template
field_ordering
map(string -> FieldOrdering)
Optional map describing how to order and categorize the fields within the template. The key of this map is the field name. If not provided, this will be auto-generated.
Show child attributes
apple_wallet_options
Options for rendering the template in Apple Wallet
Show child attributes

Response to CreateCredentialTemplateRequest
data
Created template
Show child attributes


Update Credential Template

Updates a credential template's display metadata, such as its human-readable title/description.

This call cannot be used to update credential templates in a way that might invalidate previously-issued credentials: fields cannot be added, removed, or renamed, but their title and description properties may be updated.

In order to leave a property unchanged (for example, if you wish to change description but not title), simply leave it unspecified (don't set it to an empty string/object). This applies to fields as well: any field not specified in fields will remain unchanged.

Not yet supported
const updateRequest: UpdateCredentialTemplateRequest = {
    id: templateId,
    title: "New Title",
    description: "New Description",
    fields: {
        firstName: { title: "New title for firstName" },
        lastName: { description: "New description for lastName" },
    },
    fieldOrdering: {
        age: { order: 0, section: "Misc" },
        firstName: { order: 1, section: "Full Name" },
        lastName: { order: 2, section: "Full Name" },
    },
    appleWalletOptions: {
        primaryField: "age",
        secondaryFields: ["firstName", "lastName"],
    },
};

const updateResponse = await trinsic.template().update(updateRequest);
UpdateCredentialTemplateRequest updateRequest = new() {
    Id = templateId,
    Title = "New Title",
    Description = "New Description",
    Fields =
    {
        { "firstName", new() { Title = "New title for firstName" } },
        { "lastName", new() { Description = "New description for lastName" } }
    },
    FieldOrdering =
    {
        { "age", new() { Order = 0, Section = "Misc" } },
        { "firstName", new() { Order = 1, Section = "Full Name" } },
        { "lastName", new() { Order = 2, Section = "Full Name" } },
    },
    AppleWalletOptions = new() {
        PrimaryField = "age",
        SecondaryFields = { "firstName", "lastName" }
    }
};

var updatedTemplate = await trinsic.Template.UpdateAsync(updateRequest);
update_request = UpdateCredentialTemplateRequest(
    id=template_id,
    title="New Title",
    description="New Description",
    fields={
        "firstName": TemplateFieldPatch(title="New title for firstName"),
        "lastName": TemplateFieldPatch(description="New description for lastName"),
    },
    field_ordering={
        "age": FieldOrdering(order=0, section="Misc"),
        "firstName": FieldOrdering(order=1, section="Full Name"),
        "lastName": FieldOrdering(order=2, section="Full Name"),
    },
    apple_wallet_options=AppleWalletOptions(
        primary_field="age", secondary_fields=["firstName", "lastName"]
    ),
)
update_response = await trinsic_service.template.update(request=update_request)
var newTemplateTitle = "New Title"
var newTemplateDescription = "New Description"
var newFirstNameTitle = "New title for firstName"
var newLastNameDescription = "New description for lastName"

updateRequest := &template.UpdateCredentialTemplateRequest{
    Id:          templateId,
    Title:       &newTemplateTitle,
    Description: &newTemplateDescription,
    Fields: map[string]*template.TemplateFieldPatch{
        "firstName": {Title: &newFirstNameTitle},
        "lastName":  {Description: &newLastNameDescription},
    },
    FieldOrdering: map[string]*template.FieldOrdering{
        "age":       {Order: 0, Section: "Misc"},
        "firstName": {Order: 1, Section: "Full Name"},
        "lastName":  {Order: 2, Section: "Full Name"},
    },
    AppleWalletOptions: &template.AppleWalletOptions{
        PrimaryField:    "age",
        SecondaryFields: []string{"firstName", "lastName"},
    },
}

updateResponse, err := trinsic.Template().Update(context.Background(), updateRequest)
var updateRequest =
    UpdateCredentialTemplateRequest.newBuilder()
        .setId(templateId)
        // Specify new title and description for the template
        .setTitle("New Title")
        .setDescription("New Description")
        // Update title/description for a few fields
        .putFields(
            "firstName",
            TemplateFieldPatch.newBuilder().setTitle("New title for firstName").build())
        .putFields(
            "lastName",
            TemplateFieldPatch.newBuilder()
                .setDescription("New description for lastName")
                .build())
        // Specify new ordering / categorization for template fields
        .putFieldOrdering(
            "age", FieldOrdering.newBuilder().setOrder(0).setSection("Misc").build())
        .putFieldOrdering(
            "firstName", FieldOrdering.newBuilder().setOrder(1).setSection("Full Name").build())
        .putFieldOrdering(
            "lastName", FieldOrdering.newBuilder().setOrder(2).setSection("Full Name").build())
        // Specify new Apple Wallet configuration
        .setAppleWalletOptions(
            AppleWalletOptions.newBuilder()
                .setPrimaryField("age")
                .addSecondaryFields("firstName")
                .addSecondaryFields("lastName")
                .build())
        .build();

var updatedTemplate = trinsic.template().update(updateRequest).get();

Request to update display information for a template
id
string
ID of Template to update
title
string
New human-readable title of Template
description
string
New human-readable description of Template
fields
map(string -> TemplateFieldPatch)
Fields to update within the Template
Show child attributes
field_ordering
map(string -> FieldOrdering)
New field ordering options. See documentation for template creation for usage information.
Show child attributes
apple_wallet_options
New Apple Wallet configuration
Show child attributes

Response to UpdateCredentialTemplateRequest
updated_template
The Template after the update has been applied
Show child attributes


Get Credential Template

Fetches a credential template definition by id.

trinsic template get --id <TEMPLATE_ID>
let getTemplateResponse = await trinsic.template().get(
    GetCredentialTemplateRequest.fromPartial({
        id: "id",
    }),
);
var getTemplateResponse = await trinsic.Template.GetAsync(new() { Id = template.Data.Id });
get_template_response = await trinsic_service.template.get(
    request=GetCredentialTemplateRequest(id=template.data.id)
)
getResponse, err := trinsic.Template().Get(context.Background(), &template.GetCredentialTemplateRequest{Id: templateResponse.Data.Id})
var getResponse =
    trinsic
        .template()
        .get(GetCredentialTemplateRequest.newBuilder().setId(templateId).build())
        .get();

Request to fetch a template by ID
id
string
ID of template to fetch

Response to GetCredentialTemplateRequest
template
Template fetched by ID
Show child attributes


Delete Credential Template

Deletes a credential template by id.

trinsic template delete --id <TEMPLATE_ID>
var deleteTemplateResponse = await trinsic.Template.DeleteAsync(new() { Id = template.Data.Id });
delete_template_response = await trinsic_service.template.delete(
    request=DeleteCredentialTemplateRequest(id=template.data.id)
)
deleteResponse, err := trinsic.Template().Delete(context.Background(), &template.DeleteCredentialTemplateRequest{Id: templateResponse.Data.Id})
var deleteResponse =
    trinsic
        .template()
        .delete(DeleteCredentialTemplateRequest.newBuilder().setId(templateId).build())
        .get();

Request to delete a template by ID
id
string
ID of template to delete

Response to DeleteCredentialTemplateRequest
This message has no fields


Search Credential Templates

Searches all credential templates defined in the current ecosystem.

If no query is specified, this call by default returns the first 100 templates.

If more results are available than can be returned in a single call, the continuation_token field in the response will be non-empty; pass it back in a subsequent request to retrieve the next page.

trinsic wallet search \
    --query "SELECT * FROM c"
let searchTemplateResponse = await trinsic.template().search(
    SearchCredentialTemplatesRequest.fromPartial({
        query: "Select * from c",
    }),
);
var searchTemplateResponse = await trinsic.Template.SearchAsync(new() { Query = "SELECT * FROM c" });
search_template_response = await trinsic_service.template.search(
    request=SearchCredentialTemplatesRequest(query="SELECT * FROM c")
)
searchResponse, err := trinsic.Template().Search(context.Background(), &template.SearchCredentialTemplatesRequest{Query: "SELECT * FROM c"})
var searchResponse =
    trinsic
        .template()
        .search(
            SearchCredentialTemplatesRequest.newBuilder()
                .setQuery("SELECT * FROM c WHERE c.id = '" + templateId + "'")
                .build())
        .get();

Request to search templates using a SQL query
query
string
SQL query to execute. Example: SELECT * FROM c WHERE c.name = 'Diploma'
continuation_token
optional string
Token provided by previous SearchCredentialTemplatesResponse if more data is available for query

Response to SearchCredentialTemplatesRequest
items_json
string
Raw JSON data returned from query
has_more_results
bool
Whether more results are available for this query via continuation_token
continuation_token
string
Token to fetch next set of results via SearchCredentialTemplatesRequest

The Search endpoint supports SQL queries through the query parameter.

This allows for arbitrary query predicates, as well as more advanced functionality -- such as modifying the output format.

Schema

Any table name may be used in your query (we use c here) -- it doesn't matter what it is.

Name Type Description
id string Corresponds to the id returned when credential template was created
type string Always VerifiableCredential
ecosystemId string ID of ecosystem in which credential template resides
createdBy string ID of account which defined the credential template
name string Name provided during credential template creation
schemaUri string HTTPS URL pointing to JSON Schema generated by Trinsic for this template
contextUri string HTTPS URL pointing to JSON-LD Context generated by Trinsic for this template
version int Version of template; increments whenever template is modified.
fields object JSON Object representing the credential template's fields

Note that fields is an object, not a string; thus, any of its sub-fields may be queried against.

More Info

This endpoint works very similarly to querying Wallet items; please see Wallet Service > Search for more information.