Skip to main content

Documentation

Managing Escrow

Hold any payment method in escrow for later release.

An escrow is an arrangement to hold funds in a transaction between two or more parties. Escrows help settle an exchange between a buyer and seller based upon the agreed requirements. When a buyer makes a high value purchase and the funds are held in escrow, the funds are held for one or multiple sellers and can be released in the following ways:

  • Full or partial release on demand.

  • Release automatically after a specific number of days.

  • Partial releases can be released by amount or percentage and proportional or non-proportional.

Escrow is a feature of Rapyd Collect that works with your website back end, and holds funds using a Rapyd Wallet. When the purchase is made, your website back end asks Rapyd to process the payment and then holds the funds in the wallet. The funds are then released to the seller of the item according to your predetermined agreement with the seller or on demand request. When the money is released, Rapyd notifies you via webhook that the transfer was completed successfully.

A customer purchases an item for 250 USD (U.S. Dollars) from a seller on your marketplace. You hold the funds in escrow that the customer paid. You release a partial amount of funds automatically after 5 days, and release the rest of the funds to the seller on demand based on your business policies.

PCI Certification

Only clients with PCI-DSS certification can handle personal identifying information for cards. This method is available to merchants who have signed a special agreement with Rapyd.

Step 1: Processing Escrow Payment

Finding the specific payment methods you'll accept and the corresponding required fields that customers fill out is described under How it Works.

process-escrow.jpg
  1. A customer on your marketplace purchases a product from a seller.

  2. The website back end asks Rapyd to process the transaction and hold the funds in escrow for five days.

  3. Rapyd processes the payments and holds the funds in escrow.

Step 2: Releasing Escrow Funds
release-escrow.jpg
  1. The website back end asks Rapyd to release part of the funds for the seller.

  2. Rapyd automatically releases part of the funds for the seller, and continues to hold the remaining funds in escrow.

  3. Rapyd manually releases the remaining escrow funds to the seller based on the delivery of the high value item.

The finite state diagram below summarizes the statuses for escrow payments.

escrow.svg

Description of Statuses

Status

Description

pending

The payment and escrow were created, but the payment is not completed and the funds are not in escrow.

on_hold

The payment is completed and the funds are in escrow.

released

All or part of the funds have been released to the wallets.

canceled

The escrow is canceled.

Prerequisites

To run the examples of this use case, you must create the following IDs in your own sandbox:

  • ewallet_ - Run Create Wallet for the Rapyd Wallet of the seller of the phone. Use the 'id' you get in the response. For more information, see Creating a Rapyd Wallet. Repeat for the wallet of the seller of the speaker.

On your payment page, you let the customer select a payment method. First, you need to decide which payment methods you'll accept. In this example, you'll check for payment methods using USD (U.S. Dollars) in the United States.

For that, you'll use List Payment Methods by Country with the following parameters.

Description of Query Parameters

Query Parameter

Description

country

Enter US as the country code for the United States.

currency

Enter USD as the currency code for U.S. Dollars.

List Payment Methods by Country Request

You ask for the list of all available US payment methods in USD.

    • Request

      • // Request URL: GET https://sandboxapi.rapyd.net/v1/payment_methods/country?country=US&currency=USD
        
        // Message body absent
    • .NET Core

      • using System;
        
        namespace RapydApiRequestSample
        {
            class Program
            {
                static void Main(string[] args)
                {
                    try
                    {
                        string country = "US";
                        string currency = "USD";
        
                        string result = RapydApiRequestSample.Utilities.MakeRequest("GET", $"/v1/payment_methods/country?country={country}&currency={currency}");
        
                        Console.WriteLine(result);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Error completing request: " + e.Message);
                    }
                }
            }
        }
    • JavaScript

      • const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;
        
        async function main() {
          try {
            const result = await makeRequest('GET', '/v1/payment_methods/country?country=US&currency=USD');
        
            console.log(result);
          } catch (error) {
            console.error('Error completing request', error);
          }
        }
    • PHP

      • <?php
        $path = $_SERVER['DOCUMENT_ROOT'];
        $path .= "/<path-to-your-utility-file>/utilities.php";
        include($path);
        
        try {
            $object = make_request('get', '/v1/payment_methods/country?country=US&currency=USD');
            var_dump($object);
        } catch (Exception $e) {
            echo "Error: $e";
        }
        ?>
    • Python

      • from pprint import pprint
        
        from utilities import make_request
        
        results = make_request(method='get',
                               path=f'/v1/payment_methods/country?country=US&currency=USD')
        pprint(results)
        
