Skip to content
GitHub

Getting Started

Account Servicing Entities provide and maintain payment accounts. In order to make these accounts Interledger-enabled via Rafiki, they need to provide the following endpoints and services:

Furthermore, each payment account managed by the Account Servicing Entity needs to be issued at least one wallet address in order to be serviced by Rafiki and send or receive Interledger payments.

Exchange Rates

Every Interledger payment is preceded by a rate probe that estimates the costs for transferring value from A to B over the network (= network fee). For the rate probe to be successful, Rafiki needs to be provided with the current exchange rate by the Account Servicing Entity. The Account Servicing Entity needs to expose an endpoint that accepts a GET requests and responds as follows.

Response Body

Variable NameTypeDescription
baseStringasset code represented as ISO 4217 currency code, e.g. USD
ratesObjectObject containing <asset_code : exchange_rate> pairs, e.g. {EUR: 0.8930}
rates.<asset_code>Numberexchange rate given base and <asset_code>

The response status code for a successful request is a 200. The mock-account-servicing-entity includes a minimalistic example.

The backend package requires an environment variable called EXCHANGE_RATES_URL which MUST specify the URL of this endpoint. An OpenAPI specification of that endpoint can be found here.

Fees

The Account Servicing Entity may charge fees on top of the estimated network fee for facilitating the transfer. They can specify fixed and variable fees per asset using the Admin API or UI. How they structure those fees is completely up to the Account Servicing Entity.

Sending fees can be set on a given asset using Admin UI or the setFee graphql mutation if desired:

Mutation:

mutation SetFee($input: SetFeeInput!) {
setFee(input: $input) {
code
success
message
fee {
id
assetId
type
fixed
basisPoints
createdAt
}
}
}

Query Variables:

{
"input": {
"assetId": "14863f6f-4bda-42ef-8715-bf4762898af8",
"type": "SENDING",
"fee": {
"fixed": 100,
"basisPoints": 100
}
}
}

Example Successful Response

{
"data": {
"setFee": {
"code": "200",
"success": true,
"message": "Fee set",
"fee": {
"id": "140fd9c0-8f14-4850-9724-102f04d97e69",
"assetId": "14863f6f-4bda-42ef-8715-bf4762898af8",
"type": "SENDING",
"fixed": "100",
"basisPoints": 100,
"createdAt": "2023-09-13T14:59:53.435Z"
}
}
}
}

Webhook Event Listener

Rafiki itself does not hold any user account balances, but instead, keeps track of liquidity within asset, peer, and payment accounts. This liquidity needs to be managed primarily as a response to certain events that happen in Rafiki. In order for Rafiki to notify the Account Servicing Entity about those events, the Account Servicing Entity need to expose a webhook endpoint that listens for these events and reacts accordingly.

The Account Servicing Entity’s expected behavior when observing these webhook events is detailed in the Webhook Events documentation.

Identity Provider

An Identity Provider is a service that verifies the identity of a user. In order to allow the authorization of payments by third parties, Rafiki must be integrated with an Identity Provider to handle authentication and consent. This information is collected in order to authorize grants made through the Open Payments Standard. The Rafiki backend exposes the APIs for Open Payments, and requests to them are authorized by an opinionated version of the Grant Negotiation Authorization Protocol (GNAP). A reference implementation of a Open Payments Authorization Server is include with Rafiki in the auth package.

The Authorization Server in the auth package extends an API for integrating Identity Providers to use to begin & finish an interaction to collect authorization, acquire information on a particular grant, and communicate that a user has authorized a grant. An OpenAPI specification of those endpoints can be found here.

Issuing Wallet Addresses

A Wallet Address is a standardized identifier for a payment account. It can be created using the Admin API. Note that at least one asset has to be created prior to creating the wallet address since an assetId MUST be provided as input variable on wallet address creation.

Create Asset

Query:

mutation CreateAsset($input: CreateAssetInput!) {
createAsset(input: $input) {
code
success
message
asset {
id
code
scale
}
}
}

Query Variables:

{
"input": {
"code": "USD",
"scale": 2
}
}

Example Successful Response

{
"data": {
"createAsset": {
"code": "200",
"success": true,
"message": "Created Asset",
"asset": {
"id": "0ddc0b7d-1822-4213-948e-915dda58850b",
"code": "USD",
"scale": 2
}
}
}
}

Create Wallet Address

Query:

mutation CreateWalletAddress($input: CreateWalletAddressInput!) {
createWalletAddress(input: $input) {
code
success
message
walletAddress {
id
createdAt
publicName
url
asset {
code
id
scale
}
}
}
}

Query Variables:

*Note additionalProperties are optional.

{
"input": {
"assetId": "0ddc0b7d-1822-4213-948e-915dda58850b",
"publicName": "Sarah Marshall",
"url": "https://example.wallet.com/sarah",
"additionalProperties": [
{
"key": "iban",
"value": "NL93 8601 1117 947",
"visibleInOpenPayments": false
},
{ "key": "nickname", "value": "S Mar", "visibleInOpenPayments": true }
]
}
}

Example Successful Response

{
"data": {
"createWalletAddress": {
"code": "200",
"success": true,
"message": "Created wallet address",
"walletAddress": {
"id": "695e7546-1803-4b45-96b6-6a53f4082018",
"createdAt": "2023-03-03T09:07:01.107Z",
"publicName": "Sarah Marshall",
"url": "https://example.wallet.com/sarah",
"asset": {
"id": "0ddc0b7d-1822-4213-948e-915dda58850b",
"code": "USD",
"scale": 2
}
}
}
}
}

The Account Servicing Entity SHOULD store at least the walletAddress.id in their internal database to be able to reference the account and wallet address.

Create Wallet Address Key

In order to use the Open Payments APIs, a wallet address needs to be associated with at least one private-public-keypair to be able to sign API request. One or multiple public keys are linked to the wallet address such that third-parties can verify said request signatures. It can be added using the Admin API.

Query:

mutation CreateWalletAddressKey($input: CreateWalletAddressKeyInput!) {
createWalletAddressKey(input: $input) {
code
message
success
walletAddressKey {
id
walletAddressId
revoked
jwk {
alg
crv
kid
kty
x
}
createdAt
}
}
}

Query Variables:

{
"input": {
"jwk": {
"kid": "keyid-97a3a431-8ee1-48fc-ac85-70e2f5eba8e5",
"x": "ubqoInifJ5sssIPPnQR1gVPfmoZnJtPhTkyMXNoJF_8",
"alg": "EdDSA",
"kty": "OKP",
"crv": "Ed25519"
},
"walletAddressId": "695e7546-1803-4b45-96b6-6a53f4082018"
}
}

Example Successful Response

{
"data": {
"createWalletAddressKey": {
"code": "200",
"message": "Added Key To Wallet Address",
"success": true,
"walletAddressKey": {
"id": "f2953571-f10c-44eb-ab41-4450a7ad6771",
"walletAddressId": "695e7546-1803-4b45-96b6-6a53f4082018",
"revoked": false,
"jwk": {
"alg": "EdDSA",
"crv": "Ed25519",
"kid": "keyid-97a3a431-8ee1-48fc-ac85-70e2f5eba8e5",
"kty": "OKP",
"x": "ubqoInifJ5sssIPPnQR1gVPfmoZnJtPhTkyMXNoJF_8"
},
"createdAt": "2023-03-03T09:26:41.424Z"
}
}
}
}