Transaction Data Profiles
transaction-data-profiles.conf defines the transaction data types your Enterprise Verifier2 and Wallet2 services recognize for
OpenID4VP transaction_data requests.
The transaction-data-profiles feature is enabled by default in the Enterprise API.
Transaction data types act as namespaces that:
- Enforce which
transaction_data.typevalues Verifier2 accepts and Wallet2 will present - Define the fields exposed by the Verifier2 and Wallet2 transaction-data discovery endpoints
- Drive the Enterprise Verifier2 creation UI, which renders transaction-data inputs from these profiles
- Define the DeviceSigned namespace used for
mso_mdoctransaction-data binding
mDoc issuance grant: For mso_mdoc credentials, registering a type here is not enough for the holder to device-sign it. The credential's MSO must authorize that type via KeyAuthorizations, which Issuer2 sets from the profile field authorizedTransactionDataTypes. SD-JWT VC presentations bind transaction data in the KB-JWT and do not use that field.
File Location
The Enterprise Stack reads this configuration from:
waltid-enterprise-api/config/transaction-data-profiles.conf
Fields
transactionDataProfiles
Array of Objects — List of recognized transaction data types. Each profile defines:
| Field | Type | Description |
|---|---|---|
type | String | Required. The transaction data type identifier. Used as the type field in transaction data entries and as the namespace for mso_mdoc DeviceSigned binding. Example: "org.waltid.transaction-data.payment-authorization" |
displayName | String | Human-readable name for this type. Used in the Enterprise Verifier2 UI and discovery endpoint responses. Defaults to type if not specified. |
fields | Array | List of field names expected for this type. Used for UI generation and documentation. Nested payloads (e.g. SCA) can declare a single container field such as ["payload"]. Example: ["amount", "currency", "payee"] |
Built-in Profiles
The default Enterprise configuration includes:
transactionDataProfiles = [
{
type = "org.waltid.transaction-data.payment-authorization"
displayName = "Payment Authorization"
fields = ["amount", "currency", "payee"]
},
{
type = "org.waltid.transaction-data.account-access"
displayName = "Account Access"
fields = ["account_identifier", "access_scope"]
},
{
# EUDI TS-12 SCA payment type. Payload nests, so the matcher reads
# payload.payee.name, payload.currency and payload.amount rather than flat fields.
type = "urn:eudi:sca:payment:1"
displayName = "SCA Payment"
fields = ["payload"]
},
{
# Interop identifier used by some OpenID4VP payment-card verifiers. Prefer a
# collision-resistant type for new deployments.
type = "payment_card"
displayName = "Payment Card"
fields = ["merchant_name", "amount"]
}
]
| Type | Shape | Notes |
|---|---|---|
org.waltid.transaction-data.payment-authorization | Flat fields | walt.id payment demo type |
org.waltid.transaction-data.account-access | Flat fields | Account access demo type |
urn:eudi:sca:payment:1 | Nested payload | EUDI TS-12 SCA payment; amount is a JSON number inside payload |
payment_card | Flat merchant_name, amount | Interop identifier used by some OpenID4VP payment-card verifiers. Prefer a collision-resistant type for new deployments. amount may be a combined string such as "EUR 200.00". |
Runtime CRUD
HOCON is the durable default. Each Wallet2 and Verifier2 service also stores a runtime overlay on the service document. Overlay entries win by type. Deleting a seeded type hides it on that service until it is created again. Overlay changes apply immediately and do not require a restart. Updating service configuration does not wipe the overlay.
Types such as org.waltid.transaction-data.payment-authorization contain dots, so overlays are stored on the service document rather than as Mongo child targets. Isolate profiles per service: creating a type on one Wallet2 or Verifier2 does not change another.
| Method | Path | Permission |
|---|---|---|
GET | /v2/{target}/wallet-service-api/transaction-data-profiles | ES_WALLET_PRESENT_CREDENTIALS_FULL or ES_WALLET_ISOLATED_PRESENT_CREDENTIALS |
GET | /v2/{target}/wallet-service-api/transaction-data-profiles/{type} | same as list |
POST | /v2/{target}/wallet-service-api/transaction-data-profiles | UPDATE_SERVICE_CONFIGURATION |
PUT | /v2/{target}/wallet-service-api/transaction-data-profiles/{type} | UPDATE_SERVICE_CONFIGURATION |
DELETE | /v2/{target}/wallet-service-api/transaction-data-profiles/{type} | UPDATE_SERVICE_CONFIGURATION |
GET | /v2/{target}/verifier-service-api/transaction-data-profiles | CREATE_VERIFIER_SESSION |
GET | /v2/{target}/verifier-service-api/transaction-data-profiles/{type} | CREATE_VERIFIER_SESSION |
POST | /v2/{target}/verifier-service-api/transaction-data-profiles | UPDATE_SERVICE_CONFIGURATION |
PUT | /v2/{target}/verifier-service-api/transaction-data-profiles/{type} | UPDATE_SERVICE_CONFIGURATION |
DELETE | /v2/{target}/verifier-service-api/transaction-data-profiles/{type} | UPDATE_SERVICE_CONFIGURATION |
Encode {type} in the path when it contains reserved characters. Enterprise Verifier2 session create rejects transaction_data.type values that are not in that verifier's effective registry (HOCON seed plus that service's overlay). Community Verifier2 does not apply this allowlist.
Discovery Endpoints
Enterprise Verifier2 exposes the configured profiles at:
GET /v2/{target}/verifier-service-api/transaction-data-profiles
This endpoint requires the CREATE_VERIFIER_SESSION permission on the Verifier2 service target.
Enterprise Wallet2 exposes the same configured profiles at:
GET /v2/{target}/wallet-service-api/transaction-data-profiles
This endpoint requires ES_WALLET_PRESENT_CREDENTIALS_FULL or ES_WALLET_ISOLATED_PRESENT_CREDENTIALS on the Wallet2 service target.
Adding Custom Types
To add a custom transaction data type without restarting:
POSTthe profile to the Wallet2 or Verifier2transaction-data-profilespath for that service- If your holders use a wallet you manage, add the same type there (HOCON seed or that wallet's overlay)
- For mDoc holders that must device-sign the type, also set
authorizedTransactionDataTypeson the Issuer2 credential profile
To make a type the durable default for every service, add it to transactionDataProfiles in waltid-enterprise-api/config/transaction-data-profiles.conf and restart the Enterprise API.
Example: Adding a subscription authorization type:
transactionDataProfiles = [
{
type = "org.waltid.transaction-data.payment-authorization"
displayName = "Payment Authorization"
fields = ["amount", "currency", "payee"]
},
{
type = "org.waltid.transaction-data.account-access"
displayName = "Account Access"
fields = ["account_identifier", "access_scope"]
},
{
type = "urn:eudi:sca:payment:1"
displayName = "SCA Payment"
fields = ["payload"]
},
{
type = "org.example.subscription-authorization"
displayName = "Subscription Authorization"
fields = ["service_name", "billing_cycle", "price"]
}
]
Only wallets that recognize the same transaction-data type identifiers can successfully present these requests. Keep your verifier and wallet type registries aligned.
Usage in Verification Requests
Once configured, use the profile type in the verification session request.
Flat walt.id payment type:
{
"flow_type": "cross_device",
"core_flow": {
"dcql_query": { "...": "..." }
},
"openid": {
"transactionData": [
{
"type": "org.waltid.transaction-data.payment-authorization",
"credential_ids": ["pid"],
"require_cryptographic_holder_binding": true,
"transaction_data_hashes_alg": ["sha-256"],
"amount": "42.00",
"currency": "EUR",
"payee": "ACME Corp"
}
]
}
}
Nested SCA payment type:
{
"openid": {
"transactionData": [
{
"type": "urn:eudi:sca:payment:1",
"credential_ids": ["sca_payment_card"],
"require_cryptographic_holder_binding": true,
"transaction_data_hashes_alg": ["sha-256"],
"payload": {
"transaction_id": "8D8AC610-566D-4EF0-9C22-186B2A5ED793",
"payee": {
"name": "Super Store",
"id": "merchant-001"
},
"currency": "EUR",
"amount": 11.56
}
}
]
}
}
See Transaction Data Authorization for request constraints and end-to-end examples.
