Skip to main content

Transaction Authorization

Use Procivis One to make authorization requests with transaction data. This is represented by transaction_data in OpenID4VP.

Overview

Procivis One acts as a generic verifier for transaction data requests made over OpenID4VP. Given the transaction details you provide, it builds a request the holder's wallet can render and understand, then confirms cryptographically that the holder reviewed and approved that exact request using a valid credential.

You don't need to manage the underlying OpenID4VP mechanics yourself: Procivis One derives the protocol's credential_ids from your own schema references, and always requires cryptographic holder binding on any credential used to approve a transaction — you don't need to request or configure either explicitly.

The proof result confirms that a specific, valid credential was presented and that its holder approved this transaction. Creating the signature itself — for example, requesting a QES from your signing provider — happens with your own systems afterward, using the proof result as authorization.

Prerequisites

At least one instance of transactionDataProvider must be configured. See Configuring OpenID4VP - Transaction data for how to configure one.

To see what is available to you, request your configuration and check each instance's capabilities:

  • transactionDataTypes lists which types it can produce.
  • formats lists supported credential formats.
  • features lists behavioral capabilities. If SUPPORTS_MULTIPLE_TX_DATA_PER_PRESENTATION is present, a single credential can authorize more than one transactionData entry of that type in the same request. If absent (as with QES_APPROVAL), a request with multiple entries of that type needs enough distinct eligible credentials in your proof schema for the holder to satisfy every entry separately.

The instance's name in the configuration is the value to use for type when creating a proof request.

Making a Request

To request transaction authorization, include a transactionData array when creating a proof request.

POST /api/proof-request/v1
Content-Type: application/json
Accept: application/json
Authorization: Bearer <TOKEN>
{
"proofSchemaId": "{{UUID}}",
"protocol": "OPENID4VP_FINAL1",
"transactionData": [
{
"type": "QES_APPROVAL",
"credentialSchemaIds": [
"{{UUID}}"
],
"data": {
"numSignatures": 1,
"signatureQualifier": "eu_eidas_qes",
"hashAlgorithmOID": "2.16.840.1.101.3.4.2.1",
"documentInfos": [
{
"label": "Example Contract",
"hash": "sTOgwOm+474gFj0q0x1iSNspKqbcse4IeiqlDg/HWuI=",
"hashType": "sodr"
}
]
}
}
],
"transport": [
"HTTP"
],
"verifier": "{{IDENTIFIER-UUID}}"
}
  • type — This must reference a configured instance of transactionDataProvider.
  • credentialSchemaIds — Reference your own (Procivis One) schema definitions for the credentials that may approve this transaction. The system resolves these into the credential_ids values sent to the wallet. This is distinct from the opaque, per-query credential_ids defined by OpenID4VP/CSC itself, which the wallet and holder never see under this name.
  • data — Transaction data for the provider referenced in type. Scoped per type — see Transaction types. Its shape varies significantly by type: some types pass CSC-defined fields through nearly as-is, while others accept a Procivis-defined request shape that's mapped onto a different wire format internally.

Transaction types

QES Approval

For QES_APPROVAL type transactions, data follows the CSC qesApprovalRequest structure (CSC data model bindings §7.1), minus type and credential_ids, which Procivis One adds automatically.

FieldPresenceDescription
hashAlgorithmOIDRequiredHash algorithm (OID) for document hashes and the SD-JWT VC approval binding. mdoc credentials always use SHA-256 regardless of this setting.
numSignaturesRequiredNumber of signatures being approved.
documentInfosRequiredOne entry per document; see below.
credentialID / signatureQualifierConditionalAt least one is required, identifying the certificate or certificate class.
locationsOptionalRSSP locations (RFC 9396).

Documents and hashType

Each documentInfos entry requires a hash: a standard base64-encoded, padded hash of the document, computed by the caller. Do not use base64url encoding. Procivis One does not fetch or hash document content; it only handles the hash values you provide.

hashType indicates what was actually hashed:

  • sodr — hash of the original document, before any signature-related formatting.
  • sdr — hash of the document after formatting (for example, a PDF with the signature dictionary already inserted, but not yet signed).
  • dtbsr — (default if hashType is omitted) hash of the data actually submitted to the signature algorithm.

sdr and dtbsr depend on signature-format and RSSP-specific formatting rules. sodr is the simplest choice for testing.

Other optional fields (label, access, href, checksum) are passed through to the wallet for display and are not used in verification.

Supported values

hashAlgorithmOID and signatureQualifier are both closed sets, and any other value is rejected at validation time.

hashAlgorithmOID recognizes the following OIDs as well-formed values, but currently only supports SHA-256. Using non-supported OIDs results in rejection at validation.

AlgorithmOIDStatus
SHA-2562.16.840.1.101.3.4.2.1Supported
SHA-3842.16.840.1.101.3.4.2.2Not supported
SHA-5122.16.840.1.101.3.4.2.3Not supported

signatureQualifier accepts: eu_eidas_aes, eu_eidas_qes, eu_eidas_aeseal, eu_eidas_qeseal, eu_eidas_aesqc, eu_eidas_aesealqc, za_ecta_aes, za_ecta_oes.

