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.type values 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_mdoc transaction-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:

FieldTypeDescription
typeStringRequired. 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"
displayNameStringHuman-readable name for this type. Used in the Enterprise Verifier2 UI and discovery endpoint responses. Defaults to type if not specified.
fieldsArrayList 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:

transaction-data-profiles.conf
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"]
  }
]
TypeShapeNotes
org.waltid.transaction-data.payment-authorizationFlat fieldswalt.id payment demo type
org.waltid.transaction-data.account-accessFlat fieldsAccount access demo type
urn:eudi:sca:payment:1Nested payloadEUDI TS-12 SCA payment; amount is a JSON number inside payload
payment_cardFlat merchant_name, amountInterop 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.

MethodPathPermission
GET/v2/{target}/wallet-service-api/transaction-data-profilesES_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-profilesUPDATE_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-profilesCREATE_VERIFIER_SESSION
GET/v2/{target}/verifier-service-api/transaction-data-profiles/{type}CREATE_VERIFIER_SESSION
POST/v2/{target}/verifier-service-api/transaction-data-profilesUPDATE_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:

  1. POST the profile to the Wallet2 or Verifier2 transaction-data-profiles path for that service
  2. If your holders use a wallet you manage, add the same type there (HOCON seed or that wallet's overlay)
  3. For mDoc holders that must device-sign the type, also set authorizedTransactionDataTypes on 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:

transaction-data-profiles.conf
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.

Last updated on August 24, 2026