| sidebar_position | 4 |
|---|
This guide outlines the process for platforms to receive payments from UMA addresses.
The following sequence diagram illustrates the interaction between your platform and the UMAaaS API when receiving payments:
sequenceDiagram
participant Sender as External Sender
participant UMAaaS as UMAaaS API
participant Client as Your Platform
participant Bank as Banking Provider
Note over Client, UMAaaS: One-time setup
Client->>UMAaaS: PUT /config (set domain, webhook URL)
UMAaaS-->>Client: Configuration saved
Client->>UMAaaS: POST /users (register users with bank info)
UMAaaS-->>Client: User registered
Note over Sender, UMAaaS: Payment initiated by sender
Sender->>UMAaaS: Initiates payment to UMA address
UMAaaS->>Client: Webhook: INCOMING_PAYMENT (PENDING)
alt Payment approved
Client-->>UMAaaS: HTTP 200 OK (approve payment, provide PII if requested)
UMAaaS->>Bank: Execute payment to user's bank account
UMAaaS->>Client: Webhook: INCOMING_PAYMENT (COMPLETED)
Client-->>UMAaaS: HTTP 200 OK (acknowledge completion)
else Payment rejected
Client-->>UMAaaS: HTTP 403 Forbidden with rejection reason
UMAaaS->>Sender: Payment rejected notification
end
The process consists of five main steps:
- Platform configuration (one-time setup) to set your UMA domain and required counterparty fields
- Register users with their bank account information so they can receive payments
- Set up webhook endpoints to receive notifications about incoming payments
- Receive and approve/reject incoming payments via webhooks
- Receive completion notification when the payment completes
Configure your platform settings (if you haven't already in the onboarding process). See the Platform Configuration guide for more details.
First, register your users in the system so they can receive payments via UMA. You can optionally include a platformAccountId in the bank account information to link accounts with your internal systems.
POST /usersRequest body:
{
"umaAddress": "$john.receiver@thegoodbank.com",
"platformUserId": "9f84e0c2a72c4fa",
"userType": "INDIVIDUAL",
"fullName": "John Receiver",
"birthDate": "1985-06-15",
"address": {
"line1": "123 Pine Street",
"line2": "Unit 501",
"city": "Seattle",
"state": "WA",
"postalCode": "98101",
"country": "US"
},
"bankAccountInfo": {
"accountType": "US_ACCOUNT",
"accountNumber": "123456789",
"routingNumber": "987654321",
"accountCategory": "CHECKING",
"bankName": "Chase Bank",
"platformAccountId": "chase_primary_1234"
}
}See the Configuring Users guide for more details.
Configure your webhook endpoints to receive notifications about incoming payments. You'll need to implement the webhook endpoints on your server. Remember to validate webhook signatures to ensure they are authentic. See the Webhook Verification guide for more details.
When someone initiates a payment to one of your users' UMA addresses, you'll receive a webhook call with a pending transaction:
{
"transaction": {
"transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000005",
"status": "PENDING",
"type": "INCOMING",
"senderUmaAddress": "$mary.sender@thelessgoodbank.com",
"receiverUmaAddress": "$john.receiver@thegoodbank.com",
"receivedAmount": {
"amount": 50000,
"currency": {
"code": "USD",
"name": "United States Dollar",
"symbol": "$",
"decimals": 2
}
},
"userId": "User:019542f5-b3e7-1d02-0000-000000000001",
"platformUserId": "9f84e0c2a72c4fa",
"description": "Payment for services",
"counterpartyInformation": {
"FULL_NAME": "Mary Sender",
"BIRTH_DATE": "1985-06-15"
},
"reconciliationInstructions": {
"reference": "REF-123456789"
}
},
"requestedReceiverUserInfoFields": [
{ "name": "COUNTRY_OF_RESIDENCE", "mandatory": true },
{ "name": "FULL_NAME", "mandatory": true },
{ "name": "NATIONALITY", "mandatory": false }
],
"timestamp": "2023-08-15T14:32:00Z",
"webhookId": "Webhook:019542f5-b3e7-1d02-0000-000000000007",
"type": "INCOMING_PAYMENT"
}The counterpartyInformation object contains PII about the sender, provided by their VASP. The requestedReceiverUserInfoFields array, if present, lists information fields that the sender's VASP (or governing regulations) require about your user (the recipient). UMAaaS does not have this information and is requesting it from your platform to proceed with the payment. Each item in this array is an object specifying the name of the field (from UserInfoFieldName) and whether it's mandatory.
You have two options for approving or rejecting the payment:
To approve the payment synchronously, respond with a 200 OK status:
- If the
requestedReceiverUserInfoFieldsarray was present in the webhook request and contained mandatory fields, your200 OKresponse must include a JSON body containing areceiverUserInfoobject. This object should contain the key-value pairs for the information fields that were requested. - If
requestedReceiverUserInfoFieldswas not present, was empty, or contained only non-mandatory fields for which you have no information, your200 OKresponse can have an empty body.
Example 200 OK response body when information was requested and provided:
{
"receiverUserInfo": {
"COUNTRY_OF_RESIDENCE": "US",
"FULL_NAME": "John Receiver"
}
}To reject the payment, respond with a 403 Forbidden status and a JSON body with the following fields:
{
"code": "payment_rejected",
"message": "Payment rejected due to compliance policy",
"details": {
"reason": "failed_counterparty_check",
"rejectionReason": "User is in a restricted jurisdiction"
}
}If your platform's architecture requires asynchronous processing before approving or rejecting the payment, you can:
- Return a
202 Acceptedresponse to acknowledge receipt of the webhook - Process the payment asynchronously
- Call either the
/transactions/{transactionId}/approveor/transactions/{transactionId}/rejectendpoint within 5 seconds
Example of approving asynchronously:
POST /transactions/Transaction:019542f5-b3e7-1d02-0000-000000000005/approveRequest body (if information was requested):
{
"receiverUserInfo": {
"COUNTRY_OF_RESIDENCE": "US",
"FULL_NAME": "John Receiver"
}
}Example of rejecting asynchronously:
POST /transactions/Transaction:019542f5-b3e7-1d02-0000-000000000005/rejectRequest body (optional):
{
"reason": "RESTRICTED_JURISDICTION"
}Important: If you choose the asynchronous path, you must call the approve/reject endpoint within 5 seconds, or the payment will be automatically rejected. The synchronous path (Option 1) is preferred where possible.
When the payment completes, your webhook endpoint will receive another notification:
{
"transaction": {
"transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000005",
"status": "COMPLETED",
"type": "INCOMING",
"senderUmaAddress": "$mary.sender@thelessgoodbank.com",
"receiverUmaAddress": "$john.receiver@thegoodbank.com",
"receivedAmount": {
"amount": 50000,
"currency": {
"code": "USD",
"name": "United States Dollar",
"symbol": "$",
"decimals": 2
}
},
"userId": "User:019542f5-b3e7-1d02-0000-000000000001",
"platformUserId": "9f84e0c2a72c4fa",
"settledAt": "2023-08-15T14:30:00Z",
"createdAt": "2023-08-15T14:25:18Z",
"description": "Payment for services",
"counterpartyInformation": {
"FULL_NAME": "Mary Sender",
"BIRTH_DATE": "1985-06-15"
},
"reconciliationInstructions": {
"reference": "REF-123456789"
}
},
"timestamp": "2023-08-15T14:32:00Z",
"webhookId": "Webhook:019542f5-b3e7-1d02-0000-000000000007",
"type": "INCOMING_PAYMENT"
}This section is not necessary knowledge for platforms, but it describes the flow at a more detailed level including UMA protocol messages for those who are curious.
sequenceDiagram
participant Sender as External Sender
participant UMAaaS as UMAaaS API
participant Client as Your Platform
participant Bank as Banking Provider
Note over Sender, UMAaaS: Payment initiated by sender
Sender->>UMAaaS: Lnurlp request for UMA address
Note over UMAaaS: Resolves the UMA address to a registered user
UMAaaS->>Sender: Lnurlp response with currencies and requested payer fields
Sender->>UMAaaS: Payreq request with payer information and amount
UMAaaS->>Client: Webhook: INCOMING_PAYMENT (PENDING)
alt Payment approved
Client-->>UMAaaS: HTTP 200 OK (approve payment, provide recipient PII if requested)
UMAaaS-->>Sender: Payreq response with payee info and a Lightning Invoice
Note over Sender: Sender pays Lightning Invoice
UMAaaS->>Bank: Execute payment to user's bank account
UMAaaS->>Client: Webhook: INCOMING_PAYMENT (COMPLETED)
Client-->>UMAaaS: HTTP 200 OK (acknowledge completion)
else Payment rejected
Client-->>UMAaaS: HTTP 403 Forbidden with rejection reason
UMAaaS->>Sender: Failed payreq response.
end