# Create a payment In this tutorial, we'll step through the API calls required to create a B2B payment. In a B2B payment, you - a business or institution - are the payment originator and you're paying another business or institutional beneficiary. Note While this tutorial focuses on paying a business beneficiary, the process is similar for making a payment to an individual beneficiary. To pay an individual beneficiary, specify their `beneficiary_token` in the [Accept a quote](#accept-a-quote) step. There are four main steps for creating a payment where you are the originator: 1. [Get a payout method](#get-a-payout-method) for a given country and currency. 2. [Create a quote collection](#create-a-quote-collection) for a proposed payment. 3. [Accept a quote](#accept-a-quote) to begin the payment process. 4. [Get a payment](#get-a-payment) to view your completed payment. For instructions on creating a third-party payment, where you facilitate a payment on the behalf of a third-party originator, see [Create a third-party payment](/products/payments-direct/api-docs/tutorials/create-a-third-party-payment). ## Prerequisites The following items must be addressed before you can carry out the instructions in this tutorial: * An [access token](/products/payments-direct/api-docs/tutorials/request-an-access-token) to access secured API endpoints. * The `sending_address` provided by your Ripple Liaison. You'll need this value to request a quote. * Have obtained the necessary identity tokens (see [Create an identity](/products/payments-direct/api-docs/tutorials/create-an-identity) for instructions): * A `beneficiary_token` identifies the beneficiary of your payment and is required for all payments. Base URL for the test environment The API calls in this tutorial use the **test** environment with `https://customer-name.test.rnc.ripplenet.com/v4` as the base URL. ## Get a payout method We'll start by fetching the available payout methods for a given currency in the target destination. A payout method specifies the clearing and settlement mechanisms or exchanges used to facilitate the transfer of funds, while a payment method defines how the beneficiary ultimately receives those funds. ### Payout method lookup request Use the [get a payout method](/products/payments-direct/api-docs/payments-direct-api/reference/payments-direct-api/routing/routingtablelookup) operation with the `country_code` and `payment_method` query parameters. #### Example request This example shows how to construct a query to find a payout method for a beneficiary located in Austria where the payout is in EUR. These are the query parameters: * `payment_method` : This field must be set to `BANK_PAYOUT`. * `country_code` : This example uses `AT` to represent Austria in alpha-2 format. * `payout_currency_code` : This example uses `EUR` to indicate the payout currency is euro. ```bash curl -i -X GET \ 'https://[customer-name].test.rnc.ripplenet.com/v4/config/routing_table/lookup?country_code=AT&payout_currency_code=EUR&payment_method=BANK_PAYOUT' \ -H 'Authorization: YOUR_API_KEY_HERE' ``` ### Payout method response In this example, we'll use the response of the previous request to help create the next API request. The response from the API includes the following fields: * `destination_address`: Use the value of this field as the `receiving_address` address when you create a quote collection. * `payout_method`: Use the value of this field value as the `payment_method` when you create a quote collection. In this example, `payout_method` returns `CSM_EU_EUR_SEPA` which is used in the Create quote collection operation to specify the `payment_method` parameter. ```json { "id": "235b9711-cf8c-44ea-85aa-11dbbfcfde8b", "destination_address": "rn.sgp.exampleReceiver", "payout_method": "CSM_EU_EUR_SEPA" } ``` ## Create a quote collection In this step, we call the **Create quote collection** operation, which fetches a collection of quotes containing one or more quotes for a payment using the chosen payout method. ### Create quote collection request In our payment scenario, we are sending 10,000 USD to a beneficiary in Austria, who will receive it in EUR. We have our `payment_method` value of `CSM_EU_EUR_SEPA`, so now we can construct the request body to fetch a quote. This example shows how to construct the request body to get a quote to send USD 10,000 to a beneficiary in Austria who will receive it in EUR. Prerequisite This request body includes: * The `payment_method` field uses the `payout_method` value returned by the [Get a payout method](#payout-method-response) operation. * The `receiving_address` field uses the `destination_address` value returned by the [Get a payout method](#payout-method-response) operation. * `sending_address` : Set this to the address provided by your Ripple liaison. * `receiving_address`: Set this to match the `destination_address` returned when looking up a [payout method](#get-a-payout-method). * In this example it's `rn.sgp.exampleReceiver` * `amount` : Set this value to `10000`. * `currency` : Set this value to `USD`. * `quote_type` : Set this value to `SENDER_AMOUNT`. * Setting this value returns a quote for the amount you want to send and not the amount the beneficiary of this payment will receive. * For more information, see the [quote_type param in the API reference](/products/payments-direct/api-docs/payments-direct-api/reference/payments-direct-api/quotes/createquotecollection#quotes/createquotecollection/t=request&path=quote_type). * `payment_method` : This example uses `CSM_EU_EUR_SEPA` so that it matches the response you received from the payout method lookup. #### Example quote collection request payload ```json { "sending_address": "test.usa.askYourRippleLiaisonForThisValue", "receiving_address": "test.sgp.exampleReceiver", "amount": 10000, "currency": "USD", "quote_type": "SENDER_AMOUNT", "payment_method": "CSM_EU_EUR_SEPA" } ``` ### Create quote collection response The response contains an array of one or more quote objects as a collection. Each quote object has a unique `quote_id`, and each quote contains quote elements that correspond to each step of the payment transaction and include account addresses, amounts, foreign exchange (FX) rates, and fees for each step. Quotes have an expiration date Each quote includes an `expires_at` field the indicates the expiration date and time of the quote. Quotes must be accepted prior to expiration. ```json { "quote_collection_id": "63963322-29fc-41d3-8df6-948959a5ec77", "quotes": [ { "quote_id": "203642d1-c657-4963-9620-a3f9da2cf60d", "created_at": "2024-03-22T15:13:31.275Z", "expires_at": "2024-03-22T16:13:31.275Z", "type": "SENDER_AMOUNT", "price_guarantee": "FIRM", "sender_address": "trans_usd_exampleSender@staging.usa.exampleSender", "receiver_address": "trans_aud_exampleReceiver@staging.usa.exampleReceiver", "amount": "10000", "currency_code": "USD", "currency_code_filter": null, "service_type": null, "quote_elements": [ { "quote_element_id": "25540a1f-36cf-40f6-8fb8-6abae3e890d8", "quote_element_type": "TRANSFER", "quote_element_order": "1", "sender_address": "trans_usd_exampleSender@staging.usa.exampleSender", "receiver_address": "alias_usd_exampleSender_rmde-exampleSender@staging.usa.exampleSender", "sending_amount": "10000.00", "receiving_amount": "10000.00", "sending_fee": "0.00", "receiving_fee": "0.00", "sending_currency_code": null, "receiving_currency_code": null, "fx_rate": null, "transfer_currency_code": "USD" }, { "quote_element_id": "fb68452e-acd7-45fc-85b4-ac519d6a4b95", "quote_element_type": "EXCHANGE", "quote_element_order": "2", "sender_address": "alias_usd_rmde-exampleSender@staging.usa.rmde.exampleSender", "receiver_address": "alias_usd_rmde-odl@staging.usa.rmde.exampleSender", "sending_amount": "14557.90", "receiving_amount": "14557.90", "sending_fee": "50.00", "receiving_fee": "0.0", "sending_currency_code": "USD", "receiving_currency_code": "AUD", "fx_rate": { "rate": "1.463106", "base_currency_code": "USD", "counter_currency_code": "AUD", "type": "BUY" }, "transfer_currency_code": null } ], "liquidity_warning": null, "payment_method": "CSM_EU_EUR_SEPA", "payment_method_fields": null, "payout_method_info": { "payout_method_name": "CSM_EU_EUR_SEPA", "payout_method_category": "OTHER", "description": "local rails", "estimated_time_to_credit": "5 Seconds" } } ], "quote_errors": [] } ``` ## Accept a quote Now that we have the quote for the payment, it's time to accept the quote and include the beneficiary token we generated earlier. To do this, we'll construct the [accept a quote](/products/payments-direct/api-docs/payments-direct-api/reference/payments-direct-api/quotes/acceptquote) operation. Calling this operation starts the payment process. ### Accept quote request Prerequisites * You must have the `quote_id` of the quote you want to accept from the [create a quote](#create-quote-collection-response) response. * You must have the beneficiary token you created with the [create an identity](/products/payments-direct/api-docs/tutorials/create-an-identity) operation. Construct the request body as follows: * `quote_id` : Set this value to the `quote_id` you received in the Create quote collection response. * `user_info` : This object contains the required identity token we generated earlier, as well as the purpose of the payment and source of funding. * `beneficiary_token` : Set this value to the `identityId` UUID associated with the [beneficiary identity](/products/payments-direct/api-docs/working-with-user-info-object#beneficiary_token). * `purpose` : This example uses `PAYR` to indicate that the [Purpose](/products/payments-direct/api-docs/working-with-user-info-object#purpose) is payroll. * `SourceOfCash` : This example uses `SVGS` to indicate that the [Source of Cash](/products/payments-direct/api-docs/working-with-user-info-object#sourceofcash) is savings. * `sender_end_to_end_id` : This example uses `226f827a-04ec-471f-a3ba-2c241a00c55f`. * Note : This is a required sender-created ID to use with filtering in other API operations. Note The following `user_info` object is for reference. Learn more about [working with the user_info object](/products/payments-direct/api-docs/working-with-user-info-object) ```json { "quote_id": "4209ca26-28e2-4256-9ef2-746afbe1fb5a", "user_info": { "beneficiary_token": "11111111-abcd-2222-efgh-333333333333", "purpose": "PAYR", "SourceOfCash": "SVGS" }, "sender_end_to_end_id": "226f827a-04ec-471f-a3ba-2c241a00c55f" } ``` ### Accept quote response The accept a quote response contains the `payment_id` and other information you can use to monitor the status of the payment. ```json { "payment_id": "98e7c7dc-b519-4d97-9de9-0f7a15b7a207", "contract_hash": "2a9aacce87c43c2ecbd4954f67b4fb286e86e43744961f702226900327419780", "payment_state": "ACCEPTED", "modified_at": "2024-03-22T15:24:20.245Z", "contract": { "sender_end_to_end_id": null, "created_at": "2024-03-22T15:24:19.587Z", "expires_at": "2024-05-21T15:13:31.275Z", "quote": { "quote_id": "203642d1-c657-4963-9620-a3f9da2cf60d", "created_at": "2024-03-22T15:13:31.275Z", "expires_at": "2024-03-22T16:13:31.275Z", "type": "SENDER_AMOUNT", "price_guarantee": "FIRM", "sender_address": "trans_usd_exampleSender@staging.usa.exampleSender", "receiver_address": "trans_aud_exampleReceiver@staging.usa.exampleReceiver", "amount": "10000.000000000", "currency_code": "USD", "currency_code_filter": null, "service_type": null, "quote_elements": [ { "quote_element_id": "25540a1f-36cf-40f6-8fb8-6abae3e890d8", "quote_element_type": "TRANSFER", "quote_element_order": "1", "sender_address": "trans_usd_exampleSender@staging.usa.exampleSender", "receiver_address": "alias_usd_exampleSender_rmde-exampleSender@staging.usa.exampleSender", "sending_amount": "10000.000000000", "receiving_amount": "10000.000000000", "sending_fee": "0.000000000", "receiving_fee": "0.000000000", "sending_currency_code": null, "receiving_currency_code": null, "fx_rate": null, "transfer_currency_code": "USD" }, { "quote_element_id": "fb68452e-acd7-45fc-85b4-ac519d6a4b95", "quote_element_type": "TRANSFER", "quote_element_order": "2", "sender_address": "alias_usd_rmde-exampleSender@staging.usa.rmde.exampleSender", "receiver_address": "alias_usd_rmde-odl@staging.usa.rmde.exampleSender", "sending_amount": "9950.000000000", "receiving_amount": "9950.000000000", "sending_fee": "50.000000000", "receiving_fee": "0.000000000", "sending_currency_code": null, "receiving_currency_code": null, "fx_rate": null, "transfer_currency_code": "USD" }, { "quote_element_id": "47d4c061-3553-475e-bfc4-7daa29cf6bb7", "quote_element_type": "EXCHANGE_TRADE", "quote_element_order": "3", "sender_address": "exampleSourceExchange_usd@staging.rpd.rmde-odl", "receiver_address": "exampleSourceExchange_xrp@staging.rpd.rmde-odl", "sending_amount": "9945.025000000", "receiving_amount": "9854.643689000", "sending_fee": "4.975000000", "receiving_fee": "0.000000000", "sending_currency_code": "USD", "receiving_currency_code": "XRP", "fx_rate": { "rate": "1.009171444", "base_currency_code": "XRP", "counter_currency_code": "USD", "type": "SELL" }, "transfer_currency_code": null }, { "quote_element_id": "9926aa88-3434-4683-af1f-015ea9a755c5", "quote_element_type": "CRYPTO_TRANSFER", "quote_element_order": "4", "sender_address": "exampleSendingExchange_xrp@staging.rpd.rmde-odl", "receiver_address": "exampleDestinationExchange_xrp@staging.usa.exampleReceiver-odl", "sending_amount": "9854.643689000", "receiving_amount": "9854.643689000", "sending_fee": "0.000000000", "receiving_fee": "0.000000000", "sending_currency_code": null, "receiving_currency_code": null, "fx_rate": null, "transfer_currency_code": "XRP" }, { "quote_element_id": "7ad66ec6-2f20-4056-bdbf-7a0759f55191", "quote_element_type": "EXCHANGE_TRADE", "quote_element_order": "5", "sender_address": "exampleDestinationExchange_xrp@staging.usa.exampleReceiver-odl", "receiver_address": "exampleDestinationExchange_usd@staging.usa.exampleReceiver-odl", "sending_amount": "9854.643680000", "receiving_amount": "9775.290000000", "sending_fee": "0.000000000", "receiving_fee": "4.890000000", "sending_currency_code": "XRP", "receiving_currency_code": "USD", "fx_rate": { "rate": "0.991947585", "base_currency_code": "XRP", "counter_currency_code": "USD", "type": "BUY" }, "transfer_currency_code": null }, { "quote_element_id": "8ae69544-bc6b-409f-ae00-ee8b57b92900", "quote_element_type": "TRANSFER", "quote_element_order": "6", "sender_address": "alias_usd_exampleReceiver@staging.usa.exampleReceiver", "receiver_address": "conct_usd_exampleReceiver@staging.usa.exampleReceiver", "sending_amount": "9770.400000000", "receiving_amount": "9770.400000000", "sending_fee": "0.000000000", "receiving_fee": "0.000000000", "sending_currency_code": null, "receiving_currency_code": null, "fx_rate": null, "transfer_currency_code": "USD" }, { "quote_element_id": "2ef76b05-8c96-4cd6-8cff-57b2b0ee4404", "quote_element_type": "EXCHANGE", "quote_element_order": "7", "sender_address": "conct_usd_exampleReceiver@staging.usa.exampleReceiver", "receiver_address": "alias_aud_exampleReceiver@staging.usa.exampleReceiver", "sending_amount": "9770.400000000", "receiving_amount": "14557.900000000", "sending_fee": "0.000000000", "receiving_fee": "0.000000000", "sending_currency_code": "USD", "receiving_currency_code": "AUD", "fx_rate": { "rate": "1.490000000", "base_currency_code": "USD", "counter_currency_code": "AUD", "type": "buy" }, "transfer_currency_code": null }, { "quote_element_id": "aad8e850-a625-4c05-a106-a54403a34229", "quote_element_type": "TRANSFER", "quote_element_order": "8", "sender_address": "alias_aud_exampleReceiver@staging.usa.exampleReceiver", "receiver_address": "trans_aud_exampleReceiver@staging.usa.exampleReceiver", "sending_amount": "14557.900000000", "receiving_amount": "14557.900000000", "sending_fee": "0.000000000", "receiving_fee": "0.000000000", "sending_currency_code": null, "receiving_currency_code": null, "fx_rate": null, "transfer_currency_code": "AUD" } ], "liquidity_warning": null, "payment_method": "CSM_EU_EUR_SEPA", "payment_method_fields": null, "payout_method_info": { "payout_method_name": "CSM_EU_EUR_SEPA", "payout_method_category": "OTHER", "description": "local rails", "estimated_time_to_credit": "5 Seconds" } }, "fee_info": { "nodes": { "staging.usa.rmde.exampleSender": [ { "fee_value": "50.000000000", "fee_currency": "USD", "category": "NONE", "fee_description": "Ripple Payment Service Fee" } ] }, "total_fees": [ { "total_fee": "50.000000000", "fee_currency": "USD" } ] } }, "ripplenet_info": [], "execution_condition": "PrefixSha256Condition{subtypes=[ED25519-SHA-256], type=PREFIX-SHA-256, fingerprint=aiUxWFzadeO7G_MldXLvnxQJG0S3QDScbllPkaAltxE, cost=132360}", "crypto_transaction_id": null, "validator": "staging.usa.exampleSender", "payment_type": "DIRECT", "returns_payment_with_id": null, "returned_by_payment_with_id": null, "execution_results": [], "liquidation_execution_results": [], "liquidation_details": null, "push_forward_execution_results": [], "direct_payment_id": null, "transaction_payment_id": null, "accepted_at": "2024-03-22T15:24:20.240Z", "locked_at": null, "executed_at": null, "completed_at": null, "returned_at": null, "failed_at": null, "internal_info": { "connector_role": "SENDING", "labels": [], "internal_id": null }, "user_info": [ { "node_address": "staging.usa.exampleSender", "accepted": [ { "json": { "sender_token": "12345678-abcd-1234-abcd-123456789123", "beneficiary_token": "11111111-abcd-2222-efgh-333333333333", "SourceOfCash": "SVGS", "DbtrAcct": { "Id": { "Othr": { "Id": "12345", "SchmeNm": { "Prtry": { "Cd": "CWALLET" } } } } }, "Dbtr": { "Nm": "Ripple Labs", "Id": { "OrgId": { "Othr": { "Id": "ripple" } } }, "PstlAdr": { "AdrLine": "315 Montgomery St", "PstCd": "90104", "TwnNm": "San Francisco", "Ctry": "US" } }, "Cdtr": { "PstlAdr": { "AdrLine": [ "77 Robinson Road, 16-00 Robinson 77" ], "TwnNm": "Singapore", "PstCd": "68896" }, "CtryOfRes": "CH", "Id": { "OrgId": { "RelShipToDbtr": "SUBS", "Othr": { "Id": "201708102R", "SchmeNm": { "Cd": "CINC" } } } }, "CtctDtls": { "MobNb": "+41658241064", "EmailAdr": "treasury1@ripple.com" }, "Nm": "Ripple Markets APAC Pte. Ltd." }, "CdtrAgt": { "FinInstnId": { "Othr": { "Id": "410001" }, "Nm": "Sygnum Bank AG" }, "BrnchId": { "PstlAdr": { "Ctry": "CH" } } }, "CdtrAcct": { "Ccy": "EUR", "Id": { "IBAN": "CH5883014840071160923", "Othr": { "SchmeNm": { "Cd": "BBAN" } } } }, "ChrgBr": "DEBT", "Purp": { "Cd": "OTHR" }, "version": "1.1.7" }, "created_at": "2024-03-22T15:24:20.176Z", "subState": "" } ], "locked": [], "lock_declined": [], "retry_accept": [], "retry_settlement": [], "settlement": [], "settlement_declined": [], "failed": [], "executed": [], "completed": [], "forwarded": [], "returned": [], "processing_compliance": [] } ] } ``` ## Get a payment Use the [Get payment by payment ID](/products/payments-direct/api-docs/payments-direct-api/reference/payments-direct-api/payments/getpaymentbypaymentid) operation to look up the status of a payment. ### Get payment request ### Get payment response Check the `payment_state` field in the response output for the current payment state, and refer to the user_info object for detailed payment information.