# Overview

The Split Payments solution enables a "Marketplace" model where a customer can create a single aggregated
order containing products or services from multiple vendors (sites).

When a customer pays for this aggregated order, the system automatically handles the distribution of funds.
The main order is processed on the primary (sending) site, and corresponding "internal" orders and
transactions are instantly created on the vendor (receiving) sites.

# How It Works

1. **Aggregated Order:** You create a single order request on the primary merchant site (the "marketplace site").
2. **Split Definition:** Inside this request, you declare the destination sites and amounts using the
`transactionOptions` parameter with the `splitPayment` schema.
3. **Automatic Distribution:** Upon a successful payment:


- A primary Order and Transaction are created on the sending site.
- New Orders are automatically created on each "receiving site" defined in the split schema.
- Funds Transfer: Internal credit and deposit transactions are executed to move funds from the sending site to the receiving sites.


# Integration Methods

You can implement Split Payments using either the [Direct API](/api/reference/order) or
the Hosted [Checkout solution](/guides/checkout/hosted-checkout).

### Direct API (POST /order)

Use this method if you are integrating directly via the `POST /order` endpoint.

PCI DSS Compliance Requirement
Because this integration method requires you to collect and transmit raw card details (PAN, CVV) directly in the API request,
**your organization must be fully PCI DSS compliant.**

If you are not PCI DSS compliant, you strictly cannot use this method for card payments.
Please utilize the [Hosted Checkout](/guides/checkout/hosted-checkout) solution instead, which offloads compliance
requirements by handling card data on our secure payment pages.

#### Request Structure

In addition to the standard [Create Order](/api/reference/order) parameters
(such as `amount`, `currency`, `customerId`, `orderType`),
you must include the `transactionOptions` object containing the `splitPayment` definition.

**Example Request**
In this example, a customer purchases items totaling **100.00 EUR**.

- 50.00 EUR goes to Vendor A (Site 9825).
- 30.00 EUR goes to Vendor B (Site 9792).
- 20.00 EUR remains on the Marketplace (Sending Site) as commission/fees.



```JSON
{
  "amount": 100.00,
  "currency": "EUR",
  "orderType": "purchase",
  "customerId": 12345,
  "description": "Marketplace Aggregated Order #5501",
  "transactionOptions": {
    "splitPayment": {
      "splitSchema": [
        {
          "toSite": 9825,
          "amount": 50.00,
          "description": "Payment to Vendor A",
          "tag": ["vendorA", "electronics"]
        },
        {
          "toSite": 9792,
          "amount": 30.00,
          "description": "Payment to Vendor B",
          "tag": ["vendorB", "accessories"]
        }
      ]
    }
  }
}
```

### Hosted Checkout

Use this method if you are using the [Hosted Checkout](/guides/checkout/hosted-checkout) page. The configuration is passed
within the encrypted `jsonRequest` payload used to initialize the payment session.
This method is suitable for merchants who are **not** PCI DSS compliant.

**Request Structure**
Add the `transactionOptions` object to the root of your `jsonRequest` structure.

Ensure that your checksum calculation includes this new `transactionOptions` field,
as the entire JSON payload is used to generate the signature.

**Example `jsonRequest`**


```JSON
{
  "siteId": 1,
  "customer": {
    "identifier": "your-unique-customer-id",
    "firstName": "John",
    "lastName": "Doe",
    "country": "RO",
    "city": "Bucharest",
    "email": "john.doe@test.com"
  },
  "order": {
    "orderId": "your-unique-order-id",
    "description": "Order Description",
    "type": "purchase",
    "amount": 2194.98,
    "currency": "RON"
  },
  "cardTransactionMode": "authAndCapture",
  "backUrl": "https://myshop.com/payment-back-url",
  "transactionOptions": {
    "splitPayment": {
      "splitSchema": [
        {
          "toSite": 9825,
          "amount": 1000.00,
          "description": "Payment for Vendor A",
          "tag": ["vendorA"]
        },
        {
          "toSite": 9792,
          "amount": 500.00,
          "description": "Payment for Vendor B",
          "tag": ["vendorB"]
        }
      ]
    }
  }
}
```