List Payment Methods by Country Response

Let's take a look at the response.

    • Response

      • {
            "status": {
                "error_code": "",
                "status": "SUCCESS",
                "message": "",
                "response_code": "",
                "operation_id": "2ef3f76f-6a57-4d1f-bf60-162313d304bc"
            },
            "data": [
                {
                    "type": "us_debit_visa_card",
                    "name": "Visa",
                    "category": "card",
                    "image": "https://iconslib.rapyd.net/checkout/us_visa_card.png",
                    "country": "US",
                    "payment_flow_type": "card",
                    "currencies": [
                        "USD"
                    ],
                    "status": 1,
                    "is_cancelable": false,
                    "payment_options": [],
                    "is_expirable": false,
                    "is_online": false,
                    "minimum_expiration_seconds": null,
                    "maximum_expiration_seconds": null
                }
            ]
        }

The data section of this response shows that us_debit_visa_card is an acceptable payment method.

Note: A real response usually lists many payment methods.

You need to find which fields the customer must fill in for the payment method.

For that, you'll use Get Payment Method Required Fields with the following parameter:

Description of Path Parameters

Path Parameter

Description

type

Enter us_debit_visa_card as the payment method type.

Get Payment Method Required Fields Request

You ask for the set of required fields for a us_debit_visa_card payment.

    • Request

      • / Request URL: GET https://sandboxapi.rapyd.net/v1/payment_methods/us_debit_visa_card/required_fields
        
        // Message body absent
    • .NET Core

      • using System;
        
        namespace RapydApiRequestSample
        {
            class Program
            {
                static void Main(string[] args)
                {
                    try
                    {
                        string type = "us_visa_card";
        
                        string result = RapydApiRequestSample.Utilities.MakeRequest("GET", $"/v1/payment_methods/{type}/required_fields");
        
                        Console.WriteLine(result);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Error completing request: " + e.Message);
                    }
                }
            }
        }
    • JavaScript

      • const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;
        
        async function main() {
          try {
            const result = await makeRequest('GET', '/v1/payment_methods/us_visa_card/required_fields');
        
            console.log(result);
          } catch (error) {
            console.error('Error completing request', error);
          }
        }
    • PHP

      • <?php
        $path = $_SERVER['DOCUMENT_ROOT'];
        $path .= "/<path-to-your-utility-file>/utilities.php";
        include($path);
        
        try {
            $object = make_request('get', '/v1/payment_methods/us_visa_card/required_fields');
            var_dump($object);
        } catch (Exception $e) {
            echo "Error: $e";
        }
        ?>
    • Python

      • from pprint import pprint
        
        from utilities import make_request
        
        payment_method = 'us_visa_card'
        results = make_request(method='get',
                               path=f'/v1/payment_methods/{payment_method}/required_fields')
        pprint(results)
Get Payment Method Required Fields Response

Let's take a look at the response.

    • Response

      • {
            "status": {
                "error_code": "",
                "status": "SUCCESS",
                "message": "",
                "response_code": "",
                "operation_id": "0cd7be44-fd91-4b27-941f-158f5e47fb7c"
            },
            "data": {
                "type": "us_debit_visa_card",
                "fields": [
                    {
                        "name": "number",
                        "type": "string",
                        "regex": "",
                        "is_required": true,
                        "instructions": "card number"
                    },
                    {
                        "name": "expiration_month",
                        "type": "string",
                        "regex": "",
                        "is_required": true,
                        "instructions": "expiration month as string, 01-12"
                    },
                    {
                        "name": "expiration_year",
                        "type": "string",
                        "regex": "",
                        "is_required": true,
                        "instructions": "expiration year in to digits as string, 18-99"
                    },
                    {
                        "name": "cvv",
                        "type": "string",
                        "regex": "",
                        "is_required": true,
                        "instructions": "card cvv"
                    },
                    {
                        "name": "name",
                        "type": "string",
                        "regex": "",
                        "is_required": false,
                        "instructions": "card holder name"
                    },
                    {
                        "name": "address",
                        "type": "Address",
                        "regex": "",
                        "is_required": false,
                        "instructions": "card billing address. see Address object for more details"
                    }
                ],
                "payment_method_options": [
                    {
                        "name": "3d_required",
                        "type": "string",
                        "regex": "",
                        "description": "",
                        "is_required": false,
                        "is_updatable": false
                    }
                ],
                "payment_options": [],
                "minimum_expiration_seconds": null,
                "maximum_expiration_seconds": null
            }
        }

