# Verification of Payee

This guide provides comprehensive information about the Verification of a Payee (VoP) feature, including key concepts and the required API endpoints to integrate it into your banking solution.

## What is Verification of Payee?

Verification of Payee (VoP) is an account name-checking service designed to enhance customer confidence when initiating SEPA Credit Transfers (SCT) or SEPA Instant Credit Transfers (SCT Inst). VoP helps reduce authorized push payment (APP) fraud and misdirected payments by verifying that the recipient's name and IBAN match before execution.

* **Mandate:** It is mandated by the [European Payments Council (EPC)](https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=OJ:L_202400886) and follows the standards outlined in the [Verification of a Payee Rulebook](https://www.europeanpaymentscouncil.eu/sites/default/files/kb/file/2024-10/EPC218-23%20v1.0%202024%20Verification%20Of%20Payee%20Scheme%20Rulebook_0.pdf).
* **Eurozone Deadline:** Starting October 9, 2025, VoP requirements come into effect across all Eurozone countries.
* **Non-Eurozone Deadline:** For non-Eurozone countries, these requirements will apply from July 9, 2027.
* **Exemptions:** At this time, Switzerland and the United Kingdom have not announced a planned adoption date for these EPC requirements (though the UK uses a separate Confirmation of Payee system).


## How It Works

VoP is a pre-payment check required before a customer can authorize a payment. The following sequence diagram illustrates a scenario where a verification check requires user intervention (such as a `CLOSE_MATCH`), giving the customer the opportunity to adjust their input or proceed with the transfer.

1. The customer enters the recipient's full name and IBAN.
2. Solaris forwards this information to the recipient's bank using the VoP schema.
3. The recipient bank checks if the details match and returns a result to Solaris.
4. Solaris then relays the result back to your application.



```mermaid
sequenceDiagram
    autonumber
    
    participant C as Customer
    participant P as Partner
    participant S as Solaris
    participant E as External Bank

    Note over C: Initiate SEPA Credit Transfer
    
    loop Adjust Input (e.g., CLOSE_MATCH)
        C->>P: Enter Creditor full Name & IBAN
        P->>S: Calls VoP API
        
        Note over S: Validate input &<br>Generate VoP id
        S->>E: Validate against Internal data
        
        Note over E: Generates a Result
        E-->>S: Return Result
        
        Note over S: Save Results & send<br>along with VoP id
        S-->>P: Return Result & VoP id
        
        Note over P: Save the result<br>and the VoP id
        P-->>C: Display the Result of the VoP
    end
    
    alt Decision: No
        Note over C: Transaction not initiated<br>Process Ends
    else Decision: Yes
        C->>P: Continue with Change Request Process
        
        P->>S: Initiates SCT with VoP id
        Note over S: Validates the VoP id
        
        S-->>P: Requires Change Request Process
        P->>S: Initiate Change Request
        
        Note over S: Proceeds to create transaction
        S->>E: Execute Transfer
        Note over E: Creditor is Credited
        
        S-->>P: Return Transaction outcome
        Note over P: Display Transaction outcome
        P-->>C: Transaction Executed with VoP id
    end
```

### Possible VoP Results

| Status | Description | Required Action |
|  --- | --- | --- |
| `MATCH` | The recipient's name and IBAN match exactly with the records at the recipient's bank. | Display a positive confirmation to the customer and proceed with payment authorization. |
| `CLOSE_MATCH` | There is a minor discrepancy (e.g., typo). The recipient's bank returns the correct name, which Solaris passes on to you. | You **must** notify your customer of the result and display the correct account name provided by the recipient's bank. |
| `NO_MATCH` | The provided name does not correspond with the IBAN at all. | You **must** inform your customer immediately that the transfer may be directed to an incorrect or unintended recipient if they proceed. |
| `VERIFICATION_NOT_POSSIBLE` | The verification process could not be completed (e.g., invalid IBAN, technical errors, schema issues). | You **must** inform your customer immediately that the transfer may be directed to an incorrect or unintended recipient if they proceed. |
| `VERIFICATION_NOT_SUPPORTED` | The provided name and IBAN correspond to a bank account in a country not currently required to support payee verification. | You are **not** obligated to inform the customer about this specific verification result. |


Matching Logic & Non-Eurozone Countries
The recipient bank is solely responsible for determining the match. Solaris cannot influence or guarantee the matching logic used. However, all SEPA-region banks follow the [EPC's recommended matching rules](https://www.europeanpaymentscouncil.eu/sites/default/files/kb/file/2024-10/EPC288-23%20v1.0%20EPC%20Recommendations%20for%20the%20Matching%20Processes%20under%20the%20VOP%20Scheme%20Rulebook_0.pdf).

As a best practice, we recommend always calling the Verification of Payee endpoint before initiating a SEPA or SEPA Instant transaction. For non-Eurozone countries, as well as Switzerland and the United Kingdom, the response will include a status field with the value `VERIFICATION_NOT_SUPPORTED`, along with a valid `verification_of_payee_id`. Solaris will enable support for these countries as soon as they officially adopt the Verification of Payee (VoP) scheme.

## Risk Ownership and Liability

In cases of reported fraud related to a VoP result, risk ownership depends on the origin of the issue:

* **Bank Error:** If the issue is caused by Solaris or the recipient bank (e.g., an incorrect match result or technical failure), the responsible party will bear the associated costs.
* **Customer Error (Ignored Warning):** If a correct VoP result is returned (such as `NO_MATCH` or `VERIFICATION_NOT_POSSIBLE`):
  1. Present the result to your customer.
  2. Clearly communicate that authorizing the credit transfer may result in funds being sent to an account not held by the intended recipient.
If the warning was properly communicated and the customer still proceeded, the customer bears the associated risk and costs.
* **Partner Error (Missing Warning):** If you fail to provide this warning to the customer and they complete the transfer, **you (the Partner) assume liability** for any resulting loss.


Liability Shift
If you include a valid `verification_of_payee_id` when initiating the credit transfer, we assume the VoP result was accurately presented to the customer and they made an informed decision to proceed. In such cases, Solaris bears no liability.

## Integration Steps

### 1. Initiate Verification

Initiation of the Verification of Payee should always occur prior to creating a credit transfer.

**Endpoint:** `POST /v1/verifications-of-payee`


```json
{
    "iban": "DE89370400440532013000",
    "name": "John Doe"
}
```

**Response Example:**


```json
{
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "payee": {
        "iban": "DE89370400440532013000",
        "name": "John Doe"
    },
    "result": {
        "status": "CLOSE_MATCH",
        "suggested_name": "John M. Doe",
        "error_reason": "string"
    },
    "created_at": "2025-04-16T12:34:56Z",
    "expires_at": "2025-04-16T12:39:56Z"
}
```

### 2. Validation Rules

When you subsequently initiate a credit transfer, Solaris validates the `verification_of_payee_id` included in the request.

* **Validity:** The ID is valid for **20 minutes** from the time of its creation. Any attempt to use an expired ID will be rejected.
* **Single-Use:** Each `verification_of_payee_id` is single-use only. Once received by Solaris in a transfer request, it is marked as consumed and cannot be reused.
* **Error Handling:** If the ID is missing, invalid, expired, or already used, Solaris will return a `400 Bad Request` error, causing the transfer to fail.


### 3. Retrieve Previous Result (Optional)

You can retrieve the result of a previously performed verification by its unique identifier.

**Endpoint:** `GET /v1/verifications-of-payee/{id}`

## Sandbox Testing

To simulate various VoP results in the Sandbox environment, use the following combination of values when calling the `POST` endpoint.

| VoP Result | Name | IBAN |
|  --- | --- | --- |
| `MATCH` | "John M. Doe" | `DE30110101990000000001` |
| `CLOSE_MATCH` | "John Doe" | `DE30110101990000000001` |
| `NO_MATCH` | "John" | `DE30110101990000000001` |
| `VERIFICATION_NOT_SUPPORTED` | *Any Name* | *Any SEPA non-euro/Swiss/UK IBAN* |
| `VERIFICATION_NOT_POSSIBLE` | "John M. Doe" | *Any other valid IBAN on Sandbox* |