Configure credential types
This guide shows you how to configure Type Metadata for the Truvity EUDIW Connector. Type Metadata defines the credential types your connector can issue—including claim definitions, selective disclosure settings, display metadata, and the Verifiable Credential Type (VCT) URI that wallets use to identify the credential type.
- Completed the verification quickstart
- Access to the connector's configuration files
Overview
Type Metadata is a JSON document that describes a credential type. It tells the connector which claims to include in a credential and what display information to present to wallets. The connector loads Type Metadata from its configuration at startup and serves it at a public endpoint (/oidc4vci/types/{credential_configuration_id}) so wallets can discover supported credential types.
Type Metadata feeds into the connector's Credential Issuer Metadata—the credential_configurations_supported map that wallets read from GET /.well-known/openid-credential-issuer. Each entry in that map corresponds to a configured credential configuration. When you create a credential offer, the credential_configuration_id must match a key in this map.
Time to implement: 30 minutes.
Step 1: Define Type Metadata
Create a Type Metadata JSON document for your credential type. The document follows the SD-JWT VC draft-13 §6.3 array-form schema. The example below defines an Account Ownership Credential (AOC) with bank account claims and selective disclosure settings.
{
"vct": "https://issuer.example.com/oidc4vci/types/AccountOwnershipCredential",
"display": [
{ "lang": "en-US", "name": "Account Ownership Credential" }
],
"claims": [
{ "path": ["bankName"], "sd": "allowed", "display": [{ "lang": "en-US", "label": "Bank name" }] },
{ "path": ["accountHolder"], "sd": "allowed", "display": [{ "lang": "en-US", "label": "Account holder" }] },
{ "path": ["accountNumber"], "sd": "allowed", "display": [{ "lang": "en-US", "label": "Account number" }] },
{ "path": ["iban"], "sd": "allowed", "display": [{ "lang": "en-US", "label": "IBAN" }] },
{ "path": ["bic"], "sd": "allowed", "display": [{ "lang": "en-US", "label": "BIC" }] },
{ "path": ["currency"], "sd": "allowed", "display": [{ "lang": "en-US", "label": "Currency" }] },
{ "path": ["accountType"], "sd": "allowed", "display": [{ "lang": "en-US", "label": "Account type" }] }
]
}
Key fields:
vct—a VCT URI placeholder. Whenvct.sourceislocal, the connector rewrites this field to{base_url}/oidc4vci/types/{credential_configuration_id}at startup, making the Type Metadata available at a publicly resolvable URL. You can set any value here—the connector overrides it.display—an array of localized display entries for the credential type. Each entry requireslang(a BCP47 language tag) andname(the display name wallets show for this credential). The connector uses this array in the Credential Issuer Metadata.claims—an array of claim definitions. Each entry contains:path—a JSON pointer array identifying the claim (for example,["iban"]for a top-level claim, or["address", "street"]for a nested claim).sd—the selective disclosure policy:"allowed"(wallet holder can choose to disclose),"always"(always disclosed), or"never"(never selectively disclosable).display—an array of localized display entries withlangandlabelthat wallets show as the human-readable claim name.
When vct.source is local, the connector automatically generates the public VCT URL from its base_url and the credential configuration ID. You don't need to configure a separate VCT hosting endpoint. When vct.source is external, you provide the URL directly and are responsible for hosting the Type Metadata at that URL. For external sources, the connector injects a default display entry with lang: "en-US" and name set to the credential configuration ID if the display array is missing.
Step 2: Load Type Metadata into the connector
The connector loads Type Metadata from its configuration at startup. Each credential configuration references a Type Metadata JSON file via the credential_configurations configuration section.
# Configure a credential type with a local Type Metadata file
export CONNECTOR_CREDENTIAL_CONFIGURATIONS_ACCOUNTOWNERSHIPCREDENTIAL_VCT_SOURCE=local
export CONNECTOR_CREDENTIAL_CONFIGURATIONS_ACCOUNTOWNERSHIPCREDENTIAL_VCT_FILEPATH=/config/type-metadata/aoc.json
export CONNECTOR_CREDENTIAL_CONFIGURATIONS_ACCOUNTOWNERSHIPCREDENTIAL_SCOPE=aoc_credential
Each credential configuration requires:
vct.source—how the Type Metadata is loaded. Uselocalfor a file on disk (the connector serves it at{base_url}/oidc4vci/types/{config_id}), orexternalfor a URL that wallets resolve directly.vct.filepath—path to the Type Metadata JSON file (required whensourceislocal).vct.url—the external VCT URL (required whensourceisexternal). You are responsible for hosting the Type Metadata at this URL.scope—the OAuth 2.0 scope associated with this credential type.
The credential configuration key (for example, AccountOwnershipCredential in CONNECTOR_CREDENTIAL_CONFIGURATIONS_ACCOUNTOWNERSHIPCREDENTIAL_*) becomes the credential_configuration_id you pass when creating offers. The environment variable uses an uppercase representation of the key, but the actual credential_configuration_id preserves the original casing.
For Kubernetes deployments, store Type Metadata as a ConfigMap and mount it into the connector pod:
spec:
containers:
- name: connector
env:
- name: CONNECTOR_CREDENTIAL_CONFIGURATIONS_ACCOUNTOWNERSHIPCREDENTIAL_VCT_SOURCE
value: local
- name: CONNECTOR_CREDENTIAL_CONFIGURATIONS_ACCOUNTOWNERSHIPCREDENTIAL_VCT_FILEPATH
value: /config/type-metadata/aoc.json
- name: CONNECTOR_CREDENTIAL_CONFIGURATIONS_ACCOUNTOWNERSHIPCREDENTIAL_SCOPE
value: aoc_credential
volumeMounts:
- name: type-metadata
mountPath: /config/type-metadata/
readOnly: true
volumes:
- name: type-metadata
configMap:
name: connector-type-metadata
The connector serves the loaded Type Metadata at a public endpoint. Wallets discover available credential types through the Credential Issuer Metadata endpoint.
Step 3: Verify the configuration
After starting the connector with your Type Metadata, verify that the credential type appears in the Credential Issuer Metadata.
- cURL
curl -s https://connector.example.com/.well-known/openid-credential-issuer | jq .
The response should include your credential type in the credential_configurations_supported map:
{
"credential_issuer": "https://connector.example.com",
"authorization_servers": ["https://auth.example.com"],
"credential_endpoint": "https://connector.example.com/oidc4vci/credential",
"nonce_endpoint": "https://connector.example.com/oidc4vci/nonce",
"credential_configurations_supported": {
"AccountOwnershipCredential": {
"format": "dc+sd-jwt",
"scope": "aoc_credential",
"vct": "https://connector.example.com/oidc4vci/types/AccountOwnershipCredential",
"cryptographic_binding_methods_supported": ["jwk"],
"credential_signing_alg_values_supported": ["ES256"],
"proof_types_supported": {
"jwt": {
"proof_signing_alg_values_supported": ["ES256"]
}
},
"credential_metadata": {
"display": [
{
"name": "Account Ownership Credential",
"locale": "en-US"
}
],
"claims": [
{ "path": ["bankName"], "display": [{ "name": "Bank name", "locale": "en-US" }] },
{ "path": ["accountHolder"], "display": [{ "name": "Account holder", "locale": "en-US" }] },
{ "path": ["accountNumber"], "display": [{ "name": "Account number", "locale": "en-US" }] },
{ "path": ["iban"], "display": [{ "name": "IBAN", "locale": "en-US" }] },
{ "path": ["bic"], "display": [{ "name": "BIC", "locale": "en-US" }] },
{ "path": ["currency"], "display": [{ "name": "Currency", "locale": "en-US" }] },
{ "path": ["accountType"], "display": [{ "name": "Account type", "locale": "en-US" }] }
]
}
}
},
"signed_metadata": "<JWS signed with access certificate private key>"
}
Confirm that:
- Your credential configuration key (for example,
AccountOwnershipCredential) appears as a key incredential_configurations_supported. - The
vctvalue matches{base_url}/oidc4vci/types/{credential_configuration_id}(for local source) or your external URL. - The
credential_metadata.displayarray reflects thedisplayentries from your Type Metadata document. - The
credential_metadata.claimsarray includes your configured claims withpatharrays. - The
scopefield matches the scope you configured.
Testing
Test checklist
- Credential Issuer Metadata endpoint (
GET /.well-known/openid-credential-issuer) returns a response -
credential_configurations_supportedcontains your credential configuration key - The
vctfield is{base_url}/oidc4vci/types/{credential_configuration_id}(for local source) - The
formatfield isdc+sd-jwt - The
scopefield matches your configured scope -
credential_metadata.displayincludes your credential type display entries withnameandlocale -
credential_metadata.claimsincludes your claims withpatharrays -
proof_types_supportedincludesjwtwithES256 -
cryptographic_binding_methods_supportedincludesjwk - The Type Metadata endpoint (
GET /oidc4vci/types/{credential_configuration_id}) returns your JSON document with array-formdisplayandclaims - Creating a credential offer with the configured
credential_configuration_idsucceeds
Troubleshooting
unknown_credential_configuration error when creating an offer
The credential_configuration_id in your offer request doesn't match any configured credential type. Verify that:
- The credential configuration key in your environment variables matches the
credential_configuration_idyou use in the offer request (for example,CONNECTOR_CREDENTIAL_CONFIGURATIONS_ACCOUNTOWNERSHIPCREDENTIAL_*maps tocredential_configuration_id: "AccountOwnershipCredential"). - The Type Metadata path in
CONNECTOR_CREDENTIAL_CONFIGURATIONS_<ID>_VCT_FILEPATHpoints to a valid JSON file. - The connector restarted after you added or modified credential configuration environment variables.
VCT URI not publicly resolvable
Wallets fetch the vct URI to retrieve credential type metadata. When using vct.source=local, the connector serves the Type Metadata at {base_url}/oidc4vci/types/{credential_configuration_id}—ensure your base_url is publicly reachable. When using vct.source=external:
- Verify the URI is accessible from the public internet (not just your internal network).
- Check that the domain has valid DNS records and TLS certificates.
- Ensure no firewall rules block external access to the URI.
Missing required fields in Type Metadata
The connector validates Type Metadata at startup. If the connector fails to start after adding a Type Metadata file, check the logs for validation errors. Common issues:
- Missing or unreadable file—the path in
CONNECTOR_CREDENTIAL_CONFIGURATIONS_<ID>_VCT_FILEPATHmust point to a valid JSON file. - Invalid JSON—the file must be valid JSON that can be parsed.
- Missing
vct.source—each credential configuration must specify eitherlocalorexternalas the source type. - Missing
vct.filepath—required whenvct.sourceislocal. - Missing or empty
displayarray—Type Metadata requires at least one display entry withlangandname. - Invalid
claimsformat—claimsmust be an array of objects withpath(non-empty array),sd, and optionaldisplay. The legacy object-keyed format is no longer accepted.
Next steps
- Issue a credential—use the configured credential type to issue credentials
- Build an AOC issuance flow—end-to-end tutorial using AOC Type Metadata
Further reading
- OID4VCI protocol—how the issuance protocol uses credential type metadata
- Connector architecture—system components and configuration model
- Manage certificates—configure the Issuer Signing Certificate required for credential signing