The data section of this response shows that five fields are required for a us_debit_visa_card payment. These fields are number, expiration_month , expiration_year, cvv, and name .

John Doe makes the following purchases on your marketplace website:

  • A speaker from one seller for 50.00 USD (U.S. Dollars).

  • A phone from another seller for 200.00 USD (U.S. Dollars).

You ask Rapyd to process the payment and include an escrow to hold the funds for five days.

For that, you'll use Create Payment with the following parameters:

Description of Body Parameters

Body Parameter

Description

amount

Enter 250 as the total amount of the payment.

currency

Enter USD as the code for U.S. Dollars.

payment_method

Enter a 'payment_method' object that has the following fields:

  • type - Enter us_debit_visa_card as the type of credit card.

  • Enter a 'fields' object that has the following fields:

    • number - Enter 4111111111111111 .

    • expiration_month - Enter 10.

    • expiration_year - Enter 22.

    • cvv - Enter 123.

    • name - Enter John Doe.

ewallets

Enter an 'ewallets' array that has two objects with the following fields:

First object:

  • ewallet - Enter the Rapyd Wallet 'id' that you received when you created the speaker seller's wallet in your sandbox. For purposes of this use case lesson, we are using ewallet_090e1ef18c3aa754fd43cce9ee454858, which is the wallet ID we created in our sandbox.

  • amount - Enter 50 as the amount to pay the speaker seller.

Second object:

  • ewallet - Enter the wallet 'id' that you received when you created the phone seller's wallet in your sandbox. For purposes of this use case lesson, we are using ewallet_11078019438f943986c1fcfbaba05e13, which is the wallet ID we created in our sandbox.

  • amount - Enter 200 as the amount to pay the phone seller.

escrow

Enter true to enable the escrow.

escrow_release_days

Enter 5 as the number of days before the escrow funds are automatically released.

Create Payment Request

You ask Rapyd to process the payment and escrow payment.

    • Request

      • // Request URL: POST https://sandboxapi.rapyd.net/v1/payments
        
        // Message body:
        {
                "amount": 250,
                "currency": "USD",
                "requested_currency": "USD",
                "payment_method": {
                        "type": "us_debit_visa_card",
                        "fields": {
                                "number": "4111111111111111",
                                "expiration_month": "10",
                                "expiration_year": "20",
                                "cvv": "123",
                                "name": "Test User"
                        }
                },
                "ewallets": [
                        {
                                "ewallet": "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                                "amount": 50
                        }, {
                                "ewallet": "ewallet_11078019438f943986c1fcfbaba05e13",
                                "amount": 200
                        }
                ],
                "escrow": true,
                "escrow_release_days": "5"
        }
    • Python

      • from pprint import pprint
        
        from utilities import make_request
        
        payment_body = {
            "amount": 250,
            "currency": "USD",
            "requested_currency": "USD",
            "payment_method": {
                "type": "us_visa_card",
                "fields": {
                    "number": "4111111111111111",
                    "expiration_month": "10",
                    "expiration_year": "20",
                    "cvv": "123",
                    "name": "John Doe"
                }
            },
            "ewallets": [
                {
                    "ewallet": "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                    "amount": 50
                }, {
                    "ewallet": "ewallet_11078019438f943986c1fcfbaba05e13",
                    "amount": 200
                }
            ],
            "escrow": True,
            "escrow_release_days": "5"
        }
        
        create_payment_response = make_request(method='post',
                                               path='/v1/payments',
                                               body=payment_body)
        pprint(create_payment_response)
