Skip to content
GitHub

Create an outgoing payment grant request

The Grant Request API lets you request a grant for outgoing payment, incoming payment, and quote resources.

Before your client can call most of the Open Payments APIs, it must receive a grant from the appropriate authorization server.

The code snippets below let an authenticated client request a grant for an outgoing payment. The request to the authorization server must indicate the outgoing-payment and the actions the client wants to take at the resource server.

Outgoing payments require explicit consent, typically by the client’s user, before a grant can be issued. Consent is obtained through an interactive grant.

Any authorization server that issues interactive grants must integrate with an identity provider (IdP). When a client requests the outgoing payment grant, the authorization server provides the client with the IdP URI to redirect to.

We recommend creating a wallet account on the test wallet. Creating an account allows you to test your client against the Open Payments APIs by using an ILP-enabled wallet funded with play money.

Authenticated client required
Prerequisites
Initial configuration

If you’re using JavaScript, only do the first step.

  1. Add "type": "module" to package.json.

  2. Add the following to tsconfig.json

    {
    "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022"
    }
    }
// Import dependencies
import { createAuthenticatedClient } from '@interledger/open-payments'
// Initialize client
const client = await createAuthenticatedClient({
walletAddressUrl: WALLET_ADDRESS,
privateKey: PRIVATE_KEY_PATH,
keyId: KEY_ID
})
// Get wallet address information
const walletAddress = await client.walletAddress.get({
url: WALLET_ADDRESS
})
// Request outgoing payment grant
const grant = await client.grant.request(
{
url: walletAddress.authServer
},
{
access_token: {
access: [
{
identifier: walletAddress.id,
type: 'outgoing-payment',
actions: ['list', 'list-all', 'read', 'read-all', 'create'],
limits: {
debitAmount: {
assetCode: quote.debitAmount.assetCode,
assetScale: quote.debitAmount.assetScale,
value: quote.debitAmount.value
}
}
}
]
},
interact: {
start: ['redirect'],
finish: {
method: 'redirect',
uri: 'http://localhost:3344',
nonce: NONCE
}
}
}
)
// Check grant state
if (!isPendingGrant(grant)) {
throw new Error('Expected interactive grant')
}
// Output
console.log('Please interact at the following URL:', grant.interact.redirect)
console.log('CONTINUE_ACCESS_TOKEN =', grant.continue.access_token.value)
console.log('CONTINUE_URI =', grant.continue.uri)
// Import dependencies
import { createAuthenticatedClient } from '@interledger/open-payments'
// Initialize client
const client = await createAuthenticatedClient({
walletAddressUrl: WALLET_ADDRESS,
privateKey: PRIVATE_KEY_PATH,
keyId: KEY_ID
})
// Get wallet address information
const walletAddress = await client.walletAddress.get({
url: WALLET_ADDRESS
})
// Request outgoing payment grant
const grant = await client.grant.request(
{
url: walletAddress.authServer
},
{
access_token: {
access: [
{
identifier: walletAddress.id,
type: 'outgoing-payment',
actions: ['list', 'list-all', 'read', 'read-all', 'create'],
limits: {
debitAmount: {
assetCode: quote.debitAmount.assetCode,
assetScale: quote.debitAmount.assetScale,
value: quote.debitAmount.value
},
interval: 'R/2016-08-24T08:00:00Z/P1D'
}
}
]
},
interact: {
start: ['redirect'],
finish: {
method: 'redirect',
uri: 'http://localhost:3344',
nonce: NONCE
}
}
}
)
// Check grant state
if (!isPendingGrant(grant)) {
throw new Error('Expected interactive grant')
}
// Output
console.log('Please interact at the following URL:', grant.interact.redirect)
console.log('CONTINUE_ACCESS_TOKEN =', grant.continue.access_token.value)
console.log('CONTINUE_URI =', grant.continue.uri)

For TypeScript, run tsx path/to/directory/index.ts. View full TS source

For JavaScript, run node path/to/directory/index.js. View full JS source