Approve a Transaction
This section explains how ImPAI handles approval of SEPA Instant (SCT Inst) 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.
Below you will find the dedicated approval endpoints for each message type, along with their required request fields and response formats.
Common Approval Patternβ
Although each message type (Instruction, Recall, Return, Resolution) has its own endpoint and may differ in details, they all follow a similar approval 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οΈβ£ Instruction Approvalβ
Approval of Payment Instructions (ISO 20022 pain.001 β pacs.008) is used when an initiated SEPA Instant payment requires manual release under Four-Eyes control.
Request Structure
βΆΒ Β identifiers
The identifiers section provides references to the message that requires approval:
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
internalId | String | Yes | Internal 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:
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
action | String | Yes | The action to be performed on the message. | Enum:approvereject |
rejectReason | String | No | Reason 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:
For Successful Approval/Rejection 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",
"DbtrAgt": {
"FinInstnId": {
// ... financial institution details
}
}
},
"OrgnlGrpInfAndSts": {
"OrgnlMsgId": "MSG-456312",
"OrgnlMsgNmId": "pain.001.01.09",
"OrgnlNbOfTxs": "1",
"OrgnlCtrlSum": 1006.87,
"GrpSts": "PNDG",
"StsRsnInf": [
// ... status reason information
]
},
"OrgnlPmtInfAndSts": [
// ... original payment information and status
]
}
}
},
"identifiers": {
"creditId": "PAI1500000018805",
"instructionId": "PAI1500000019002"
}
}
For Simple Success Response:
{
"header": {
"responseId": "603027ad-1047-43a3-b89b-03ff75fc8af9",
"originalRequestId": "ReqId-833583220015",
"responseTime": "2025-06-02T14:15:22Z"
},
"success": {
"status": "Success",
"transactionid": "PAI1500004121533"
}
}
π΄ 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:
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:
| Group | Description |
|---|---|
errorCode | Application-level error identifier (e.g. 500_INTERNAL_ERROR) |
message | Brief description such as "Time-out" or "Something went wrong" |
Example:
{
"errorCode": "500_INTERNAL_ERROR",
"message": "Something went wrong"
}
2οΈβ£ Recall Approvalβ
Approval of Recalls is used when a previously sent SEPA Instant payment has been recalled (ISO 20022 camt.056) and that recall operation itself requires authorization.
Request Structure
βΆΒ Β identifiers
The identifiers section provides references to the message that requires approval:
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
internalId | String | Yes | Internal 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:
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
action | String | Yes | The action to be performed on the message. | Enum:approvereject |
rejectReason | String | No | Reason 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:
For Successful Approval/Rejection 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",
"DbtrAgt": {
"FinInstnId": {
// ... financial institution details
}
}
},
"OrgnlGrpInfAndSts": {
"OrgnlMsgId": "MSG-456312",
"OrgnlMsgNmId": "pain.001.01.09",
"OrgnlNbOfTxs": "1",
"OrgnlCtrlSum": 1006.87,
"GrpSts": "PNDG",
"StsRsnInf": [
// ... status reason information
]
},
"OrgnlPmtInfAndSts": [
// ... original payment information and status
]
}
}
},
"identifiers": {
"creditId": "PAI1500000018805",
"instructionId": "PAI1500000019002"
}
}
For Simple Success Response:
{
"header": {
"responseId": "603027ad-1047-43a3-b89b-03ff75fc8af9",
"originalRequestId": "ReqId-833583220015",
"responseTime": "2025-06-02T14:15:22Z"
},
"success": {
"status": "Success",
"transactionid": "PAI1500004121533"
}
}
π΄ 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:
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:
| Group | Description |
|---|---|
errorCode | Application-level error identifier (e.g. 500_INTERNAL_ERROR) |
message | Brief description such as "Time-out" or "Something went wrong" |
Example:
{
"errorCode": "500_INTERNAL_ERROR",
"message": "Something went wrong"
}
3οΈβ£ Return Approvalβ
Approval of Returns is used when a payment is being sent back (ISO 20022 pacs.004) and this operation must be confirmed by an authorized user.
Request Structure
βΆΒ Β identifiers
The identifiers section provides references to the message that requires approval:
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
internalId | String | Yes | Internal 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:
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
action | String | Yes | The action to be performed on the message. | Enum:approvereject |
rejectReason | String | No | Reason 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:
For Successful Approval/Rejection 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",
"DbtrAgt": {
"FinInstnId": {
// ... financial institution details
}
}
},
"OrgnlGrpInfAndSts": {
"OrgnlMsgId": "MSG-456312",
"OrgnlMsgNmId": "pain.001.01.09",
"OrgnlNbOfTxs": "1",
"OrgnlCtrlSum": 1006.87,
"GrpSts": "PNDG",
"StsRsnInf": [
// ... status reason information
]
},
"OrgnlPmtInfAndSts": [
// ... original payment information and status
]
}
}
},
"identifiers": {
"creditId": "PAI1500000018805",
"instructionId": "PAI1500000019002"
}
}
For Simple Success Response:
{
"header": {
"responseId": "603027ad-1047-43a3-b89b-03ff75fc8af9",
"originalRequestId": "ReqId-833583220015",
"responseTime": "2025-06-02T14:15:22Z"
},
"success": {
"status": "Success",
"transactionid": "PAI1500004121533"
}
}
π΄ 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:
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:
| Group | Description |
|---|---|
errorCode | Application-level error identifier (e.g. 500_INTERNAL_ERROR) |
message | Brief description such as "Time-out" or "Something went wrong" |
Example:
{
"errorCode": "500_INTERNAL_ERROR",
"message": "Something went wrong"
}
4οΈβ£ Resolution Approvalβ
Approval of Resolutions is used when a resolution message (ISO 20022 camt.029) is sent in response to a recall or investigation and requires an explicit decision.
Request Structure
βΆΒ Β identifiers
The identifiers section provides references to the message that requires approval:
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
internalId | String | Yes | Internal 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:
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
action | String | Yes | The action to be performed on the message. | Enum:approvereject |
rejectReason | String | No | Reason 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:
For Successful Approval/Rejection 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",
"DbtrAgt": {
"FinInstnId": {
// ... financial institution details
}
}
},
"OrgnlGrpInfAndSts": {
"OrgnlMsgId": "MSG-456312",
"OrgnlMsgNmId": "pain.001.01.09",
"OrgnlNbOfTxs": "1",
"OrgnlCtrlSum": 1006.87,
"GrpSts": "PNDG",
"StsRsnInf": [
// ... status reason information
]
},
"OrgnlPmtInfAndSts": [
// ... original payment information and status
]
}
}
},
"identifiers": {
"creditId": "PAI1500000018805",
"instructionId": "PAI1500000019002"
}
}
For Simple Success Response:
{
"header": {
"responseId": "603027ad-1047-43a3-b89b-03ff75fc8af9",
"originalRequestId": "ReqId-833583220015",
"responseTime": "2025-06-02T14:15:22Z"
},
"success": {
"status": "Success",
"transactionid": "PAI1500004121533"
}
}
π΄ 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:
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:
| Group | Description |
|---|---|
errorCode | Application-level error identifier (e.g. 500_INTERNAL_ERROR) |
message | Brief description such as "Time-out" or "Something went wrong" |
Example:
{
"errorCode": "500_INTERNAL_ERROR",
"message": "Something went wrong"
}
Summary β Approving SCT Inst Messagesβ
All four approval endpoints (Instruction, Recall, Return, Resolution) implement the same Four-Eyes approval pattern:
identify the transaction β decide (approve/reject) β system validates, updates state, and logs.
Each endpoint has:
- Its own URL and use case,
- Possibly slightly different request fields or identifiers,
- The same high-level response/HTTP status patterns.