# Multi-leg payments The [Multi-leg payments feature](https://developers.pismo.io/pismo-docs/reference/corporate-v3-post-multileg-payments) enables you to process payment transactions by grouping multiple legs into a single request. This approach simplifies payment processing and removes the need to send multiple separate single-leg payment requests. With this feature, you can define each individual transaction—either credit or debit—within each leg of the multi-leg payment. The Pismo platform ensures data integrity by enforcing strict validation, idempotency, and error-handling mechanisms throughout the payment lifecycle. Each transaction is uniquely identified by a multi-leg ID, which cannot be reused across different services. In the event of errors—such as a failed debit or credit leg—the platform employs a robust rollback process to reverse all successfully executed legs, maintaining transactional consistency and supporting accurate reconciliation. **Notes** * Each multi-leg payment request must contain a minimum of two legs (either credit or debit) and can include up to a maximum of 20 legs. * You cannot use [Post multi-leg payment](https://developers.pismo.io/pismo-docs/reference/corporate-v3-post-multileg-payments) to transfer credit and debit leg payments to different accounts for identical amounts. For such situations, use [Post payment](https://developers.pismo.io/pismo-docs/reference/corporate-v2-post-payments) instead. # Supported features In addition to simplifying complex transactions, multi-leg payments offer several capabilities that enhance flexibility, control, and reconciliation. * **Instant clearing**: Use the `instant_clearing` field to request immediate clearing for specific debit or credit legs. Refer to [Post multi-leg payment](https://developers.pismo.io/pismo-docs/reference/corporate-v3-post-multileg-payments) for details. * **Earmark support**: Debit legs can reference an `earmark_id` to use earmarked funds. * **Granular validation rules**: Per-leg validation options allow override or force behavior for account status and ledger checks, reducing the likelihood of rollbacks. * **Metadata support**: You can pass metadata and soft descriptor in each leg. Custom metadata provided in the request is returned in responses and included in events, aiding reconciliation and reporting. # Multi-leg and tracking ID A `multileg_id` uniquely identifies the entire multi-leg payment request. A tracking ID on the other hand, is used to identify and track an individual payment leg within a multi-leg transaction, whether debit or credit. When using [Post multi-leg payment](https://developers.pismo.io/pismo-docs/reference/corporate-v3-post-multileg-payments), you must pass a tracking ID in each leg to ensure the transaction is unique. ### About tracking ID Each tracking ID is single-use and cannot be reused across different services. For example, if a tracking ID has already been used for a [Post payment](https://developers.pismo.io/pismo-docs/reference/corporate-v2-post-payments), it cannot be used again for a leg in [Post multi-leg payment](https://developers.pismo.io/pismo-docs/reference/corporate-v3-post-multileg-payments). # Force payment restrictions In scenarios where `force_post` is set to `true`, any reason-based force payment restrictions on the account result in a failed force payment operation. These restrictions apply to both credit and debit operations. Use the [List status reasons](https://developers.pismo.io/pismo-docs/reference/v4-get-account-reason) endpoint to view the corresponding reason IDs. Forced transfers from an earmark balance are not supported. If an account has a status that prevents force operations, the payment will fail. For more information, refer to [Manage account statuses](https://developers.pismo.io/pismo-docs/docs/managing-account-statuses). # Error handling mechanism During the processing of a multi-leg payment request, the Pismo platform enforces a robust error-handling mechanism known as rollback to safeguard data integrity. If any leg—credit or debit—fails, all previously successful legs are rolled back. If a rollback attempt itself fails, those legs are marked as `ROLLBACK_FAILED`. The rollback process is resource-intensive and generates compensating transactions to reverse any legs that were already executed.\ To minimize the need for rollbacks, the Pismo platform performs thorough validations when each payment request is received and proactively returns errors for invalid inputs before processing begins. ## Error response structure When validation errors occur in a request, the API returns a structured error response with these components. * **Standard error message**: For example, error code `WMLP0005` warns about invalid inputs without providing leg-specific details. This typically occurs when reusing a `tracking_id`. * **Duplicate tracking ID**: If you reuse a tracking ID from a previous payment, the system returns error code `WPMT0007` and rejects the request. * **List of leg-specific errors**: For certain failures, the response includes detailed errors for individual legs within the error object of each leg. In some cases, errors apply to the entire request, such as when the maximum number of legs is exceeded, and only a standard code and message are returned. ## Error identification When a leg fails, you can retrieve the payment’s status using [Get multi-leg payment status](https://developers.pismo.io/pismo-docs/reference/corporate-v3-get-multileg-payment) and check the `event_datetime` field in the affected leg to see when the error occurred. This information is available only if the multi-leg payment was being created and the failure occurred while generating platform authorization. Note that not all legs display the `event_datetime` field. **Note** If either a credit or debit leg fails in a multi-leg payment, the Pismo platform automatically initiates a rollback of all previously executed legs, unless the rollback itself fails. In cases where a rollback cannot be completed, the affected legs are marked as `ROLLBACK_FAILED`. This rollback mechanism helps maintain transactional consistency. You can monitor the status of a multi-leg payment by using the [Get multi-leg payment status](https://developers.pismo.io/pismo-docs/reference/corporate-v3-get-multileg-payment) endpoint with a `multileg_id`. The `event_datetime` field might be displayed for a failed leg only when the multi-leg payment is created and the failure occurs while generating platform authorization. If a rollback fails under these conditions, the same endpoint reflects that status, enabling you to verify the outcome. # How to use Post multi-leg payment Consider a scenario in which your account has a balance of $1000, and you wish to initiate a payment request with three legs: two debit legs (one for $100, another for $200) and one credit leg for $600. Here are the API request details.
Sample request ```curl cURL curl --request POST \ --url https://sandbox.pismolabs.io/corporate/v3/payments/multileg \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "multileg_id": "0a50c88a-ade8-4bcc-a639-9a0b0f11e245", "debits": [ { "tracking_id": "cf7f77ae-466c-428d-8e9f-7834341dd81e", "amount": 100.00, "currency": "USD", "external_account_id": "account-a", "processing_code": "219258", "soft_descriptor": "ACME Inc. - Invoice 2938", "force_post": false, "validation_rules": { "ACCOUNT_STATUS": { "override": false }, "LEDGER": { "force": false } }, "skip_account_date_validation": false, "earmark_id": "8a3be3c1-5a2c-4d98-9901-8-account-a", "instant_clearing": false }, { "tracking_id": "4cd1caeb-d454-4c92-971f-aeb6c14a4445", "amount": 200.00, "currency": "USD", "external_account_id": "account-a", "processing_code": "220037", "soft_descriptor": "ACME Inc. - Invoice 2938", "instant_clearing": false } ], "credits": [ { "tracking_id": "8c0d14ff-5c1d-4046-8e55-6833161f218e", "amount": 600.00, "currency": "USD", "external_account_id": "account-a", "processing_code": "220035", "soft_descriptor": "ACME Inc. - Invoice 2938", "instant_clearing": false, "force_post": true } ], "metadata": { "custom_info": "abc" } } ```
Upon successful execution, the API returns the following response payload to confirm the successful processing of your request.
Sample response ```json JSON 202 Accepted { "debits": [ { "tracking_id": "cf7f77ae-466c-428d-8e9f-7834341dd81e", "external_account_id": "account-a", "processing_code": "219258", "soft_descriptor": "ACME Inc. - Invoice 2938", "amount": 100, "currency": "USD", "earmark_id": "8a3be3c1-5a2c-4d98-9901-account-a", "force_post": false, "validation_rules": { "ACCOUNT_STATUS": { "force": false, "override": false }, "LEDGER": { "force": false, "override": false } }, "instant_clearing": false, "skip_account_date_validation": false }, { "tracking_id": "4cd1caeb-d454-4c92-971f-aeb6c14a4445", "external_account_id": "account-a", "processing_code": "220037", "soft_descriptor": "ACME Inc. - Invoice 2938", "amount": 200, "currency": "USD", "force_post": false, "instant_clearing": false, "skip_account_date_validation": false } ], "credits": [ { "tracking_id": "8c0d14ff-5c1d-4046-8e55-6833161f218e", "external_account_id": "account-a", "processing_code": "220035", "soft_descriptor": "ACME Inc. - Invoice 2938", "amount": 600, "currency": "USD", "force_post": true, "instant_clearing": false, "skip_account_date_validation": false } ], "multileg_id": "0a50c88a-ade8-4bcc-a639-9a0b0f11e245", "metadata": { "custom_info": "abc" } } ```
You can optionally use [Get transaction banking account information](https://developers.pismo.io/pismo-docs/reference/get-accounts) to retrieve and display the complete result of this transaction. As shown in the response, the payment request comprising two debit legs totaling $300 and one credit leg of $600 results in an updated account balance of $1300.