Skip to main content

Approve a Transaction

Last updated on Apr 10, 2026 at 10:35 PM

This section explains how ImPAI handles approval of transactions that require manual authorization under the Four-Eyes Principle. The approval step is part of the platform’s compliance and risk-control framework and is triggered whenever a message enters the Approval Pending state during processing.

The following message categories may require approval, depending on configuration and workflow rules:

  • Payment Instruction  – a newly submitted outgoing credit transfer.

  • Recall  – a request to undo a previously sent payment.

  • Return  – a financial return initiated by a receiving bank.

  • Resolution  – a response to a previously issued recall.

Each approval operation follows a standardized pattern:
an authorized user (checker) submits a decision to either approve or reject the pending transaction, after which ImPAI validates the request, applies business rules, records the action, and forwards the workflow to the next appropriate state.

All approval requests are processed through a single, unified approval endpoint, regardless of the underlying message category. Below you will find this endpoint, along with its required request fields and response formats.


Common Approval Pattern​

Although each transaction category (Instruction, Recall, Return, Resolution) uses different transaction types, the approval always follows a similar model:

β‘  Identify the transaction​

Each approval request includes one or more identifiers that uniquely reference the message to be approved or rejected.
Commonly this is an internal ID created by ImPAI (for example the Global Id / Internal Id) and may be accompanied by other message-specific identifiers.

β‘‘ Decide on an action​

The approval request carries the decision:

  • approve – release the transaction for further processing and execution
  • reject – stop processing and record the rejection reason

For rejections, a reason text is typically required to support audit and investigation.

β‘’ System behaviour​

For all four message types, the approval services:

  • Validate that the transaction is still in a state where it can be approved or rejected.
  • Check that the caller is properly authenticated and authorized.
  • Update the transaction state to Approved or Rejected.
  • Write audit information (who approved/rejected, when, and why).
  • Trigger any follow-up processing (e.g. forwarding to clearing, status updates, or closing workflows).

1️⃣ Transaction Approval​

The Approval API is to be used for

  • Payment Instructions (ISO 20022 pain.001 β†’ pacs.008) when an initiated SEPA Instant payment requires manual release under Four-Eyes control.
  • Recalls when a previously sent SEPA Instant payment has been recalled (ISO 20022 camt.056) and that recall operation itself requires authorization.
  • Returns when a payment is being sent back (ISO 20022 pacs.004) and this operation must be confirmed by an authorized user.
  • Resolutions when a resolution message (ISO 20022 camt.029) is sent in response to a recall or investigation and requires an explicit decision.
Request Structure

Inside the approvalRequest group the following data has to be provided.

❢  identifiers

The identifiers section provides references to the message that requires approval:

FieldTypeRequiredDescriptionConstraints
internalIdStringYesInternal identifier of the SCT_INST message to be processed. Must reference a previously created instruction, recall, return, or resolution message.1-36 chars, e.g. PAI1500002433134

❷  approvalDetails

The approvalDetails section specifies the action to be taken and optional rejection reasoning:

FieldTypeRequiredDescriptionConstraints
actionStringYesThe action to be performed on the message.Enum:
approve
reject
rejectReasonStringNoReason for rejection. Required only when action is reject.Max 512 chars, e.g. "Suspicious transaction pattern"
Response Structure
🟒 Success β€” HTTP 200

Approval or rejection was accepted by the system and its state updated. The HTTP 200 – OK response may include updated identifiers and/or a pain.002 status message.

This returns a response with the following structure:

GroupDescription
headerResponse metadata containing responseId, originalRequestId, responseTime
messageAn object holding an ISO 20022 pain.002 message structure in Document.CstmrPmtStsRpt
successResponse body for successful processing with status and transactionid
identifiersInternal transaction identifiers containing fields for creditId and instructionId

Example(s)

{
"header": { "responseId": "0000", "originalRequestId": "ReqId-Example", "responseTime": "2025-01-01T00:00:00Z" },
"error": { "code": "VALIDATION_ERROR", "message": "Invalid request" },
"context": { "traceId": "..." }
}
πŸ”΄ Error β€” HTTP 400

In case of a validation or logical error (e.g. wrong state, missing fields), the API responds with the following structure for HTTP 400 – Bad Request errors:

GroupDescription
headerResponse metadata containing responseId, originalRequestId, responseTime
messageAn object holding an ISO 20022 pain.002 message structure in Document.CstmrPmtStsRpt
errorStructured error with code and message
fieldsAn array listing field-level issues (fieldMap, reasonCode, reasonText)
identifiersInternal transaction identifiers containing fields for creditId and instructionId

Example(s)

Error with ISO Message:

{
"header": {
"responseId": "603027ad-1047-43a3-b89b-03ff75fc8af9",
"originalRequestId": "ReqId-833583220015",
"responseTime": "2025-06-02T14:15:22Z"
},
"message": {
"Document": {
"CstmrPmtStsRpt": {
"GrpHdr": {
"MsgId": "PAI0500000018109",
"CreDtTm": "2025-04-30T17:30:29.587379623+02:00"
},
"OrgnlGrpInfAndSts": {
"OrgnlMsgId": "MSG-456312",
"OrgnlMsgNmId": "pain.001.01.09",
"OrgnlNbOfTxs": "1",
"OrgnlCtrlSum": 1006.87,
"GrpSts": "RJCT",
"StsRsnInf": [
// ... rejection reason information
]
}
}
}
},
"identifiers": {
"creditId": "PAI1500000018805",
"instructionId": "PAI1500000019002"
}
}

Timeout Error:

{
"header": {
"responseId": "603027ad-1047-43a3-b89b-03ff75fc8af9",
"originalRequestId": "ReqId-833583220015",
"responseTime": "2025-06-02T14:15:22Z"
},
"error": {
"message": "Timeout while waiting for response"
}
}

Field Validation Error:

{
"header": {
"responseId": "603027ad-1047-43a3-b89b-03ff75fc8af9",
"originalRequestId": "ReqId-833583220015",
"responseTime": "2025-06-02T14:15:22Z"
},
"fields": [
{
"fieldMap": "/Document/CstmrCdtTrfInitn/PmtInf/0/CdtTrfTxInf/0/UltmtCdtr/Id/OrgId",
"reasonCode": "FF01",
"reasonText": "expected string, but got object"
}
]
}
🟑 Error β€” HTTP 500

Responses for HTTP 500 β€” Server Error errors are returned on unexpected server-side failures and contain:

GroupDescription
errorCodeApplication-level error identifier (e.g. 500_INTERNAL_ERROR)
messageBrief description such as "Time-out" or "Something went wrong"

Example(s)

{
"errorCode": "500_INTERNAL_ERROR",
"message": "Something went wrong"
}

Summary β€” Approving Messages​

All approval operations for Instruction, Recall, Return, and Resolution messages are handled through a single unified approval endpoint.

Regardless of the underlying message category, the same Four-Eyes approval pattern applies:

identify the transaction β†’ decide (approve/reject) β†’ system validates, updates state, and logs the action.

The unified endpoint provides:

  • A consistent URL and technical interface for all approval use cases,
  • Message-type-specific handling based on supplied identifiers and workflow context,
  • A uniform response structure and HTTP status model across all categories.

While the business context differs per message type, the approval mechanism itself remains standardized, predictable, and audit-compliant.