Shared objects

The following object types recur across the SCA (Strong Customer Authentication) transaction types below. Unlike QES_APPROVAL, data for these types uses Procivis-defined camelCase field names — not the snake_case wire format defined by TS12 itself. All SCA types support SD-JWT VC only; there is no mdoc encoding defined for them.

Payee

FieldPresenceDescription
nameRequiredPayee name.
idRequiredPayee identifier.
logoOptionalString.
websiteOptionalString.

TPP (Third Party Provider) — used as pisp (Payment Initiation Service Provider) on Payment Confirmation, and aisp (Account Information Service Provider) on Account Access.

FieldPresenceDescription
legalNameRequiredString.
brandNameRequiredString.
domainNameRequiredString.

Recurrence

FieldPresenceDescription
startDateOptionalString.
endDateOptionalString.
numberOptionalInteger.
frequencyRequiredISO 20022-style frequency code.
mitOptionsOptionalMIT (Merchant-Initiated Transaction) options; see below.

MitOptions — all fields optional.

FieldDescription
amountVariableBoolean.
minAmount / maxAmount / totalAmount / initialAmountNumbers.
initialAmountNumberInteger.
aprNumber.

Payment Confirmation

For SCA_PAYMENT_CONFIRMATION type transactions (urn:eudi:sca:payment:1), data accepts:

FieldPresenceDescription
transactionIdRequiredString.
dateTimeOptionalString.
payeeRequiredPayee object.
pispOptionalTPP object.
executionDateOptionalString date. Must not be in the past, allowing for the provider's configured leewaySeconds. Mutually exclusive with recurrence.
currencyRequiredString.
amountRequiredNumber.
amountEstimatedOptionalBoolean.
amountEarmarkedOptionalBoolean.
sctInstOptionalBoolean — whether this uses the SEPA Instant Credit Transfer scheme.
recurrenceOptionalRecurrence object. Mutually exclusive with executionDate.

Login and Risk-Based Authentication

For SCA_LOGIN_RISK_TRANSACTION type transactions (urn:eudi:sca:login_risk_transaction:1), data accepts:

FieldPresenceDescription
transactionIdRequiredString.
dateTimeOptionalString.
serviceOptionalString.
actionRequiredString.

Account Access

For SCA_ACCOUNT_ACCESS type transactions (urn:eudi:sca:account_access:1), data accepts:

FieldPresenceDescription
transactionIdRequiredString.
dateTimeOptionalString.
aispOptionalTPP object.
descriptionOptionalString.

E-mandate

For SCA_EMANDATE type transactions (urn:eudi:sca:emandate:1), data accepts:

FieldPresenceDescription
transactionIdRequiredString.
dateTimeOptionalString.
startDateOptionalString.
endDateOptionalString.
referenceNumberOptionalString.
creditorIdOptionalString.
purposeConditionalString describing what's being mandated.
paymentPayloadConditionalA full Payment Confirmation object, nested.

At least one of purpose or paymentPayload is required — the holder must be told what they're mandating, either in words or via the payment itself. If paymentPayload is present, its own executionDate / recurrence rules apply exactly as described under Payment Confirmation.

What happens after the request is created

Creating the proof request assembles and sends the transaction data, and the approval happens through the normal OpenID4VP presentation exchange:

  1. Procivis One assembles and validates the request. It takes your data object, adds type (the CSC transaction data type identifier) and credential_ids (derived from credentialSchemaIds), and encodes the result as the transaction_data value in the OpenID4VP authorization request sent to the holder's wallet. Before doing so, the responsible provider checks that the object is well-formed according to the specification it implements — for QES_APPROVAL, this includes confirming hashAlgorithmOID refers to a supported algorithm and that either credentialID or signatureQualifier is present. If validation fails, creating the proof request fails outright — an invalid transaction data object is never sent to the wallet. No hashing of document content happens at this stage; any document hashes in documentInfos must already be set on the way in.

  2. The wallet renders the request to the holder. The wallet displays the document labels and other details so the holder can review exactly what they're being asked to approve before presenting a credential.

  3. The holder approves, and the wallet binds the approval to the credential. The wallet hashes the transaction data it received and embeds the result in the presentation using that credential format's native holder binding: a claim in the Key Binding JWT for SD-JWT VC, or a signed data element for mdoc. This cryptographically ties this credential to this transaction document.

  4. Procivis One verifies the presentation. It recomputes the expected hash from the original transaction data using the same format-specific method, and compares it against what the wallet returned. A mismatch, or a credential that doesn't satisfy the request's schema and validity checks, results in the presentation being rejected.

  5. The result is available to you. Procivis One does not create the actual signature — you use the proof result as authorization to proceed with the transaction (for example, requesting the QES from your RSSP) off-platform.

    To retrieve the result:

    • Poll GET /api/proof-request/v1/{id} and check state for ACCEPTED.
    • Subscribe to a webhook instead of polling. See Webhooks for instructions on setting up webhooks for verification notices.