# Configuration Reference

`transactionOptions` Schema

| Field | Type | Description |
|  --- | --- | --- |
| `splitPayment` | Object | The root object for the split configuration. |
| `splitPayment.splitSchema` | Array | A list of objects defining where funds should be routed. |


`splitSchema` Item Details

| Field | Type | Description |
|  --- | --- | --- |
| `toSite` | Integer | The Site ID of the vendor receiving the funds.  **Note**: Do not use the sending site's ID here |
| `amount` | Float | The amount to be transferred to this site |
| `description` | String | A description for this specific portion of the payment. |
| `tag` | Array | Optional tags for categorization or reconciliation. |


Validation Note
The sum of amount in the split schema must not exceed the total amount of the main order.
Any remainder stays on the sending site.

# Post-Processing & Artifacts

Once the transaction is successful, the system generates several linked entities to represent the flow of funds.

### On the Sending Site (Marketplace)

- **Order**: A standard purchase order is created.
- **Transaction**: A transaction of `type='credit'` and `transactionMethod='transfer'` is created.
  - This transaction will have a component named "internal-credit".


### On the Receiving Site (Vendor)

For every item in the `splitSchema`, the following are automatically generated on the specific `toSite`:

- New Customer:
  - Created with identifier format: `"internal-{customerId from sending site}"`.
- New Order:
  - Created with `orderType='purchase'`.
  - Linked via `externalOrderId` format: `"internal-{orderId from sending site}"`.
- New Transaction:
  - Created with `type='deposit'` and `transactionMethod='transfer'`.
  - This transaction will have a component named `"internal-deposit"`.


# Refunds

## Overview

Refunding a split payment follows the same API endpoint as a standard refund — `DELETE /transaction/{id}` — but with an important distinction: you must include the `splitPayment.splitSchema` in the request body if you want to also reverse the transfers to secondary recipients.

All refund operations target the **parent transaction only**. You should never call DELETE directly on a transfer transaction.

## Transaction Structure

A split payment with one secondary recipient produces:

| # | Transaction | Visible to |
|  --- | --- | --- |
| 1 | **Parent** — card charge from customer to primary merchant | Primary merchant |
| 2 | **Transfer** — funds moved from primary merchant to secondary recipient | Primary merchant & Secondary recipient |


The transfer transaction is linked to the parent via `parent_transaction_id`.

## Prerequisites

Before a refund can be processed, the following conditions must be met:

- The parent transaction type must be `DEPOSIT`.
- The transaction status must allow refunds (not already fully refunded, voided, or canceled).
- The `splitStatus` must be `SPLIT_COMPLETE` or `SPLIT_CONFIRM` (or `null` for non-split transactions).
- All sites involved in the refund must have sufficient funds.


## Full Refund (Order + Splits)

To fully refund the entire order **and** reverse all split transfers, make a single `DELETE` call on the parent transaction with the original split schema:


```
DELETE /transaction/{parentTransactionId}
```

**Request body:**


```json
{
  "transactionOption": {
    "splitPayment": {
      "splitSchema": [
        {
          "toSite": 12345,
          "amount": 50.00,
          "description": "Full refund"
        }
      ]
    }
  }
}
```

**What happens:**

1. The card transaction is refunded — funds are returned to the customer.
2. The transfer to the secondary recipient is reversed — funds are clawed back from the secondary recipient to the primary merchant.


> **Note:** The amounts in the `splitSchema` should match the original split amounts for a full refund.


## Partial Refund (Order + Splits)

To partially refund the order while also partially reversing split transfers, provide an `amount` and an adjusted split schema:


```
DELETE /transaction/{parentTransactionId}
```

**Request body:**


```json
{
  "amount": 30.00,
  "transactionOption": {
    "splitPayment": {
      "splitSchema": [
        {
          "toSite": 12345,
          "amount": 20.00,
          "description": "Partial refund"
        }
      ]
    }
  }
}
```

**What happens:**

1. A partial card refund of 30.00 is issued to the customer.
2. 20.00 is clawed back from the secondary recipient.
3. The remaining 10.00 comes from the primary merchant's balance.


