Menu

Grants and limits

A grant is what your app holds to act on a node's wallet addresses. This page lists what a grant may ask for, when the owner must agree, how limits are counted, and the few places where a Dassie node is stricter than the Open Payments specs require.

On this page
  1. What a grant may ask for
  2. When the owner decides
  3. Limits on outgoing payments
  4. How limits are spent
  5. What a grant spends from
  6. Tokens and time
  7. Room for clients
  8. Where Dassie differs

What a grant may ask for

A grant request names up to three access items. Each has a type, its actions, and for some types a wallet address and limits:

Type Actions identifier limits
incoming-payment create, complete, read, read-all, list, list-all Optional; without one, every wallet address of the node None
outgoing-payment create, read, read-all, list, list-all Required Optional, below
quote create, read, read-all None None
  • Each action appears once in an item, and each item once in a request.
  • The -all actions include their plain forms, and reach what other clients made too. The plain ones reach only what your app made.
  • An identifier must be one of this node's wallet addresses, under any of its names. The node records it in its /pay/<asset> form, so /.well-known/pay and /pay/xrp are the same wallet address when XRP is the default.
  • Only one item per wallet address may allow creating outgoing payments, so that it is always clear which limits apply.
  • A subject request, asking the node to prove a wallet address, takes one identity, a wallet address URL.
  • Card authorization is not offered: a node has no cards.

When the owner decides

Some grants move the owner's money or show more than your app's own resources, so they wait for the owner. The rest are approved at once.

The request holds Approved
Any outgoing-payment item By the owner
Any list-all action By the owner
read-all on quotes By the owner
A subject request By the owner
Anything else, read-all on incoming payments included At once

Reading any incoming payment needs no owner: a sender's wallet reads a payment it did not create to learn how to pay it, and the payment shows only what paying needs.

A grant that waits for the owner must:

  • ask to interact, with "start": ["redirect"], and, if it names a finish, "method": "redirect", a URI without a fragment and a nonce of 1 to 256 bytes;
  • name your app by its wallet address. A client known only by its key gets 400 invalid_client, since the owner must see who asks.

The owner sees the request on a consent page in their wallet, which says what each side of a payment comes to, as far as it is known. Connect apps shows that side.

Consent through a front door is not there yet: a node reached at <node ID>.dassiepay.net cannot yet approve a grant that waits for its owner. What's next

Limits on outgoing payments

An outgoing-payment item may limit what its payments debit, what they deliver, which incoming payment they pay, and over which interval:

debitAmount

The most the payments may debit from the wallet address, every fee and exchange on the way included. On an item that may create payments, it must be in the wallet address's own asset and scale. A limit in another asset there is refused with 400 invalid_request, whose description names the asset it must be in, since no payment could ever fit it. An item that only reads or lists is not checked for it.

receiveAmount

The most the payments may deliver, as their receivers count it. It is taken only beside a debitAmount: a limit on what is delivered alone is refused, since it puts no bound on what the owner pays.

A receive limit in another asset than the receiver it names is not refused: the owner sees a warning on the consent page, and a payment that cannot fit it is refused when it is made.

receiver

The only incoming payment the grant may pay: an incoming payment's URL, without a query or a fragment. On an item that only reads or lists, it narrows what the item reaches.

interval

An ISO 8601 repeating interval, such as R/2026-10-28T09:00:00Z/P1D for every day from that moment. The amounts apply to each window again. Without one, they apply to all time. Windows are counted as the reference server, Rafiki, counts them, so a month from January 31 ends on February 28. Each window must last at least a minute. No payment may be made before the first window or after the last.

Amounts are strings of whole units at the asset's scale, and must be above zero.

Why it works this way: why a receive limit alone is refused.

How limits are spent

  • Reserved when a payment is made. An outgoing payment takes its amounts from the window it is made in. One that would pass a limit is refused with 403 invalid_request.
  • Given back when it ends. What a payment did not send goes back to the window. If it failed, so does what it did not deliver.
  • A receive limit caps the money, not only the books. Under a grant with a receiveAmount, a payment delivers no more than its own receive amount, even when its quote fixed what it debits. It may then finish without debiting all of its debitAmount.
  • What the window has spent comes back when your app creates a payment, in grantSpentDebitAmount and grantSpentReceiveAmount, and at any time from GET /outgoing-payment-grant, which the client library calls outgoingPayment.getGrantSpentAmounts.
  • The node checks the funds too. What the owner has free on that ledger, with what the node can move into its hub from the owner's own account, must cover the payment and what the payments still sending there have left to send. Otherwise it is refused with 400 invalid_request.

Why it works this way: why a receive limit caps what payments deliver.

What a grant spends from

A wallet address books on the ledger its asset arrives on: on the testnet, the node's account in a settlement hub. So a grant to pay from /pay/xrp spends from the node's XRP hub. The hub keeps only a float, and the rest is on the owner's own XRP Ledger account; a payment larger than the float waits a few seconds while the node moves the difference into the hub.

Settlement hubs and Ledgers, books and realms explain where a node keeps money.

Tokens and time

What How long
An access token One hour. Rotate it at its manage URL, or ask again.
A grant that waits for the owner Ten minutes, then it lapses
The wait before you continue a grant Five seconds, as continue.wait says
A quote Five minutes
An outgoing payment Ten minutes at most, then it fails
An incoming payment your app creates A day by default, seven days at most
  • A grant is bound to your app's key. Every later request under it must be signed with that key, so a stolen token is of no use alone.
  • The node keeps tokens only as hashes, and cannot show one again.
  • The owner can revoke a grant at any time, on the wallet's Connected apps page. Its tokens get 401 unauthorized from then on.

Room for clients

Anyone can be a client, so a node keeps room for its owner and for the apps the owner already approved. When strangers fill their share, a new stranger is refused, never the owner.

  • Requests are rate-limited per client address, with a tighter limit on whatever creates something: grants, incoming payments, quotes and outgoing payments. Past it, you get 429 too_many_requests.
  • Grants. An app the owner has not approved before is a stranger, counted by its wallet address and by its network, an IPv4 /24 or an IPv6 /56. Each may hold only a small share of the grants kept and of the grants waiting for the owner: past it, 429 too_many_requests. When a whole pool is full, 503 request_denied: try again later.
  • Incoming payments. Clients' open incoming payments are bounded apart from the owner's. When clients' share is full, the oldest one that has received nothing is closed to make room.
  • Quotes. Clients' quotes share the probes that measure routes, and a few are kept for the owner alone.

Why it works this way

Where Dassie differs

A node implements Open Payments as its specs define it. Where the specs leave a choice, or another server may be more lenient, a Dassie node:

  • refuses a limit on what is received alone;
  • caps what payments deliver under a receive limit, not only what they reserve;
  • refuses a debit limit in another asset than its wallet address's, on an item that may create payments;
  • takes at most three access items, and one item per wallet address that creates outgoing payments;
  • needs windows of at least a minute;
  • asks the owner for list-all and for read-all on quotes, but not for read-all on incoming payments;
  • refuses a client known only by its key for a grant the owner must approve;
  • offers no card authorization, and no SPSP.

The Open Payments endpoints reference lists the routes, and Accept payments with Open Payments walks through a grant end to end.

Why it works this way

A kopje of granite blocks against the sun, in veld grass; one dassie climbs its slab, one keeps lookout on top inside the sun, and one sleeps on the next rock; on a wide screen, a pair sits on a kopje to the left