Payment validation

Configure payment validation rules to send or accept payments in Mambu Payments (formerly Numeral) based on your business requirements

Introduction

Payment validation is used to approve or reject payments before they are sent or when they are received. Common payment validations include checking:

  • The status of an internal account before confirming or rejecting a payment received
  • If a beneficiary is on a sanctions list before sending a payment
  • If a direct debit mandate is not blocked when receiving a direct debit payment
  • If a payment type and an amount are allowed for an internal account

Payment validation rules

Overview

Validations are managed via payment validation rules that group and orchestrate the execution of validations for a target payment flow (outgoing SCT Instant, incoming SDD, etc.)

Approval rules can be attached to:

  • Payment orders and outgoing returns, to decide whether the payment should be cancelled or approved
  • Incoming payments, to decide whether the payment should be rejected or accepted (possible statuses depend on the payment type, see Incoming payment lifecycle for more details)

A rule is defined by its:

  • Criteria, defining the payments this rule will apply to. Supported criteria are connected accounts, payment types, and directions
  • Validations which is the list of validations to be performed on these payments. Each validation has a list of possible outcomes mapped to different actions (move to next validation, cancel payment, etc.)

Example of a payment validation rule

Validations within a single step are executed in parallel. For a payment to advance or reach final approval, the system must receive successful results from all concurrent validations. However, if any single validation triggers a rejection or cancellation, that action is executed immediately, regardless of the status of other pending validations.

You can map specific rejection codes to individual validations. For instance, a "Sanctions Screening" failure can be configured to return code FRAD (fraud), while an "Internal Account" failure returns AC04 (closed Account). This allows for granular error reporting and automated downstream handling.

Validation rules can be configured with specific execution triggers. While validations typically run upon payment creation or following the previous step, you can delay them until the payment value date. This is particularly useful for incoming SEPA Direct Debits (SDD), which may arrive up to 14 days early. Delaying the check ensures that account status and liquidity validations are performed against real-time data on the actual collection date.

Case of incoming SCT Instant

In the case of incoming SCT Instant, you must provide an answer (positive or negative) in the 7 seconds following the payment initiation. To ensure full scheme compliance, Mambu Payments will automatically reject the payment after this period, even if all validations are not completed.

sequenceDiagram
participant S as Scheme
participant N as Mambu Payments
participant C as Customer
autonumber
S->>N: Forward incoming SCT Instant
N->>C: Trigger validation
alt Validation is shorter than 7 seconds
N->>S: Accept or reject payment
N-->>C: incoming_payment.rejected or confirmed
else Validation is longer than 7 seconds
N->>S: Reject payment with reason AB05
N-->>C: incoming_payment.rejected
end

Validations

Mambu Payments currently supports two types of validations:

  • Custom validations performed by your systems based on your internal logic and data providers
  • Pre-built validations performed on Mambu Payments objects and data, like internal accounts, direct debit mandates, external account reachability etc. which can be configured for your business needs

In any case, each validation object provides a detailed breakdown of an individual check. The schema includes:

  • Type: The specific category of the check (e.g., risk_screening)
  • Status: The current lifecycle state, such as queued, in_progress, pending_investigation, successful, failed, or canceled
  • Status details: Contextual information or error messages regarding the current status
  • Resource reference: A resource_id and resource_url linking to the underlying entity (e.g., a specific screening report or internal account)
  • Timestamps: A last_updated_at field to track the most recent activity

Asynchronous

Mambu Payments sends an event to your webhook when a validation in your system is required. The result of the validation can be shared using the dedicated API endpoint.

sequenceDiagram
    participant ThirdParty as Third-party service (e.g., ComplyAdvantage)
    participant Customer as Customer
    participant Numeral as Mambu Payments
		autonumber
    Customer->>Numeral: Create payment order
    activate Numeral
    Note over Numeral: Validate payload
    Numeral-->>Customer: payment_order.pending_approval event
    Note over Numeral: Initiate validation
    Numeral-->>Customer: payment_order.validation_updated event
    Note over Numeral: Wait for validation result

    Customer->>ThirdParty: Send validation request
    ThirdParty-->>Customer: Send validation result

    Customer->>Numeral: Update validation result<br/>POST /payment_order/{id}/payment_validation
    Note over Numeral: Finalise validation
    Numeral-->>Customer: payment_order.approved event
    deactivate Numeral

