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:
transactionDataTypeslists which types it can produce.formatslists supported credential formats.featureslists behavioral capabilities. IfSUPPORTS_MULTIPLE_TX_DATA_PER_PRESENTATIONis present, a single credential can authorize more than onetransactionDataentry of that type in the same request. If absent (as withQES_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 oftransactionDataProvider.credentialSchemaIds— Reference your own (Procivis One) schema definitions for the credentials that may approve this transaction. The system resolves these into thecredential_idsvalues sent to the wallet. This is distinct from the opaque, per-querycredential_idsdefined by OpenID4VP/CSC itself, which the wallet and holder never see under this name.data— Transaction data for the provider referenced intype. 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.
| Field | Presence | Description |
|---|---|---|
hashAlgorithmOID | Required | Hash algorithm (OID) for document hashes and the SD-JWT VC approval binding. mdoc credentials always use SHA-256 regardless of this setting. |
numSignatures | Required | Number of signatures being approved. |
documentInfos | Required | One entry per document; see below. |
credentialID / signatureQualifier | Conditional | At least one is required, identifying the certificate or certificate class. |
locations | Optional | RSSP 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 ifhashTypeis 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.
| Algorithm | OID | Status |
|---|---|---|
| SHA-256 | 2.16.840.1.101.3.4.2.1 | Supported |
| SHA-384 | 2.16.840.1.101.3.4.2.2 | Not supported |
| SHA-512 | 2.16.840.1.101.3.4.2.3 | Not 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
| Field | Presence | Description |
|---|---|---|
name | Required | Payee name. |
id | Required | Payee identifier. |
logo | Optional | String. |
website | Optional | String. |
TPP (Third Party Provider) — used as pisp (Payment Initiation
Service Provider) on Payment Confirmation, and aisp (Account
Information Service Provider) on Account Access.
| Field | Presence | Description |
|---|---|---|
legalName | Required | String. |
brandName | Required | String. |
domainName | Required | String. |
Recurrence
| Field | Presence | Description |
|---|---|---|
startDate | Optional | String. |
endDate | Optional | String. |
number | Optional | Integer. |
frequency | Required | ISO 20022-style frequency code. |
mitOptions | Optional | MIT (Merchant-Initiated Transaction) options; see below. |
MitOptions — all fields optional.
| Field | Description |
|---|---|
amountVariable | Boolean. |
minAmount / maxAmount / totalAmount / initialAmount | Numbers. |
initialAmountNumber | Integer. |
apr | Number. |
Payment Confirmation
For SCA_PAYMENT_CONFIRMATION type transactions (urn:eudi:sca:payment:1),
data accepts:
| Field | Presence | Description |
|---|---|---|
transactionId | Required | String. |
dateTime | Optional | String. |
payee | Required | Payee object. |
pisp | Optional | TPP object. |
executionDate | Optional | String date. Must not be in the past, allowing for the provider's configured leewaySeconds. Mutually exclusive with recurrence. |
currency | Required | String. |
amount | Required | Number. |
amountEstimated | Optional | Boolean. |
amountEarmarked | Optional | Boolean. |
sctInst | Optional | Boolean — whether this uses the SEPA Instant Credit Transfer scheme. |
recurrence | Optional | Recurrence 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:
| Field | Presence | Description |
|---|---|---|
transactionId | Required | String. |
dateTime | Optional | String. |
service | Optional | String. |
action | Required | String. |
Account Access
For SCA_ACCOUNT_ACCESS type transactions
(urn:eudi:sca:account_access:1), data accepts:
| Field | Presence | Description |
|---|---|---|
transactionId | Required | String. |
dateTime | Optional | String. |
aisp | Optional | TPP object. |
description | Optional | String. |
E-mandate
For SCA_EMANDATE type transactions (urn:eudi:sca:emandate:1), data
accepts:
| Field | Presence | Description |
|---|---|---|
transactionId | Required | String. |
dateTime | Optional | String. |
startDate | Optional | String. |
endDate | Optional | String. |
referenceNumber | Optional | String. |
creditorId | Optional | String. |
purpose | Conditional | String describing what's being mandated. |
paymentPayload | Conditional | A 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:
-
Procivis One assembles and validates the request. It takes your
dataobject, addstype(the CSC transaction data type identifier) andcredential_ids(derived fromcredentialSchemaIds), and encodes the result as thetransaction_datavalue 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 — forQES_APPROVAL, this includes confirminghashAlgorithmOIDrefers to a supported algorithm and that eithercredentialIDorsignatureQualifieris 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 indocumentInfosmust already be set on the way in. -
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.
-
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.
-
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.
-
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 checkstateforACCEPTED. - Subscribe to a webhook instead of polling. See Webhooks for instructions on setting up webhooks for verification notices.
- Poll