Send Payment (beta)

How do I send a Bitcoin Lightning Network payment?

Availability

This feature is currently in beta and available to all partners in the sandbox environment.

👍

To enable in the production environment, please contact the partner success team.

Overview

The Cybrid Platform will eventually support sending payment in either USD or BTC; however, only USD is currently supported. This guide currently describes sending payment in USD only.

In order to support customers sending payments in USD on the Lightning Network, a special type of fiat account called an "invoice operations" pre-fund account must be created. While the Cybrid Platform will sub-ledger the USD balance of the invoice operations pre-fund account, the actual USD balance is held with a third party Lightning Network provider.

Customer payments will initially be funded from this invoice operations pre-fund account, and the payment amount will be subsequently book-transferred from the customer's fiat account to the bank-level fiat account (see figure below). Both the invoice operations pre-fund account and the customer's fiat account must have sufficient balance to fund the customer's payment amount including network fees.

In order to fund (and top-up as required) the invoice operations pre-fund account, a special type of transfer called an "inter-account" transfer will be used to transfer from the bank-level fiat account to the invoice operations pre-fund account. These inter-account transfers are wire transfers between the Cybrid Platform and the Lightning Network provider for which wire fees will apply. These inter-account transfer wire fees will be included in the partner's Cybrid Platform monthly invoicing.

To allow a customer to send a Bitcoin Lightning Network payment in USD, follow these steps on the Cybrid Platform:

  1. Create a bank-level fiat account.
  2. Create and fund a customer-level fiat account.
  3. Create an invoice operations pre-fund account.
  4. Fund the invoice operations pre-fund account with an inter-account transfer.
  5. Create a Lightning Network send payment transfer.
  6. Top-up the invoice operations pre-fund account as required.

For this guide, we'll use the following terminology:

  • The Cybrid partner's customer will be referred to as the "payer".
  • The payer's end-merchant will be referred to as the "payee".

1. Create a bank-level fiat account

If you haven't already, create a bank-level fiat account. This is a one-time operation.

See the guide for creating accounts at the bank-level here.

2. Create and fund a customer-level fiat account

If you haven't already, create a customer-level fiat account. This is a one-time operation.

Once the customer-level fiat account has been created, the account must be funded. This is an ongoing operation.

See the guides for creating and funding accounts at the customer-level here and here.

3. Create an invoice operations pre-fund account

The invoice operations pre-fund account is created at the bank-level. This is a one-time operation.

You may create a USD invoice operations pre-fund account at the bank-level via the POST /api/accounts endpoint.

An example POST /api/accounts request body is below:

{
  "type": "invoice_operations",
  "asset": "USD",
  "name": "<insert account descriptive name>"
}

When executed, the following response body will be returned:

{
  "created_at": "<created_at timestamp>",
  "updated_at": "<updated_at timestamp>",
  "type": "invoice_operations",
  "guid": "<created account GUID>",
  "asset": "USD",
  "name": "<inserted account descriptive name>",
  "bank_guid": "762a77263ea05ee526a330a98b2b610c",
  "platform_balance": 0,
  "platform_available": 0,
  "state": "storing",
  "labels": null
}

The account will begin in "state":"storing", and automatically progress to "state":"created" which is the terminal state for accounts.

4. Fund the invoice operations pre-fund account with an inter-account transfer

The invoice operations pre-fund account must funded in order for a customer to send a USD payment via the Lightning Network. This is an ongoing operation.

👍

Note: When funding the invoice operations pre-fund account, be sure to also account for potential network fees.

You may create a quote to fund the invoice operations pre-fund account via the POST /api/quotes endpoint.

An example POST /api/quotes request body is below:

{
  "product_type": "inter_account",
  "asset": "USD",
  "deliver_amount": <insert deliver_amount>
}

When executed, the following response body will be returned:

{
  "created_at": "<created_at timestamp>",
  "updated_at": "<updated_at timestamp>",
  "guid": "<created quote_guid>",
  "product_type": "inter_account",
  "bank_guid": "<associated bank_guid>",
  "asset": "USD",
  "side": "deposit",
  "receive_amount": <calculated receive_amount>,
  "deliver_amount": <inserted deliver_amount>,
  "fee": 0,
  "issued_at": "<issued_at timestamp>",
  "expires_at": "<expires_at timestamp>"
}

Use the the above quote GUID in the POST /api/transfers request.

An example POST /api/transfers request body is below:

{
  "transfer_type": "inter_account",
  "quote_guid": "<insert quote_guid>",
  "source_account_guid": "<insert bank-level fiat account_guid>",
  "destination_account_guid": "<insert invoice operations account_guid>"
}

When executed, the following response body will be returned:

{
  "created_at": "<created_at timestamp>",
  "updated_at": "<updated_at timestamp>",
  "guid": "<created transfer_guid>",
  "transfer_type": "inter_account",
  "bank_guid": "<associated bank_guid>",
  "quote_guid": "<inserted quote_guid>",
  "external_bank_account_guid": null,
  "asset": "USD",
  "side": "deposit",
  "state": "storing",
  "failure_code": null,
  "amount": <inserted deliver_amount>,
  "estimated_amount": <inserted deliver_amount>,
  "fee": 0,
  "source_account": {
    "type": "fiat",
    "guid": "<inserted bank-level fiat account_guid>",
    "bank_guid": "<associated bank_guid>"
  },
  "source_participants": null,
  "destination_account": {
    "type": "invoice_operations",
    "guid": "<insert invoice operations account_guid>",
    "bank_guid": "<associated bank_guid>"
  },
  "destination_participants": null,
  "labels": null
}

Use the GET /api/transfers/{transfer_guid} endpoint to verify the "state" of the transfer.

Once the transfer has progressed to "state":"completed", use the GET /api/accounts/{account_guid} endpoint to verify that the "platform_available" balance of the invoice operations account has been credited to the reflect the transfer amount.

5. Create a Lightning Network send payment transfer

Once the invoice operations pre-fund account has been funded, customers may now send a payment in order to pay a Lightning Network invoice (see the Receive Payment guide for steps to create a Lightning Network invoice).

For a customer (i.e. payor) that is "state":"verified", and for whom a USD fiat account has been created on the Cybrid Platform, you may send payment to a Lightning Network invoice via the POST /api/transfers endpoint.

You may create a "lightning_transfer" quote using the POST /api/quotes endpoint.

An example POST /api/quotes request body is below:

{
  "product_type": "lightning_transfer",
  "customer_guid": "<insert customer_guid>",
  "network_address": "<insert network_address>",
  "asset": "USD"
}

👍

Note: When creating quotes in sandbox banks, the "receive_amount" will be a randomly generated amount.

👍

Note: Since Lightning Network channels are not created in sandbox banks (i.e. "network_address" will always be "sandbox_network_address"), when creating quotes for payment instructions that were generated in sandbox banks the "network_address" can be any string value.

When executed, the following response body will be returned:

{
  "created_at": "<created_at timestamp>",
  "updated_at": "<updated_at timestamp>",
  "guid": "<created quote_guid>",
  "product_type": "lightning_transfer",
  "customer_guid": "<inserted customer_guid>",
  "asset": "USD",
  "side": "withdrawal",
  "receive_amount": <calculated receive_amount>,
  "deliver_amount": <calculated deliver_amount>,
  "fee": 0,
  "issued_at": "<issued_at timestamp>",
  "expires_at": "<expires_at timestamp>"
  "network_fee_asset": "USD",
  "network_address": "<inserted network_address>"
}

You may create a "lightning" transfer using the "quote_guid" from above and the POST /api/transfer endpoint.

👍

Note: When creating the "lightning" transfer, you may specify if the partner or the customer is paying the network fees by inserting either the bank-level fiat account_guid or the customer-level fiat account_guid in the "network_fee_account_guid". Network fees are quoted in USD, are usually only pennies, and are sometimes free.

An example POST /api/transfers request body is below:

{
  "transfer_type": "lightning",
  "customer_guid": "<inserted customer_guid>",
  "quote_guid": "<inserted quote_guid>",
  "network_fee_account_guid": "<inserted network_fee_account_guid>"
}

When executed, the following response body will be returned:

{
  "created_at": "<created_at timestamp>",
  "updated_at": "<updated_at timestamp>",
  "guid": "<created transfer_guid>",
  "transfer_type": "lightning",
  "customer_guid": "<inserted customer_guid>",
  "quote_guid": "<inserted quote_guid>",
  "external_bank_account_guid": null,
  "asset": "USD",
  "side": "withdrawal",
  "state": "storing",
  "failure_code": null,
  "amount": <calculated amount>,
  "estimated_amount": <calculated estimated_amount>,
  "fee": 0,
  "source_account": {
    "type": "fiat",
    "guid": "<inserted account_guid>",
    "customer_guid": "<inserted customer_guid>"
  },
  "source_participants": null,
  "destination_account": null,
  "destination_participants": null,
  "labels": null
}

Use the GET /api/transfers/{transfer_guid} endpoint to verify the "state" of the transfer.

Once the transfer has progressed to "state":"completed":

  • Use the GET /api/accounts/{account_guid} endpoint to verify that the "platform_available" balance of the invoice operations pre-fund account has been debited to the reflect the transfer amount.
    • The invoice operations pre-fund account initially covers the payment amount including network fees.
  • Use the GET /api/accounts/{account_guid} endpoint to verify that the "platform_available" balance of the customer fiat account has also been debited to the reflect the transfer amount.
    • The payment amount including network fees will be book transferred from the network fees.
  • Use the GET /api/accounts/{account_guid} endpoint to verify that the "platform_available" balance of the bank-level fiat account has been credited to the reflect the transfer amount.
    • This bank-level fiat balance may be book-transferred to top-up the invoice operations pre-fund account as required.

6. Top-up the invoice operations pre-fund account as required

In order to top-up the invoice operations pre-fund, repeat step 3: Fund the invoice operations pre-fund account.