Call #6 will look like this:

curl --request POST \
     --url https://numeral.io/v1/payment_orders/{}/payment_validation \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "type": "sanctions_screening",
  "status": "successful",
  "payment_validation_rule_id": "6118aa97-a9bb-4af9-9c25-259349eff44c",
  "status_details": "No hit",
  "resource_id": "123ABC",
  "resource_url": "https://complyadvantage/my-cases/123ABC"
}
'

Learn more about these endpoints:

Synchronous

Mambu Payments calls an endpoint (in your system or in a third-party system). The result of the validation is shared as a response in the HTTP session.

sequenceDiagram
    participant Customer as Customer
    participant Numeral as Numeral

    Customer->>Numeral: Create payment order
    activate Numeral
    Note over Numeral: Validate payload
    Numeral-->>Customer: payment_order.pending_approval event

    Note over Numeral: Send validation request
    Numeral->>Customer: Request
    activate Customer
    Note over Numeral: Wait for response
    Customer-->>Numeral: Response
    deactivate Customer

    Note over Numeral: Finalise validation
    Numeral-->>Customer: payment_order.approved event
    deactivate Numeral
curl --request POST \
     --url https://your-system.com/sanction-screening \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
    "id": "e19aff61-53ce-4293-9a0a-6996d4995e18",
    "object": "payment_order",
    // The whole payment order is sent. Only a subset of the object is displayed here to enhance clarity.
    "status": "pending_approval",
    "payment_validation": {
        "status": "in_progress",
        "validation_results": [{
            "status": "in_progress",
            "validations": [
                [{
                    "type": "sanction_screening",
                    "status": "in_progress",
                    "resource_id": null,
                    "resource_url": null,
                    "status_details": null
                }],
            ],
            "payment_validation_rule_id": "f1613230-50d6-49cd-89d1-0f019f71f7c7"
        }]
    }
}
'
200

{
  "status": "successful",
  "status_details": "no sanction hit"
}

Pre-built

Mambu Payments manages the validations based on your configuration.

sequenceDiagram
    participant Customer as Customer
    participant Numeral as Numeral

    Customer->>Numeral: Create payment order
    activate Numeral
    Note over Numeral: Validate payload
    Numeral-->>Customer: payment_order.pending_approval event
    Note over Numeral: Perform validation on Numeral objects
    Numeral-->>Customer: payment_order.approved event
    deactivate Numeral

Validation in payments

Every payment object (payment orders, incoming payments, and returns) features a dedicated payment_validation object in its payload. This provides full visibility into the validation lifecycle, including:

  • Overall status: The high-level state of the validation process (e.g., in_progress, successful, failed)
  • Rule attribution: The unique ID of the validation rule applied to the payment
  • Granular results: A comprehensive list of individual validations, detailing the status and result of each validation step

Below is an example of a payment order:

{
	"id": "b38f5318-a389-4278-9cbe-d16116750987",
	"object": "payment_order",
	"status": "pending_approval",

	// Only a subset of the object is displayed to enhance clarity.

	"payment_validation": {
		"status": "in_progress",
		"validation_results": [{
			"payment_validation_rule_id": "7c149cf6-0306-4a45-b48c-b3562c39ab2b",
			"status": "in_progress",
			"validations": [
				[{
					"type": "internal_account_is_active",
					"status": "successful",
					"status_details": null,
					"resource_id": "some ID",
          "resource_url": "https://someurl.com/someid",
					"last_updated_at": "2022-01-03T11:53:19.568Z"
				}],
				[{
						"type": "sanction_screening",
						"status": "successfull",
						"status_details": "No hit",
						"resource_id": "123456",
						"resource_url": "my-sanction-tool.com/case/123456",
						"last_updated_at": "2022-01-03T11:53:19.568Z"
					},
					{
						"type": "risk_screening",
						"status": "failed",
						"status_details": "multiple hits",
						"resource_id": "789ABC",
						"resource_url": "my-risk-tool.com/case/789ABC",
						"last_updated_at": "2022-01-03T11:53:19.568Z"
					}
				],
				[{
					"type": "liquidity_screening",
					"status": "canceled",
					"status_details": null,
					"resource_id": null,
					"resource_url": null
				}]
			]
		}]
	}
}

Example of a payment order validations