# 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](/products/payments-odl/api-docs/ripplenet/tutorials/receive-a-payment/receive-a-payment-basic). 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](/products/payments-odl/api-docs/ripplenet/best-practices/webhooks). ## Overview Note Before you read this tutorial, make sure you're familiar with the concepts presented in [Payment flow](/products/payments-odl/introduction/concepts/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](/products/payments-odl/api-docs/ripplenet/best-practices/authentication) | [auth](/products/payments-odl/api-docs/ripplenet/best-practices/authentication#determine-the-desired-environment) | Receiver requests a *bearer token* for authentication/authorization for use with authorized RippleNet API operations. | | [Lock payment](#lock-payment) | [*Lock payment*](/products/payments-odl/api-docs/ripplenet/reference/openapi/non-orchestration-payments/lockpayment) | 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) | [*Complete payment*](/products/payments-odl/api-docs/ripplenet/reference/openapi/non-orchestration-payments/completepayment) | 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](/products/payments-odl/api-docs/ripplenet/tutorials/non-orchestration/send-a-payment-advanced) 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](/products/payments-odl/api-docs/ripplenet/test-automation/test-harness-overview) 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](https://www.getpostman.com), 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](https://www.getpostman.com) or [Insomnia](https://insomnia.rest/). You can import the **cURL** examples into these clients. For more information, see: * [Import and Export Data](https://support.insomnia.rest/article/52-importing-and-exporting-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](/products/payments-odl/api-docs/ripplenet/best-practices/baseurls). #### 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](/products/payments-odl/api-docs/ripplenet/reference/openapi/quotes/acceptquote) and [Settle payment](/products/payments-odl/api-docs/ripplenet/reference/openapi/non-orchestration-payments/settlepayment)) 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](/products/payments-odl/api-docs/ripplenet/best-practices/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*](/products/payments-odl/api-docs/ripplenet/reference/openapi/non-orchestration-payments/lockpayment) 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](/products/payments-odl/api-docs/ripplenet/tutorials/non-orchestration/send-a-payment-advanced#check-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** ```json GET /v4/payments/?state=ACCEPTED HTTP/1.1 Host: south-bank.ripplenet.com Authorization: Bearer 5ld1ye ... ``` **Get payments: cURL request** ```json 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. details summary Click to view the response ... ```json { "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: 1. Gather the `quote_id` for the quote that you want to lock for your partner institution. 2. Make a *Lock payment* request containing an empty an empty JSON object: `{}` **Lock payment: HTTP request** ```json 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** ```json 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](/products/payments-odl/introduction/concepts/payment-states). details summary Click to view the response ... ```json { "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*](/products/payments-odl/api-docs/ripplenet/reference/openapi/non-orchestration-payments/completepayment) 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** ```json 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: 1. Gather the `payment_id` for the payment that you want to mark complete. 2. Make a *Complete payment* request to RippleNet with the value of the `payment_id`. The request format is `POST /v4/payments/{PAYMENT_ID}/settle`. **Complete payment: HTTP request** ```json 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`. details summary Click to view the response ... ```json { "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](/products/payments-odl/introduction/concepts/payment-states).