Saltearse al contenido
GitHub

Get an outgoing payment grant for future payments

Esta página aún no está disponible en tu idioma.

Often, a transaction will start with the client getting the recipient’s details and asking the recipient’s ASE for permission to send money. However, Open Payments also supports a different approach, where the client gets permission from the sender’s ASE to send money before knowing who the recipient will be. Web Monetization’s pay-as-you-browse model uses this approach.

In this model, a user installs a browser extension and visits a web monetized site. The extension uses Open Payments to issue continuous outgoing payments to the site, on behalf of the user, for as long as the user is on the site. The extension has no idea who the recipient will be until the user visits the site.

Setting up the extension requires the user to connect it to their wallet account. They specify a maximum amount they’re willing to spend and select whether the amount should renew monthly. The extension then receives an outgoing payment grant from the user’s wallet provider, allowing the extension to initiate future payments.

In this guide, you’ll assume the role of an app developer. The guide takes you through the steps your app will perform to receive an outgoing payment grant with a specified debit amount but no known recipients. The example scenario illustrates how to allow your app’s user to send payments of up to $100 CAD a month for three months.

Let’s assume your user saved their wallet address in their account profile when setting up your app. Call the Get Wallet Address API to get required details about your user’s wallet account.

const userWalletAddress = await client.walletAddress.get({
url: 'https://cloudninebank.example.com/user'
})

2. Request an interactive outgoing payment grant

Section titled “2. Request an interactive outgoing payment grant”

Use the authorization server information received in the previous step to call the Grant Request API. The purpose of this call is to obtain a token that allows your client to request outgoing payment resources be created on your user’s wallet account.

In addition to any required parameters, include the following in the request:

  • limits object
    • debitAmount - The maximum amount that your user can send per interval. When the next interval begins, the value resets.
    • interval - The time interval under which the grant is valid.

Your user indicates they want to make payments of up to $100 CAD a month for three months. The amount resets each month and any unspent portions don’t roll over.

const grant = await client.grant.request(
{
url: userWalletAddress.authServer,
},
{
access_token: {
access: [
{
identifier: userWalletAddress.id,
type: 'outgoing-payment',
actions: ['read', 'create'],
limits: {
interval: 'R3/2025-05-20T13:00:00Z/P1M'
debitAmount: {
assetCode: 'CAD',
assetScale: 2,
value: '10000',
},
},
},
],
},
client: userWalletAddress.id,
interact: {
start: ['redirect'],
finish: {
method: 'redirect',
uri: 'https://cloudninebank.example.com/finish/T8jw5Xy',
nonce: NONCE,
},
},
},
);

The interval used in this guide is R3/2025-05-20T13:00:00Z/P1M. Remember that your user wants to send payments up to $100 CAD a month for three months. The interval breaks down like this:

  • R[3]/ is the number of repetitions - three.
  • 2025-05-20 is the start date of the repeating interval - 20 May 2025
  • T13:00:00Z/ is the start time of the repeating interval - 1:00 PM UTC.
  • [P1M] is the period between each interval - one month. Used with R[3], you have a grant that’s valid once a month for three months.

Altogether, your user can send up to $100 CAD from:

  • 1 PM UTC on 20 May 2025 through 12:59 PM UCT on 20 June 2025
  • 1 PM UTC on 20 June 2025 through 12:59 PM UTC on 20 July 2025
  • 1 PM UTC on 20 July 2025 through 12:59 PM UCT on 20 August 2025

Once your client receives the authorization server’s response, it must send the user to the interact.redirect URI contained in the response. This starts the interaction flow.

The response also includes a continue object, which is essential for managing the interaction and obtaining explicit user consent for outgoing payment grants. The continue object contains an access token and a URI that the client will use to finalize the grant request after the user has completed their interaction with the identity provider (IdP). This ensures that the client can securely obtain the necessary permissions to proceed with the payment process.

Example response
{
"interact": {
"redirect": "https://auth.interledger-test.dev/4CF492MLVMSW9MKMXKHQ",
"finish": "4105340a-05eb-4290-8739-f9e2b463bfa7"
},
"continue": {
"access_token": {
"value": "33OMUKMKSKU80UPRY5NM"
},
"uri": "https://auth.interledger-test.dev/continue/4CF492MLVMSW9MKMXKHQ",
"wait": 30
}
}

The user interacts with the authorization server through the server’s interface and approves or denies the grant.

Provided the user approves the grant, the authorization server:

  • Sends the user to your client’s previously defined finish.uri. The means by which the server sends the user to the URI is out of scope, but common options include redirecting the user from a web page and launching the system browser with the target URI.
  • Secures the redirect by adding a unique hash, allowing your client to validate the finish call, and an interaction reference as query parameters to the URI.

In this guide, we’re assuming the IdP has a user interface with which your user interacts. When the interaction completes, your user is directed back to your app. Now the client can make a grant continuation request.

Add the interact_ref returned in the redirect URI’s query parameters.

const grant = await client.grant.continue(
{
accessToken: CONTINUE_ACCESS_TOKEN,
url: CONTINUE_URI,
},
{
interact_ref: INTERACT_REF,
},
);

A successful response provides your app with an access token. Now your app can issue outgoing payment requests to future recipients against the grant. Each request must reference the access token.