> ## Documentation Index
> Fetch the complete documentation index at: https://docs.finventi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Guide

> Complete testing scenarios and requirements before moving to production.

## Overview

This guide outlines the mandatory test scenarios for integrating with Inventi's Verification of Payee (VoP) solution. You must complete all test scenarios in the test environment before moving to production.

<Note>
  Once you complete all test cases, notify the Inventi VoP Product Manager to proceed with production deployment.
</Note>

## General Testing Guidelines

### Idempotency Requirement

<Warning>
  **All POST and PUT requests must include an `Idempotency-Key` header.** This ensures that duplicate submissions are safely ignored by the system and is required across all integration environments.
</Warning>

```bash theme={null}
--header 'Idempotency-Key: b7f3f8a2-9e0c-4d1e-8a2f-1234567890ab'
```

### Testing Requirements

* All expected results must be verified
* All test cases listed in this document must be fully completed
* Contact the Inventi VoP Product Manager after completion

## Test Scenarios

<Tabs>
  <Tab title="Requesting PSP Tests">
    ## VoP API - Verification Tests

    These test scenarios verify your VoP API integration, ensuring correct name and identifier matching and proper response handling.

    <AccordionGroup>
      <Accordion title="Test Case 1: IBAN + Matching Name" icon="circle-check">
        **Scenario**: Verify exact name match

        **Request Payload**:

        ```json theme={null}
        {
          "iban": "LT927300000000000001",
          "account_holder_name": "Lukas Johnson"
        }
        ```

        **Expected Result**:

        ```json theme={null}
        {
          "match_result": "MATCH"
        }
        ```
      </Accordion>

      <Accordion title="Test Case 2: IBAN + Close Name Match" icon="circle-half-stroke">
        **Scenario**: Verify fuzzy name matching

        **Request Payload**:

        ```json theme={null}
        {
          "iban": "LT657300000000000002",
          "account_holder_name": "L. Johnson"
        }
        ```

        **Expected Result**:

        ```json theme={null}
        {
          "match_result": "CLOSE_MATCH",
          "real_name": "Lukas Johnson"
        }
        ```

        <Info>
          The `real_name` field contains the actual registered account holder name. Always display this to the user for confirmation.
        </Info>
      </Accordion>

      <Accordion title="Test Case 3: IBAN + Incorrect Name" icon="circle-xmark">
        **Scenario**: Verify name mismatch detection

        **Request Payload**:

        ```json theme={null}
        {
          "iban": "LT387300000000000003",
          "account_holder_name": "Thomas Allen"
        }
        ```

        **Expected Result**:

        ```json theme={null}
        {
          "match_result": "NO_MATCH"
        }
        ```
      </Accordion>

      <Accordion title="Test Case 4: IBAN + Matching Organization Identifier (LEI)" icon="building">
        **Scenario**: Verify organization identifier matching

        <Note>
          Skip this test if you only send VoP checks using account holder names and not organization identifiers.
        </Note>

        **Request Payload**:

        ```json theme={null}
        {
          "iban": "LT117300000000000004",
          "organisation_identification": {
            "lei": "123456789012345678"
          }
        }
        ```

        **Expected Result**:

        ```json theme={null}
        {
          "match_result": "MATCH"
        }
        ```
      </Accordion>

      <Accordion title="Test Case 5: IBAN + Incorrect Organization Identifier" icon="building">
        **Scenario**: Verify organization identifier mismatch

        <Note>
          Skip this test if you only send VoP checks using account holder names and not organization identifiers.
        </Note>

        **Request Payload**:

        ```json theme={null}
        {
          "iban": "LT817300000000000005",
          "organisation_identification": {
            "lei": "123456789012345678"
          }
        }
        ```

        **Expected Result**:

        ```json theme={null}
        {
          "match_result": "NO_MATCH"
        }
        ```
      </Accordion>

      <Accordion title="Test Case 6: VoP Check Not Possible" icon="triangle-exclamation">
        **Scenario**: Verify handling when verification cannot be performed

        **Request Payload**:

        ```json theme={null}
        {
          "iban": "LT547300000000000006",
          "account_holder_name": "Anna Robbins"
        }
        ```

        **Expected Result**:

        ```json theme={null}
        {
          "match_result": "CANNOT_VERIFY"
        }
        ```
      </Accordion>

      <Accordion title="Test Case 7: Missing Required Fields" icon="exclamation-triangle">
        **Scenario**: Verify proper validation error handling

        **Request Payload**:

        ```json theme={null}
        {
          "iban": "LT277300000000000007",
          "account_holder_name": " "
        }
        ```

        **Expected Result**:

        ```json theme={null}
        HTTP 400 Bad Request
        {
          "message": "accountHolderName must not be blank if provided"
        }
        ```

        Or:

        ```json theme={null}
        {
          "message": "One of account_holder_name or organisation_identification must be provided"
        }
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Data Import TEST (for responding PSP side)">
    ## Data Import API - Account Management Tests

    These test scenarios ensure account data is correctly imported, updated, and deleted, and that accurate VoP responses are returned.

    <AccordionGroup>
      <Accordion title="Test Case 1: Single Account Import (Natural Person)" icon="user">
        **Scenario**: Import a single IBAN with natural person name

        **Request**: POST a valid single IBAN and name

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        {
          "total_count": 1,
          "imported_count": 1
        }
        ```
      </Accordion>

      <Accordion title="Test Case 2: Single Account Import (Legal Entity)" icon="building">
        **Scenario**: Import a single IBAN with legal entity details

        **Request**: POST a valid single IBAN, name, and the organization identifier you support

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        {
          "total_count": 1,
          "imported_count": 1
        }
        ```
      </Accordion>

      <Accordion title="Test Case 3: Batch Import (10 Accounts)" icon="layer-group">
        **Scenario**: Import multiple accounts in a single request

        **Request**: POST 10 IBAN and name entries

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        {
          "total_count": 10,
          "imported_count": 10
        }
        ```
      </Accordion>

      <Accordion title="Test Case 4: Batch Import with Validation Error" icon="triangle-exclamation">
        **Scenario**: Verify partial import with one invalid entry

        **Request**: POST 10 IBAN and name entries, but one entry has a missing IBAN

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        {
          "total_count": 10,
          "imported_count": 9,
          "failed_count": 1
        }
        ```
      </Accordion>

      <Accordion title="Test Case 5: Update Account by IBAN" icon="pen-to-square">
        **Scenario**: Update an existing account using IBAN

        **Request**: PUT a valid single IBAN and name using an IBAN (use IBAN from test case #1)

        **Note**: All account data must be imported before updating

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        ```
      </Accordion>

      <Accordion title="Test Case 6: Update Account by Client ID" icon="pen-to-square">
        **Scenario**: Update an existing account using Client ID

        **Request**: PUT a valid single IBAN and name using a Client ID (use IBAN from test case #2)

        **Note**: All account data must be imported before updating

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        ```
      </Accordion>

      <Accordion title="Test Case 7: Delete Existing IBAN" icon="trash">
        **Scenario**: Delete an account by IBAN

        **Request**: DELETE a known IBAN (use any IBAN from test case #3)

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        ```
      </Accordion>

      <Accordion title="Test Case 8: Delete by Client ID" icon="trash">
        **Scenario**: Delete an account by Client ID

        **Request**: DELETE a known ClientID (use valid ClientID from test case #4)

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        ```
      </Accordion>

      <Accordion title="Test Case 9: Delete Unknown IBAN" icon="trash">
        **Scenario**: Verify handling of deletion for non-existent account

        **Request**: DELETE an unknown IBAN (use random IBAN that was not imported in previous test cases)

        **Expected Result**:

        ```json theme={null}
        HTTP 200 OK
        {
          "total_count": 1,
          "failed_count": 1
        }
        ```
      </Accordion>

      <Accordion title="Test Case 10: Empty Import Request" icon="exclamation-triangle">
        **Scenario**: Verify validation for empty request

        **Request**: POST a request with an empty IBANs list

        ```json theme={null}
        {
          "ibans": []
        }
        ```

        **Expected Result**:

        ```json theme={null}
        HTTP 400 Bad Request
        {
          "message": "must not be empty"
        }
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

## Organization Identifiers

<Info>
  Responding PSPs should include organization identifiers (e.g., LEI, VAT) for all legal entity accounts to ensure accurate VoP validation.
</Info>

### Why Organization Identifiers Matter

When a Requesting PSP initiates a payment using IBAN + identifier (instead of a legal name), Inventi matches this against your imported data. If the identifier is missing, the request may return a `NO_MATCH` result, which could lead to payment failures.

<Note>
  A full list of supported identifiers can be found in the [VoP API Reference](/vop/api/account-management/batch-import-of-account-entries).
</Note>

## Best Practices

<CardGroup cols={2}>
  <Card title="Handle CLOSE_MATCH Carefully" icon="triangle-exclamation">
    Always treat `CLOSE_MATCH` differently from `MATCH`. Display the `real_name` field to the payer for confirmation before proceeding with the payment.

    **Example**:

    ```json theme={null}
    {
      "match_result": "CLOSE_MATCH",
      "real_name": "Lukas Johnson"
    }
    ```

    Show: *"Did you mean: Lukas Johnson?"*
  </Card>

  <Card title="Use Aliases for Legal Entities" icon="building">
    Include alias values when importing legal entity data to improve name-matching accuracy.

    **Example**:

    * Full name: "International Business Machines"
    * Alias: "IBM"

    This improves matching flexibility when users enter common abbreviations.
  </Card>

  <Card title="Implement Idempotency Keys" icon="key">
    Always include unique `Idempotency-Key` headers to prevent duplicate submissions.

    Use UUIDs or other unique identifiers:

    ```
    Idempotency-Key: b7f3f8a2-9e0c-4d1e-8a2f-1234567890ab
    ```
  </Card>

  <Card title="Verify All Test Cases" icon="clipboard-check">
    Complete all test scenarios before requesting production access. Keep a record of:

    * Test case number
    * Request sent
    * Response received
    * Pass/Fail status
  </Card>
</CardGroup>
