Resource server
What the resource server does
Section titled “What the resource server does”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.
incoming-payment
Section titled “incoming-payment”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
receivedAmountas 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 differentassetCodevalues. - Commit to deliver the quoted
receiveAmountto the recipient’s ASE if an outgoing payment is created against the quote within the quote’s validity window. - Assign the quote a
quoteIdand persist it. - Set a validity window after which the quote is no longer honored. ASEs define this window; it must be short enough that rate and fee exposure is bounded and long enough that the client can collect interactive consent before it 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.
outgoing-payment
Section titled “outgoing-payment”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
quoteIdis present, look up the quote, confirm it has not expired, and use the quoted amounts. - If no
quoteIdis present (for example, in Web Monetization-style use cases), use theincomingPaymentanddebitAmountfrom 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.
Payment method details
Section titled “Payment method details”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 rail they support.
When using Interledger (ILP) as the payment method, the resource server must include the following in the methods object:
typeset toilp.- 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.
"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 that integrates with Open Payments. ASEs that intend to settle over a different rail must wait for that rail’s payment method to be defined and integrated.
Application layer vs. settlement layer
Section titled “Application layer vs. settlement layer”Open Payments is a protocol that operates in the application layer. The resource server stores the agreement between the two ASEs (“ASE A will deliver X to ASE B against this incoming payment”) and exposes it through the APIs.
Actual movement of funds happens on the settlement layer:
- Once the outgoing payment is created and the corresponding incoming payment is open, the sender’s ASE is obligated to settle with the recipient’s ASE.
- Settlement runs over a shared payment rail outside of Open Payments.
- Open Payments does not touch funds, hold balances, or execute transfers. The ASE is fully responsible for that.
ASEs must keep the two layers in sync. As funds arrive at the recipient’s ASE, the resource server must update the receivedAmount on the corresponding incoming payment so clients have an accurate view of payment progress.
Token validation
Section titled “Token validation”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 that 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.
ASEs decide whether the resource server validates tokens locally (for example, against a shared cache) or by calling the authorization server. The protocol does not mandate one approach. Whichever pattern an ASE chooses, the resource server must refuse requests with insufficient tokens. For more details on token issuance and lifecycle, refer to Authorization server.
Reference implementation
Section titled “Reference implementation”Rafiki provides an open-source implementation of an Open Payments resource server.