Create Payment Response

Let's take a look at the response.

    • Response

      • {
            "status": {
                "error_code": "",
                "status": "SUCCESS",
                "message": "",
                "response_code": "",
                "operation_id": "2eb07c96-f541-43fa-bd33-3599c7ebb033"
            },
            "data": {
                "id": "payment_3b01b41950ec59d92c532974edc8f7dd",
                "amount": 250,
                "original_amount": 250,
                "is_partial": false,
                "currency_code": "USD",
                "country_code": "US",
                "status": "CLO",
                "description": "",
                "merchant_reference_id": "",
                "customer_token": "cus_30896ef7ee24397f340cc64a1f474697",
                "payment_method": "card_cf53c0452fb183a09d1fff2f16577b74",
              
        //   ...
                  
                "created_at": 1580986835,
              
        //   ...         
              
                "paid": true,
                "paid_at": 1580986836,
                
        //   ...         
                  
                "ewallets": [
                    {
                        "ewallet_id": "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                        "amount": 200,
                        "percent": 0,
                        "released_amount": 0,
                        "refunded_amount": 0
                    },
                    {
                        "ewallet_id": "ewallet_11078019438f943986c1fcfbaba05e13",
                        "amount": 50,
                        "percent": 80,
                        "released_amount": 0,
                        "refunded_amount": 0
                    }
                ],
                "payment_method_options": {},
                "payment_method_type": "us_debit_visa_card",
                "payment_method_type_category": "card",
               
         //   ...                  
                  
                "escrow": {
                    "id": "escrow_150c88345d2bca0a8be05e54a952cc80",
                    "payment": "payment_3b01b41950ec59d92c532974edc8f7dd",
                    "amount_on_hold": 250,
                    "total_amount_released": 0,
                    "status": "on_hold",
                    "escrow_release_days": 5,
                    "created_at": 1580986835,
                    "updated_at": 1580986835,
                    "last_payment_completion": 1580986836
                },
                "group_payment": ""
            }
        }

The data section of this response shows that:

  • The amount is 250.

  • The currency is USD.

  • The ewallets object indicates:

    • An amount of 50 is held in escrow for ewallet_idewallet_090e1ef18c3aa754fd43cce9ee454858 .

    • An amount of 200 is held in escrow for ewallet_idewallet_11078019438f943986c1fcfbaba05e13 .

  • The escrow object indicates:

    • Its id is escrow_150c88345d2bca0a8be05e54a952cc80 .

    • The payment ID is payment_3b01b41950ec59d92c532974edc8f7dd.

    • The amount_on_hold is 250.

    • The status is on_hold.

    • The escrow_release_days is 5.

When you ask Rapyd to release the funds to the speaker seller, you will use the speaker seller's ewallet_id, the escrow object's id and the payment ID .

You decide to immediately release the funds of 50 USD (U.S. Dollars) to the seller of the speaker.

For that, you'll use Release Funds from Escrow with the following parameters:

Description of Path Parameters

Path Parameter

Description

payment

Enter the payment ID 'id' that you received when you created the payment in your sandbox. For purposes of this use case lesson, we are using payment_3b01b41950ec59d92c532974edc8f7dd, which is the payment ID we created in our sandbox.

escrow

Enter the escrow ID 'id' that you received when you created the payment in your sandbox. For purposes of this use case lesson, we are using escrow_150c88345d2bca0a8be05e54a952cc80, which is the escrow ID we created in our sandbox.

Description of Body Parameters

Body Parameter

Description

ewallets

Enter an 'ewallets' array with one object that has the following fields:

  • ewallet - Enter the Rapyd Wallet 'id' that you received when you created the speaker seller's wallet in your sandbox. For purposes of this use case lesson, we are using ewallet_090e1ef18c3aa754fd43cce9ee454858, which is the wallet ID we created in our sandbox.

  • amount - Enter 50 as the amount to release to the speaker seller.

Release Funds from Escrow Request

