Receiver payment flow — non-orchestration
This page is for developers of existing receiver integrations that already use the API operations that pre-date Ripple orchestration payments.
Note
If you are developing a new integration, you should instead use the orchestration API operations. See Receive a payment.
If you want to use webhooks notifications with your integration, you must use the orchestration API operations. The Lock payment and Complete payment operations described in this topic do not support webhooks. For more information about webhooks, see Webhook notification.
Overview
Note
Before you read this tutorial, make sure you're familiar with the concepts presented in Payment flow.
The following table describes the tasks required to receive a payment using the Lock payment and Complete payment API operations.
Payment flow step | Related API operation | Description |
---|---|---|
Authorization | auth | Receiver requests a bearer token for authentication/authorization for use with authorized RippleNet API operations. |
Lock payment | Lock payment | Receiver agrees to the payment terms that the sender has already accepted. This changes the payment state from ACCEPTED to LOCKED . |
Complete payment | Complete payment | Receiver confirms receipt of the payment and the payout to the beneficiary. This changes the payment state to COMPLETED . |
Receiving a payment
The combined steps in this tutorial and Sender payment flow — non-orchestration simulate sending one 10-USD payment from the sender, North Bank, to the receiver, South Bank. To simplify the tutorial, no FX exchange rates are applied to the payment.
Prerequisites
Before you begin, you must have the following:
- Access to your RippleNet test instance.
- Access to a counterparty instance; either a test harness server that Ripple provides or a counterparty's UAT instance.
- Credentials to authenticate API authorization to your RippleNet test instance.
- A way to make API requests and view the responses. For example, you can use a REST client like Postman , or cURL from the command line.
Using the RippleNet Server API
The following sections describe the requirements for using the RippleNet Server API.
REST clients
To test the HTTP requests and responses described in this tutorial, use a REST client such as Postman or Insomnia.
You can import the cURL examples into these clients.
For more information, see:
- Import and Export Data in the Insomnia documentation.
Base URL
The base URL is derived from the HTTPS path of the server running RippleNet. It includes the protocol (http://
or https://
) and the domain. It does not include the API version.
For example, the base URL for a payment sender in this tutorial is https://sf-bank.ripplenet.com
.
For more information about base URLs, see API base URLs.
Required headers
All RippleNet API operations (except authentication) must contain the following header:
Authorization: Bearer {VALID_ACCESS_TOKEN}
All POST requests (such as Accept quote and Settle payment) must also contain the following header:
Content-Type: application/json
Authentication
To use RippleNet you need a valid access token for all operations except the Authentication operation itself. For more information, see Authentication.
Lock payment
After authentication to the API, the first step to receive payments is to check for payments with the ACCEPTED
state. These are payments that need to be locked. Locking a payment means your institution agrees to, and locks, the terms of the payment.
When your institution (as the receiver) agrees to proceed with the payment by making a successful Lock payment request, the payment's state becomes LOCKED
.
For more information, see Lock payment in the RippleNet API Reference.
Poll for accepted quotes
To check for payments that need to be locked, poll your RippleNet instance for payments with the ACCEPTED
state.
Tip
You can fetch the details for an individual payment at any point by Checking the status of a payment. The payment state is one useful detail in a successful response.
Make a Get payments request for payments with the state of ACCEPTED
:
Get payments: HTTP request
GET /v4/payments/?state=ACCEPTED HTTP/1.1
Host: south-bank.ripplenet.com
Authorization: Bearer 5ld1ye ...
Get payments: cURL request
curl -X GET \
'https://south-bank.ripplenet.com/v4/payments/?state=ACCEPTED' \
-H 'Authorization: Bearer 5ld1ye ...'
If the request is successful, Get payments returns HTTP status 200 OK
and a response similar to the following example. Notice that the payment is in the ACCEPTED
state.
Click to view the response ...
{
"payment_id": "43-bba3-f52c40c91e-d8a05234-8dbbf844",
"contract_hash": "30a58cb704ef66a2ef266687aab48320b455601941263dc9cce77e95127d84bc",
"internal_info": {
"connector_role": "SENDING",
"labels": [],
"internal_id": null
},
"payment_state": "ACCEPTED",
"modified_at": "2019-07-29T18:56:11.519Z",
"contract": {
"sender_end_to_end_id": null,
"created_at": "2019-07-29T18:55:56.617Z",
"expires_at": "2019-07-29T19:55:53.781Z",
"quote": {
"quote_id": "ef829465-62f3-4192-80c2-b04be8c84949",
"created_at": "2019-07-29T18:55:53.781Z",
"expires_at": "2019-07-29T19:55:53.781Z",
"type": "SENDER_AMOUNT",
"price_guarantee": "FIRM",
"sender_address": "transactional_usd@test.north-bank.com",
"receiver_address": "tinycorp_transactional_usd1@dev.xcurrent.tinycorp",
"amount": "10.010000000",
"currency_code": "USD",
"currency_code_filter": null,
"service_type": null,
"quote_elements": [
{
"quote_element_id": "419456bf-2ff1-4f54-afc2-aefb791298df",
"quote_element_type": "TRANSFER",
"quote_element_order": "1",
"sender_address": "transactional_usd@test.north-bank.com",
"receiver_address": "north_nostro_usd@test.north-bank.com",
"sending_amount": "10.000000000",
"receiving_amount": "10.000000000",
"sending_fee": "0.010000000",
"receiving_fee": "0.000000000",
"sending_currency_code": null,
"receiving_currency_code": null,
"fx_rate": null,
"transfer_currency_code": "USD"
},
{
"quote_element_id": "346b3a55-cc17-456b-b612-7e9eb0603fd1",
"quote_element_type": "TRANSFER",
"quote_element_order": "2",
"sender_address": "south_vostro_usd@test.south-bank.com",
"receiver_address": "south_transactional_usd1@test.south-bank.com",
"sending_amount": "10.000000000",
"receiving_amount": "10.000000000",
"sending_fee": "0.000000000",
"receiving_fee": "0.000000000",
"sending_currency_code": null,
"receiving_currency_code": null,
"fx_rate": null,
"transfer_currency_code": "USD"
}
],
"liquidity_warning": null,
"payment_method": null
}
},
"user_info": [
{
"node_address": "test.north-bank.com",
"accepted": [
{
"json": [
{
"key": "accept",
"value": "value"
}
],
"created_at": "2019-07-29T18:55:56.719Z",
"subState": ""
}
],
"locked": [],
"lock_declined": [],
"retry_accept": [],
"retry_settlement": [],
"settlement": [],
"settlement_declined": [],
"failed": [],
"executed": [],
"completed": [],
"forwarded": [],
"returned": []
}
],
"ripplenet_info": [],
"execution_condition": "PrefixSha256Condition{subtypes=[ED25519-SHA-256], type=PREFIX-SHA-256, fingerprint=HB5qYUfvQacxNn-eEpCsZ36WpG2-tCSvhJMegYNxXkE, cost=132360}",
"crypto_transaction_id": "4123817-9736-4ggg-a3c7-50fc1010916e",
"validator": "dev.xcurrent.aperture",
"payment_type": "REGULAR",
"returns_payment_with_id": null,
"returned_by_payment_with_id": null,
"execution_results": []
}
Lock the payment
To lock an accepted quote with the API, complete the following steps:
-
Gather the
quote_id
for the quote that you want to lock for your partner institution. -
Make a
Lock payment
request containing an empty an empty JSON object:
{}
Lock payment: HTTP request
POST /v4/payments/43-bba3-f52c40c91e-d8a05234-8dbbf844/lock HTTP/1.1
Host: south-bank.ripplenet.com
Content-Type: application/json
Authorization: Bearer 5ld1ye ...
{}
Lock payment: cURL Request
curl -X POST \
https://south-bank.ripplenet.com/v4/payments/43-bba3-f52c40c91e-d8a05234-8dbbf844/lock \
-H 'Authorization: Bearer 5ld1ye ...' \
-H 'Content-Type: application/json' \
-d '{}'
Note
The Lock payment POST request must contain an empty JSON object: {}
.
If the request is successful, Lock payment returns HTTP status 200 OK
and a response similar to the following example. Notice that the payment state has changed from ACCEPTED
to LOCKED
. For more information about payment states, see Payment states.
Click to view the response ...
{
"payment_id": "43-bba3-f52c40c91e-d8a05234-8dbbf844",
"contract_hash": "30a58cb704ef66a2ef266687aab48320b455601941263dc9cce77e95127d84bc",
"internal_info": {
"connector_role": "RECEIVING",
"labels": [],
"internal_id": null
},
"payment_state": "LOCKED",
"modified_at": "2019-07-29T18:56:10.55Z",
"contract": {
"sender_end_to_end_id": null,
"created_at": "2019-07-29T18:55:56.617Z",
"expires_at": "2019-07-29T19:55:53.781Z",
"quote": {
"quote_id": "ef829465-62f3-4192-80c2-b04be8c84949",
"created_at": "2019-07-29T18:55:53.781Z",
"expires_at": "2019-07-29T19:55:53.781Z",
"type": "SENDER_AMOUNT",
"price_guarantee": "FIRM",
"sender_address": "transactional_usd@test.north-bank.com",
"receiver_address": "south_transactional_usd1@test.south-bank.com",
"amount": "10.010000000",
"currency_code": "USD",
"currency_code_filter": null,
"service_type": null,
"quote_elements": [
{
"quote_element_id": "419456bf-2ff1-4f54-afc2-aefb791298df",
"quote_element_type": "TRANSFER",
"quote_element_order": "1",
"sender_address": "transactional_usd@test.north-bank.com",
"receiver_address": "north_nostro_usd@test.north-bank.com",
"sending_amount": "10.000000000",
"receiving_amount": "10.000000000",
"sending_fee": "0.010000000",
"receiving_fee": "0.000000000",
"sending_currency_code": null,
"receiving_currency_code": null,
"fx_rate": null,
"transfer_currency_code": "USD"
},
{
"quote_element_id": "346b3a55-cc17-456b-b612-7e9eb0603fd1",
"quote_element_type": "TRANSFER",
"quote_element_order": "2",
"sender_address": "south_vostro_usd@test.south-bank.com",
"receiver_address": "south_transactional_usd1@test.south-bank.com",
"sending_amount": "10.000000000",
"receiving_amount": "10.000000000",
"sending_fee": "0.000000000",
"receiving_fee": "0.000000000",
"sending_currency_code": null,
"receiving_currency_code": null,
"fx_rate": null,
"transfer_currency_code": "USD"
}
],
"liquidity_warning": null,
"payment_method": null
}
},
"user_info": [
{
"node_address": "test.north-bank.com",
"accepted": [
{
"json": [
{
"key": "accept",
"value": "value"
}
],
"created_at": "2019-07-29T18:55:56.719Z",
"subState": ""
}
],
"locked": [],
"lock_declined": [],
"retry_accept": [],
"retry_settlement": [],
"settlement": [],
"settlement_declined": [],
"failed": [],
"executed": [],
"completed": [],
"forwarded": [],
"returned": []
}
],
"ripplenet_info": [],
"execution_condition": "PrefixSha256Condition{subtypes=[ED25519-SHA-256], type=PREFIX-SHA-256, fingerprint=HB5qYUfvQacxNn-eEpCsZ36WpG2-tCSvhJMegYNxXkE, cost=132360}",
"crypto_transaction_id": null,
"validator": "test.north-bank.com",
"payment_type": "REGULAR",
"returns_payment_with_id": null,
"returned_by_payment_with_id": null,
"execution_results": []
}
Complete payment
After you, as receiver, have locked the payment, the sender institution will make a request to settle the payment. The payment can be then paid out to the beneficiary, the relevant accounts on your ledgers can be settled, and the payment can be completed.
The payout to the beneficiary can be completed by a RippleNet institution or through a partner on local rails. Then, as the receiver institution involved in the payment, you must signal that the payment beneficiary has received the payment.
To indicate to RippleNet that the beneficiary received their payment, the receiver institution must make a request to the Complete payment operation. A successful call to Complete payment changes the payment state to COMPLETED
, signaling to RippleNet that the payment is executed, settled, and paid out to the beneficiary.
Note
In a typical payment flow, you would verify out-of-band that the beneficiary has received the payment before you take action to complete the payment. This tutorial does not include this step.
For more information, see Complete payment in the RippleNet Server API reference.
Poll for executed payments
To check for payments that need to be completed, use the Get payments operation to poll for payments in the EXECUTED
state:
Get payments: HTTP request
GET /v4/payments/?state=EXECUTED HTTP/1.1
Host: south-bank.ripplenet.com
Authorization: Bearer 5ld1ye ...
Get payments: cURL request
curl -X GET \
https://south-bank.ripplenet.com/v4/payments/?state=EXECUTED \
-H Authorization: Bearer 5ld1ye ...
If the request is successful, Get payments returns HTTP status 200 OK
and a response similar to the example above for the ACCEPTED
payment, except that the payment is now in the EXECUTED
state.
Complete the payment
Follow these steps to complete the payment:
-
Gather the
payment_id
for the payment that you want to mark complete. -
Make a
Complete payment
request to RippleNet with the value of the
payment_id
. The request format isPOST /v4/payments/{PAYMENT_ID}/settle
.
Complete payment: HTTP request
POST /v4/payments/43-bba3-f52c40c91e-d8a05234-8dbbf844/complete HTTP/1.1
Host: north-bank.ripplenet.com
Content-Type: application/json
Authorization: Bearer 5ld1ye ...
{}
Complete payment: cURL request
curl -X POST \
https://north-bank.ripplenet.com/v4/payments/43-bba3-f52c40c91e-d8a05234-8dbbf844/complete \
-H 'Authorization: Bearer 5ld1ye ...' \
-d '{}'
If the request is successful, Complete payment returns HTTP status 200 OK
and a response similar to the following example. The payment instructions have been successfully sent. The payment changes state from the status of EXECUTING
to COMPLETED
.
Click to view the response ...
{
"payment_id": "43-bba3-f52c40c91e-d8a05234-8dbbf844",
"contract_hash": "30a58cb704ef66a2ef266687aab48320b455601941263dc9cce77e95127d84bc",
"internal_info": {
"connector_role": "RECEIVING",
"labels": [],
"internal_id": null
},
"payment_state": "COMPLETED",
"modified_at": "2019-07-29T18:56:18.607Z",
"contract": {
"sender_end_to_end_id": null,
"created_at": "2019-07-29T18:55:56.617Z",
"expires_at": "2019-07-29T19:55:53.781Z",
"quote": {
"quote_id": "ef829465-62f3-4192-80c2-b04be8c84949",
"created_at": "2019-07-29T18:55:53.781Z",
"expires_at": "2019-07-29T19:55:53.781Z",
"type": "SENDER_AMOUNT",
"price_guarantee": "FIRM",
"sender_address": "transactional_usd@test.north-bank.com",
"receiver_address": "south_transactional_usd1@test.south-bank.com",
"amount": "10.010000000",
"currency_code": "USD",
"currency_code_filter": null,
"service_type": null,
"quote_elements": [
{
"quote_element_id": "419456bf-2ff1-4f54-afc2-aefb791298df",
"quote_element_type": "TRANSFER",
"quote_element_order": "1",
"sender_address": "transactional_usd@test.north-bank.com",
"receiver_address": "north_nostro_usd@test.north-bank.com",
"sending_amount": "10.000000000",
"receiving_amount": "10.000000000",
"sending_fee": "0.010000000",
"receiving_fee": "0.000000000",
"sending_currency_code": null,
"receiving_currency_code": null,
"fx_rate": null,
"transfer_currency_code": "USD"
},
{
"quote_element_id": "346b3a55-cc17-456b-b612-7e9eb0603fd1",
"quote_element_type": "TRANSFER",
"quote_element_order": "2",
"sender_address": "south_vostro_usd@test.south-bank.com",
"receiver_address": "south_transactional_usd1@test.south-bank.com",
"sending_amount": "10.000000000",
"receiving_amount": "10.000000000",
"sending_fee": "0.000000000",
"receiving_fee": "0.000000000",
"sending_currency_code": null,
"receiving_currency_code": null,
"fx_rate": null,
"transfer_currency_code": "USD"
}
],
"liquidity_warning": null,
"payment_method": null
}
},
"user_info": [
{
"node_address": "test.north-bank.com",
"accepted": [
{
"json": [
{
"key": "accept",
"value": "value"
}
],
"created_at": "2019-07-29T18:55:56.719Z",
"subState": ""
}
],
"locked": [],
"lock_declined": [],
"retry_accept": [],
"retry_settlement": [],
"settlement": [],
"settlement_declined": [],
"failed": [],
"executed": [],
"completed": [],
"forwarded": [],
"returned": []
}
],
"ripplenet_info": [],
"execution_condition": "PrefixSha256Condition{subtypes=[ED25519-SHA-256], type=PREFIX-SHA-256, fingerprint=HB5qYUfvQacxNn-eEpCsZ36WpG2-tCSvhJMegYNxXkE, cost=132360}",
"crypto_transaction_id": "46950817-9736-4fff-a2b7-50fb2510916e",
"validator": "test.north-bank.com",
"payment_type": "REGULAR",
"returns_payment_with_id": null,
"returned_by_payment_with_id": null,
"execution_results": [
{
"execution_result_id": "419456bf-2ff1-4f54-afc2-aefb791298df",
"execution_timestamp": "2019-07-29T18:56:14.18Z",
"execution_result_type": "TRANSFER",
"execution_result_order": "1",
"sender_address": "transactional_usd@test.north-bank.com",
"receiver_address": "north_nostro_usd@test.north-bank.com",
"sending_amount": "10.000000000",
"receiving_amount": "10.000000000",
"sending_fee": "0.010000000",
"receiving_fee": "0.000000000",
"sending_currency_code": null,
"receiving_currency_code": null,
"fx_rate": null,
"transfer_currency_code": null,
"intermediary_delta": null,
"incentive_type": null
},
{
"execution_result_id": "346b3a55-cc17-456b-b612-7e9eb0603fd1",
"execution_timestamp": "2019-07-29T18:56:07.01Z",
"execution_result_type": "TRANSFER",
"execution_result_order": "2",
"sender_address": "south_vostro_usd@test.south-bank.com",
"receiver_address": "south_transactional_usd1@test.south-bank.com",
"sending_amount": "10.000000000",
"receiving_amount": "10.000000000",
"sending_fee": "0.000000000",
"receiving_fee": "0.000000000",
"sending_currency_code": null,
"receiving_currency_code": null,
"fx_rate": null,
"transfer_currency_code": null,
"intermediary_delta": null,
"incentive_type": null
}
]
}
For more information about payment states, see Payment states.