Skip to content
GitHub

Resource server

An ASE’s resource server hosts three sets of APIs, one per resource type. For each request, the resource server validates the access token presented by the client with the ASE’s authorization server before performing the operation.

When the resource server receives a Create Incoming Payment request, it must:

  • Generate unique payment details that the sender’s ASE will use to address payments to this incoming payment.
  • Persist the incoming payment resource so it can be retrieved, listed, and completed via subsequent API calls.
  • Track the running receivedAmount as payments arrive.

If the request specifies an incomingAmount, the resource server must enforce it as a maximum total. One or more payments can be associated with the incoming payment, but the sum across them must not exceed incomingAmount. The resource server should mark the incoming payment as completed once the running total reaches the cap.

If incomingAmount is absent, the resource server cannot determine completion on its own. It must accept payments until a client issues a Complete an Incoming Payment request, or until the incoming payment expires. ASEs can define an expiration window. The expiresAt must be returned to the client in such cases so that the client knows when the resource will stop accepting payments.

When the resource server receives a Create a Quote request, it must:

  • Compute the debitAmount, receiveAmount, and fee for the requested payment, including any applicable exchange rate when the sender’s and recipient’s wallet addresses use different assetCode values.
  • Commit to deliver the quoted receiveAmount to the recipient’s ASE if an outgoing payment is created against the quote within the quote’s validity window.
  • Assign the quote a quoteId and persist it.
  • Set a validity window after which the quote is no longer honored. ASEs define this window. It must be short enough to bind rate and fee exposure, and long enough for the client to complete any remaining grant and authorization steps and call Create Outgoing Payment before the quote expires.

A quote represents a binding commitment from the sender’s ASE. If the sender’s ASE cannot honor the quote at execution time, that is an ASE-side failure, not a protocol error.

When the resource server receives a Create Outgoing Payment request, it must:

  • Validate that the access token presented carries a grant that authorizes this specific outgoing payment, including the limits collected during the interactive consent flow.
  • If a quoteId is present, look up the quote, confirm it has not expired, and use the quoted amounts.
  • If no quoteId is present (for example, in Web Monetization-style use cases), use the incomingPayment and debitAmount from the request to scope the outgoing payment.
  • Persist the outgoing payment resource and initiate settlement.

The outgoing-payment resource is the ASE’s instruction to itself to move funds. Returning a 201 does not mean money has moved; it means the resource server has accepted and durably stored the instruction.

The methods array in the incoming payment response tells the sender’s ASE how to deliver funds. ASEs are responsible for populating this array with valid payment method data for each payment method they support.

When using Interledger (ILP) as the payment method, the resource server must include the following in the methods object:

  • type set to ilp.
  • The recipient ASE’s ILP address, so packets routed over the Interledger network reach the recipient’s ASE.
  • A sharedSecret: a cryptographically generated secret used to secure the STREAM connection between the sender’s and recipient’s ASEs.
incoming-payment methods object (ILP)
"methods": [
{
"type": "ilp",
"ilpAddress": "g.ilp.iwuyge987y.98y08y",
"sharedSecret": "1c7eaXa4rd2fFOBl1iydvCT1tV5TbM3RW1WLCafu_JA"
}
]

ASEs must generate a fresh sharedSecret per incoming payment and must not reuse secrets across resources.

ILP is currently the only payment method defined in the Open Payments standard. Payment methods are messaging mechanisms, not settlement layers. ASEs that need a different payment method must wait for it to be defined and integrated in the standard, or propose adding one. Refer to Get involved.

Open Payments carries payment instructions, it does not move funds. The resource server records the agreement between parties (“ASE A will deliver X to ASE B against this incoming payment”) and exposes it through the APIs.

The ASE is responsible for executing the payment against the underlying accounts.

  • Once the outgoing payment is created and the corresponding incoming payment is open, the sender’s ASE must deliver the agreed amount to the recipient.
  • When the sender and recipient use different ASEs, settlement between those ASEs runs over a shared payment rail outside of Open Payments and ILP.
  • When both parties hold accounts at the same ASE, the ASE may complete the payment by moving funds between those internal accounts. No inter-ASE settlement is required.
  • Open Payments does not touch funds, hold balances, or execute transfers.

ASEs must keep the resource server’s view of payment progress aligned with what has actually been credited to accounts. As funds arrive at the recipient’s account, the resource server must update the receivedAmount on the corresponding incoming payment so clients have an accurate view of payment progress.

Every request to the resource server carries an access token issued by the ASE’s authorization server. Before serving the request, the resource server must validate the token.

  • Is well-formed and not revoked.
  • Covers the requested action (create, read, list, complete) and resource type (incoming-payment, quote, outgoing-payment).
  • Is scoped to the wallet address the request targets, where applicable.
  • Enforces grant limits on outgoing-payment create requests, including debit amount, receive amount, and interval restrictions collected during interactive consent.

How and where tokens are validated is an ASE implementation choice. The checks above must still run on every request before the resource server serves it. For more details on token issuance and lifecycle, refer to Authorization server.

Rafiki provides an open-source reference implementation of Open Payments-compatible servers.