**Validation rules for partial refunds:**

- Each site's cumulative refunded amount (across multiple partial refunds) must not exceed the original split amount for that site.
- The total refund amount must not exceed the remaining refundable amount on the parent transaction.
- Multiple partial refunds can be issued over time, as long as the cumulative totals stay within limits.


## Refund Without Reversing Splits

If you call DELETE **without** the `transactionOption.splitPayment` field, only the parent card transaction is refunded. The split transfers remain untouched — secondary recipients keep their funds.


```
DELETE /transaction/{parentTransactionId}
```

**Request body:**


```json
{
  "amount": 10.00
}
```

**What happens:**

1. 10.00 is refunded to the customer.
2. The funds come entirely from the primary merchant's balance.
3. All transfer transactions remain unchanged.


This is useful when the primary merchant wants to issue a goodwill refund to the customer without affecting the secondary recipients.

## Summary

| Scenario | `amount` | `splitSchema` included | Result |
|  --- | --- | --- | --- |
| Full refund with split reversal | Omitted (defaults to full amount) | Yes — with original amounts | Card refunded + all transfers reversed |
| Partial refund with split reversal | Partial amount | Yes — with adjusted amounts | Partial card refund + partial transfer reversals |
| Refund without split reversal | Any amount | No | Only card refunded, transfers untouched |


## Important Notes

- Always operate on the **parent transaction ID**. Do not attempt to refund transfer transactions directly.
- The system performs a **funds availability check** on all involved sites before processing the refund.
- For split payments with **multiple secondary recipients**, include all relevant recipients in the `splitSchema` array.
- **Nested splits** (splits of splits) are supported and handled recursively — the same schema structure applies at each level.


# Integration & Compliance Checklist

## Security & PCI Compliance

Determine Integration Type & Scope:

- [ ] **Direct API**: Confirm your organization is **PCI DSS Compliant** (typically SAQ D or Level 1 audit) to handle raw card data.
- [ ] **Hosted Checkout**: Confirm you qualify for **SAQ A** (all card data handling offloaded to xMoney).


Credentials Management:

- [ ] Ensure `Private Key` is never exposed in client-side code (browser/mobile app).


## Split Schema Validation (Business Logic)

Amount Verification:

- [ ] **Sum Check**: Total of `amount` in `splitSchema` <= Main Order `amount`.
- [ ] **Remainder**: Confirm that any unallocated remainder is intended to stay on the Sending Site (Marketplace) as commission.


Site ID Rules:

- [ ] **No Self-Loop**: `toSite` must not equal the Sending Site ID.
- [ ] **No Duplicates**: `toSite` IDs must be unique within the `splitSchema` array.


Currency Consistency:

- [ ] Ensure all split amounts assume the same currency as the main order
(cross-currency splits are not supported in this schema).


## Technical Integration

If using Hosted Checkout:

- Payload Structure:
  - [ ] `transactionOptions` is placed inside the root of the `jsonRequest` object.
- Checksum Calculation:
  - [ ] The checksum calculation (HMAC-SHA-512) includes the **entire** JSON payload, including the new `transactionOptions` object.
  - [ ] Verify the JSON stringification order does not alter the checksum (ensure consistent serialization).


If using Direct API:

- Payload Structure:
  - [ ] `transactionOptions` is a sibling to amount and customerId in the POST body.


## Post-Integration Testing

End-to-End Flow:

- [ ] Perform a successful transaction using a [Test Card](/guides/general/get-started#test-cards).


Verify Sending Site:

- [ ] Confirm 1 Order and 1 Transaction (`internal-credit`) created.


Verify Receiving Site(s):

- [ ] Login to vendor dashboard (or use API) to confirm 1 Order and 1 Transaction (`internal-deposit`) created per split.
- [ ] Verify `externalOrderId` matches the format `internal-{parent_order_id}`.
- [ ] Verify `amount` matches the specific split value.


## Error Handling

- [ ] Implement logic to handle `400 Bad Request` if the split amount exceeds the total order amount.
- [ ] Handle partial failures (e.g., if a vendor account is suspended) based on xMoney's specific error codes.