You ask Rapyd to release the funds to a seller.

    • Request

      • // Request URL: POST https://sandboxapi.rapyd.net/v1/payments/payment_3b01b41950ec59d92c532974edc8f7dd/escrows/escrow_150c88345d2bca0a8be05e54a952cc80/escrow_releases
        
        // Message body:
        {
        "ewallets": [
                        {
                                "ewallet": "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                                "amount": 50
                        }
          ]
        }
    • .NET Core

      • using System;
        using System.Text.Json;
        
        namespace RapydApiRequestSample
        {
            class Program
            {
                static void Main(string[] args)
                {
                    try
                    {
                        string payment = "payment_3b01b41950ec59d92c532974edc8f7dd";
                        string escrow = "escrow_150c88345d2bca0a8be05e54a952cc80";
        
                        var requestObj = new
                        {
        
                            ewallets = new Object[]
                            {
                                new {
                                    ewallet =  "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                                    amount = 50
                                },
                            }
                        };
        
                        string request = JsonSerializer.Serialize(requestObj);
        
                        string result = RapydApiRequestSample.Utilities.MakeRequest("POST", $"/v1/payments/{payment}/escrows/{escrow}/escrow_releases", request);
        
                        Console.WriteLine(result);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Error completing request: " + e.Message);
                    }
                }
            }
        }
    • PHP

      • <?php
        $path = $_SERVER['DOCUMENT_ROOT'];
        $path .= "/<path-to-your-utility-file>/utilities.php";
        include($path);
        
        $body = [
            array(
                "ewallet" => "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                "amount" => 50
            )
        ];
        
        try {
            $object = make_request('post', '/v1/payments/payment_3b01b41950ec59d92c532974edc8f7dd/escrows/escrow_150c88345d2bca0a8be05e54a952cc80/escrow_releases', $body);
            var_dump($object);
        } catch (Exception $e) {
            echo "Error: $e";
        }
        ?>
    • Python

      • from pprint import pprint
        
        from utilities import make_request
        
        release_funds_body = {
            "ewallets": [
                {
                    "ewallet": "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                    "amount": 50
                }
            ]
        }
        release_funds_response = make_request(method='post',
                                              path='/v1/payments/payment_3b01b41950ec59d92c532974edc8f7dd/escrows/escrow_150c88345d2bca0a8be05e54a952cc80/escrow_releases',
                                              body=release_funds_body)
        pprint(release_funds_response)
Release Funds from Escrow Response

Let's take a look at the response.

    • Response

      • {
            "status": {
                "error_code": "",
                "status": "SUCCESS",
                "message": "",
                "response_code": "",
                "operation_id": "8338da6d-997c-41fb-97ef-def18c133224"
            },
            "data": {
                "id": "escrow_150c88345d2bca0a8be05e54a952cc80",
                "payment": "payment_3b01b41950ec59d92c532974edc8f7dd",
                "amount_on_hold": 250,
                "total_amount_released": 50,
                "status": "released",
                "escrow_release_days": 5,
                "escrow_releases": {
                    "data": [
                        {
                            "id": "er_ac023aae3b13b0e74ad64c876b1034dd",
                            "amount": 50,
                            "trigger": "event",
                            "proportional_release": false,
                            "ewallets": [
                                {
                                    "ewallet": "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                                    "amount": 250
                                }
                            ],
                            "created_at": 1580987535
                        }
                    ],
                    "has_more": false,
                    "total_count": 1,
                    "url": "/v1/payments/payment_3b01b41950ec59d92c532974edc8f7dd/escrows/escrow_150c88345d2bca0a8be05e54a952cc80/escrow_releases"
                },
                "created_at": 1580986835,
                "updated_at": 1580987535,
                "last_payment_completion": 1580986836
            }
        }

The data section of this response shows that:

  • The amount_on_hold is 250.

  • The escrow_releases object indicates:

    • An amount of 50 USD was released to ewallet_idewallet_090e1ef18c3aa754fd43cce9ee454858

  • The escrow_release_days is 5.

After five days, 50 USD is automatically released to ewallet_11078019438f943986c1fcfbaba05e13. For a list of all releases of funds from this escrow, run List Escrow Releases.