Escrow

Hold any payment method in escrow for later release.

Hold a payment in escrow

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 backend, and holds funds using a Rapyd Wallet. When the purchase is made, your website backend 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.

Multiple Releases to a Seller Workflow

A customer purchases an item for $2000 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 PCIPCI - Payment Card Industry certification can handle personal identifying information for cards.

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.

  1. A customer on your marketplace purchases a product from a seller.
  2. The website backend 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

  1. The website backend 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.

How It Works

👍

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.

Finding Available Payment Methods

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 United States dollars (USD) in the United States.

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

Query Parameter

Description

country

Enter US as the country code for the United States.

currency

Enter USD as the currency code for United States dollars.

List Payment Methods by Country request

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

// Request URL: GET https://sandboxapi.rapyd.net/v1/payment_methods/country?country=US&currency=USD

// Message body absent
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);
            }
        }
    }
}
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
$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";
}
?>
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. Payment Method Object describes the fields in the response.

{
    "status": {
        "error_code": "",
        "status": "SUCCESS",
        "message": "",
        "response_code": "",
        "operation_id": "2ef3f76f-6a57-4d1f-bf60-162313d304bc"
    },
    "data": [
        {
            "type": "us_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_visa_card is an acceptable payment method.

Note that a real response usually lists many payment methods.

Finding Required Fields for the Payment Method

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:

Path Parameter

Description

type

Enter us_visa_card as the payment method type.

Get Payment Method Required Fields request

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

/ Request URL: GET https://sandboxapi.rapyd.net/v1/payment_methods/required_fields/us_visa_card

// Message body absent
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/required_fields/{type}");

                Console.WriteLine(result);
            }
            catch (Exception e)
            {
                Console.WriteLine("Error completing request: " + e.Message);
            }
        }
    }
}
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;

async function main() {
  try {
    const result = await makeRequest('GET', '/v1/payment_methods/required_fields/us_visa_card');

    console.log(result);
  } catch (error) {
    console.error('Error completing request', error);
  }
}
<?php
$path = $_SERVER['DOCUMENT_ROOT'];
$path .= "/<path-to-your-utility-file>/utilities.php";
include($path);

try {
    $object = make_request('get', '/v1/payment_methods/required_fields/us_visa_card');
    var_dump($object);
} catch (Exception $e) {
    echo "Error: $e";
}
?>
from pprint import pprint

from utilities import make_request

payment_method = 'us_visa_card'
results = make_request(method='get',
                       path=f'/v1/payment_methods/required_fields/{payment_method}')
pprint(results)

Get Payment Method Required Fields response

Let's take a look at the response. Payment Method Object describes the fields in the response.

{
    "status": {
        "error_code": "",
        "status": "SUCCESS",
        "message": "",
        "response_code": "",
        "operation_id": "0cd7be44-fd91-4b27-941f-158f5e47fb7c"
    },
    "data": {
        "type": "us_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_visa_card payment. These fields are number, expiration_month, expiration_year, cvv, and name.

Creating the Payment and Escrow

John Doe makes the following purchases on your marketplace website:

  • A speaker from one seller for $50.00.
  • A phone from another seller for $200.00.

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:

Body Parameter

Description

amount

Enter 250 as the total amount of the payment.

currency

Enter USD as the code for US dollars.

payment_method

Enter a 'payment_method' object that has the following fields:
type - Enter us_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 URL: POST https://sandboxapi.rapyd.net/v1/payments

// Message body:
{
    "amount": 2000,
    "currency": "USD",
    "requested_currency": "USD",
    "payment_method": {
        "type": "us_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": 500
        }
    ],
    "escrow": true,
    "escrow_release_days": "5"
}
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. Payment Object describes the fields in the response.

{
    "status": {
        "error_code": "",
        "status": "SUCCESS",
        "message": "",
        "response_code": "",
        "operation_id": "2eb07c96-f541-43fa-bd33-3599c7ebb033"
    },
    "data": {
        "id": "payment_3b01b41950ec59d92c532974edc8f7dd",
        "amount": 2000,
        "original_amount": 2000,
        "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": 500,
                "percent": 0,
                "released_amount": 0,
                "refunded_amount": 0
            },
            {
                "ewallet_id": "ewallet_11078019438f943986c1fcfbaba05e13",
                "amount": 200,
                "percent": 80,
                "released_amount": 0,
                "refunded_amount": 0
            }
        ],
        "payment_method_options": {},
        "payment_method_type": "us_visa_card",
        "payment_method_type_category": "card",
       
 //   ...                  
          
        "escrow": {
            "id": "escrow_150c88345d2bca0a8be05e54a952cc80",
            "payment": "payment_3b01b41950ec59d92c532974edc8f7dd",
            "amount_on_hold": 2000,
            "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 2000.
  • The currency is USD.
  • The ewallets object indicates:
  • An amount of $50 is held in escrow for ewallet_id ewallet_090e1ef18c3aa754fd43cce9ee454858.
  • An amount of $500 is held in escrow for ewallet_id ewallet_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 .

Releasing Funds to One Seller

You decide to immediately release the funds of $50 to the seller of the speaker.

For that, you'll use Release Funds from Escrow with the following 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.

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 URL: POST https://sandboxapi.rapyd.net/v1/payments/payment_3b01b41950ec59d92c532974edc8f7dd/escrows/escrow_150c88345d2bca0a8be05e54a952cc80/escrow_releases

// Message body:
{
"ewallets": [
        {
            "ewallet": "ewallet_090e1ef18c3aa754fd43cce9ee454858",
            "amount": 1500
        }
  ]
}
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
$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";
}
?>
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. Escrow Object describes the fields in the 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": 1500,
        "total_amount_released": 500,
        "status": "released",
        "escrow_release_days": 5,
        "escrow_releases": {
            "data": [
                {
                    "id": "er_ac023aae3b13b0e74ad64c876b1034dd",
                    "amount": 1500,
                    "trigger": "event",
                    "proportional_release": false,
                    "ewallets": [
                        {
                            "ewallet": "ewallet_090e1ef18c3aa754fd43cce9ee454858",
                            "amount": 1500
                        }
                    ],
                    "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 1500.
  • The escrow_releases object indicates:
  • An amount of $500 was released to ewallet_id ewallet_090e1ef18c3aa754fd43cce9ee454858
  • The escrow_release_days is 5.

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

📘

Looking for more in-depth technical information?

Want to see the Rapyd API methods and objects that you'll use?
Visit the Rapyd API Reference Documentation for more technical details.

Updated about a month ago


Escrow


Hold any payment method in escrow for later release.

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.