Payments on behalf of a user
A programmatic client can pay for purchases on a user's behalf when the user has pre-authorized a spending limit. This is common for AI assistants or automated systems that act on behalf of a user. It uses the same checkout flow as API payments, but links each payment to a specific user account.
Flow
User → Authorizes agent with spending limit (your app)
Agent → POST /payments/requests (with customer_id)
Agent → GET /payments/public/{request_id}
Agent → Sends XRP on-chain from agent wallet
Agent → POST /payments/{request_id}/verify
DropPay → Sends payment.confirmed webhook (includes customer_id)
Your server → Logs purchase against user's account
Agent → Informs user of completed purchase
Pre-authorization model
Store the user's spending limit in your database. The agent checks this before creating a payment.
agent_auth.py
# Schema: user_authorizations(user_id, agent_id, max_per_tx, max_total, spent_total)
def check_authorization(user_id: str, agent_id: str, amount_xrp: float) -> bool:
auth = db.get_authorization(user_id, agent_id)
if not auth:
return False
if amount_xrp > auth["max_per_tx"]:
return False
if auth["spent_total"] + amount_xrp > auth["max_total"]:
return False
return True
agentAuth.js
// Schema: user_authorizations(user_id, agent_id, max_per_tx, max_total, spent_total)
async function checkAuthorization(userId, agentId, amountXrp) {
const auth = await db.getAuthorization(userId, agentId);
if (!auth) return false;
if (amountXrp > auth.maxPerTx) return false;
if (auth.spentTotal + amountXrp > auth.maxTotal) return false;
return true;
}
Create the payment
Pass customer_id so your webhook handler can link the payment to the user's account.
agent_pay.py
import requests
BASE = "https://droppayxrp.com"
API_KEY = "dp_live_your_api_key_here"
def agent_purchase(user_id: str, agent_id: str, item: dict) -> dict:
if not check_authorization(user_id, agent_id, item["price_xrp"]):
raise PermissionError(f"Exceeds spending limit for user {user_id}")
response = requests.post(
f"{BASE}/payments/requests",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"amount": item["price_xrp"],
"currency": "XRP",
"description": item["name"],
"customer_id": user_id,
"order_id": item["order_id"]
}
)
payment = response.json()
# Get locked amount and wallet from public endpoint
pub = requests.get(
f"{BASE}/payments/public/{payment['request_id']}"
).json()
return {"payment": payment, "pub": pub}
agentPay.js
const BASE = "https://droppayxrp.com";
const API_KEY = "dp_live_your_api_key_here";
async function agentPurchase(userId, agentId, item) {
const authorized = await checkAuthorization(userId, agentId, item.priceXrp);
if (!authorized) {
throw new Error(`Exceeds spending limit for user ${userId}`);
}
const response = await fetch(`${BASE}/payments/requests`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
amount: item.priceXrp,
currency: "XRP",
description: item.name,
customer_id: userId,
order_id: item.orderId
})
});
const payment = await response.json();
const pub = await fetch(
`${BASE}/payments/public/${payment.request_id}`
).then(r => r.json());
return { payment, pub };
}
Send XRP and verify
After creating the payment, send XRP on-chain and call the verify endpoint. The steps are identical to those in API payments - step 2 onwards.
Log the purchase in your webhook
customer_id is returned in the webhook payload under data.customer_id.
webhook.py
event = request.json
if event["event"] == "payment.confirmed":
data = event["data"]
user_id = data["customer_id"]
amount = float(data.get("amount", 0))
db.log_purchase(
user_id=user_id,
order_id=data["order_id"],
amount=amount,
currency=data["currency"],
request_id=data["request_id"]
)
db.update_spending_total(user_id, amount)
webhook.js
if (event.event === "payment.confirmed") {
const { customer_id, order_id, amount, currency, request_id } = event.data;
await db.logPurchase({
userId: customer_id,
orderId: order_id,
amount: parseFloat(amount),
currency,
requestId: request_id
});
await db.updateSpendingTotal(customer_id, parseFloat(amount));
}
Notes
- The agent wallet sends the XRP, not the user's wallet. Pre-load the agent wallet with enough XRP to cover purchases.
- Keep a per-user spending ledger. If the webhook never arrives (network issue), reconcile later via
GET /payments/public/{request_id}. - Notify the user after each purchase via push notification, email, or the next agent reply.
Next steps
- Webhooks reference - full payload with
customer_idfield - API payments - same pattern without per-user authorization