AgentPay VN
<!-- mcp-name: io.github.phuocdu/agentpay-vn -->
   
VietQR payment infrastructure for AI agents β collect money inside any conversation.
AgentPay VN lets AI agents (Claude, GPT, custom bots) generate payment QR codes, send them to users, and automatically confirm when the money arrives β all without ever holding or touching funds. Money flows directly from the payer's bank account into the merchant's account; AgentPay only reads the bank transaction feed to confirm settlement.
Status: Early access / self-hosted β running on the same swarm as Sα» Nợ AI.
---
How it works
AI Agent AgentPay API Bank feed (SePay)
| | |
|-- create_payment_request ->| |
|<- { qr_image_url, id } ----| |
| | |
|-- send QR to user -------->| |
| | user scans & pays |
| |<-- webhook (bank txn) ----|
| |-- match AP* pay_code |
| |-- status β settled |
|<-- await_settlement done --| |
| | |
|-- deliver order / unlock ->| |
- Create β agent calls
POST /v1/payment-requestsβ gets a VietQR image URL and a checkout page. - Send β agent embeds the QR image or sends the checkout link to the user in chat.
- Await β agent calls
await_settlement()(or the MCP tool) to poll untilstatus = settled. - Deliver β only after confirmed settlement does the agent release the goods/service.
AgentPay never holds money. The QR points directly at the merchant's bank account number. The platform only monitors the bank transaction feed to detect matching transfers.
---
Quick start
1. Install
pip install agentpay-vn
2. Set your API key
export AGENTPAY_API_KEY=ap_test_xxx # sandbox key for testing
Get a key from the admin dashboard (self-hosted) or contact the platform operator.
3. Collect a payment (3 lines)
from agentpay.client import AsyncAgentPayClient, await_settlement
import asyncio
async def main():
async with AsyncAgentPayClient("ap_test_xxx") as client:
pr = await client.create_payment_request(amount=50_000, description="Order #1")
print(pr["checkout_url"]) # send this link to your user
result = await await_settlement(client, pr["id"], timeout=120)
assert result["status"] == "settled"
asyncio.run(main())
See examples/quickstart.py for the full runnable version.
---
MCP server setup
AgentPay ships an MCP server so any MCP-compatible AI agent can call it as a tool β no extra code needed.
Claude Desktop / Claude Code
Add to claude_desktop_config.json (or use examples/claude_desktop_config.json):
{
"mcpServers": {
"agentpay": {
"command": "python",
"args": ["-m", "agentpay.mcp_server"],
"env": {
"AGENTPAY_API_KEY": "ap_test_xxx",
"AGENTPAY_BASE_URL": "https://agentpay.servicesai.vn/v1"
}
}
}
}
Or use the installed console script:
{
"mcpServers": {
"agentpay": {
"command": "agentpay-mcp",
"env": { "AGENTPAY_API_KEY": "ap_live_xxx" }
}
}
}
Available MCP tools
| Tool | Description | |------|-------------| | create_payment_request | Generate a VietQR code for a given amount | | check_payment | Get current status of a payment request | | await_settlement | Poll until payment arrives or timeout (max 600 s) | | list_recent_payments | List last N settled transactions |
---
Python SDK
Synchronous
from agentpay.client import AgentPayClient
with AgentPayClient("ap_live_xxx") as client:
# Create
pr = client.create_payment_request(
amount=150_000,
description="Consulting session 30 min",
ttl_minutes=30,
idempotency_key="session-abc-123",
)
# Poll manually
import time
for _ in range(60):
pr = client.get_payment_request(pr["id"])
if pr["status"] != "pending":
break
time.sleep(5)
# Reconcile
txns = client.list_transactions(limit=10)
Asynchronous
from agentpay.client import AsyncAgentPayClient, await_settlement
async with AsyncAgentPayClient("ap_live_xxx") as client:
pr = await client.create_payment_request(amount=75_000, description="eBook download")
result = await await_settlement(client, pr["id"], timeout=300)
if result["status"] == "settled":
send_download_link(result["metadata"].get("email"))
Webhook verification
import hashlib, hmac
def verify_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header)
Register a webhook endpoint:
ep = client.register_webhook(
url="https://your-server.com/webhooks/agentpay",
events=["payment.settled", "payment.expired"],
)
print(ep["secret"]) # store this β shown only once
---
API reference
- OpenAPI spec:
agentpay-openapi.yaml - Base URL:
https://agentpay.servicesai.vn/v1 - Authentication:
Authorization: Bearer ap_live_xxx(orap_test_xxxfor sandbox)
Key endpoints
| Method | Path | Description | |--------|------|-------------| | POST | /v1/payment-requests | Create payment request | | GET | /v1/payment-requests/{id} | Get status | | POST | /v1/payment-requests/{id}/cancel | Cancel pending request | | GET | /v1/transactions | List settled transactions | | POST | /v1/webhook-endpoints | Register webhook URL | | POST | /v1/sandbox/simulate-settlement | Simulate payment (sandbox only) | | GET | /pay/{pay_code} | Public checkout page (HTML, mobile-friendly) |
---
Self-hosting
AgentPay runs as part of the SỠNợ AI FastAPI backend.
Requirements
- Docker Swarm cluster (same as Sono)
- MongoDB (shared with Sono)
- SePay bank feed account (for live payments)
- Nginx with an
agentpay.servicesai.vnvhost
Environment variables
| Variable | Default | Description | |----------|---------|-------------| | AGENTPAY_BASE_URL | https://agentpay.servicesai.vn | Public base URL for checkout links | | MONGO_URI | mongodb://localhost:27017 | Inherited from Sono | | BILLING_WEBHOOK_TOKEN | β | SePay webhook token (inherited) |
Create an API key (admin)
curl -X POST https://sono.servicesai.vn/api/admin/agentpay/keys \
-H "Authorization: Bearer <admin-jwt>" \
-H "Content-Type: application/json" \
-d '{"org_id": "<shop-user-id>", "name": "My bot", "livemode": true}'
The response includes the full key β store it immediately; it is shown only once.
---
Rate limits
| Tier | Settled payments/month | Requests/minute | |------|----------------------|-----------------| | Free | 50 | 120 |
---
Design principles
- No money held β QR codes point directly at the merchant's bank account. AgentPay only reads the transaction feed; it never touches the money.
- Idempotency β pass an
Idempotency-Keyheader onPOST /payment-requeststo safely retry without creating duplicates (24-hour deduplication window).
- HMAC webhook verification β every outbound webhook is signed with
HMAC-SHA256(whsec_..., raw_body)in theAgentPay-Signatureheader. Always verify before processing.
- Sandbox β use
ap_test_*keys andPOST /v1/sandbox/simulate-settlementto develop and test without real transactions.
- Minimal trust surface β the MCP server is a thin REST client with no local secrets beyond the API key. Compromising an agent key only exposes one tenant's payment-request creation ability.
---
License
MIT Β© 2026 ServicesAI β see LICENSE.











