Crypto payments for 3x-ui
A small self-hosted service that lets your 3x-ui panel take crypto payments through SnapEX Pay. Your Telegram bot or website asks it for a checkout link, the customer pays in USDT on the SnapEX Pay page, and when the invoice is paid the service adds a client to your inbound, or extends the existing one, and returns the subscription link. 3x-ui itself has no billing, so this is the payment layer between your shop and the panel.
Free. Version 1.0.0.
What it does
- Each order gets its own SnapEX Pay invoice and
pay_url. Customers pay in USDT on TRC20, ERC20 or BEP20; other coins can appear on the payment page when SnapEX Pay can offer them. - A new username becomes a new client on
XUI_INBOUND_ID. An existing one is renewed: expiry is pushed forward (or counted from now if it already ran out), the client is re-enabled and traffic is reset for plans with a quota. The UUID andsubIdstay the same, so the customer's config keeps working. - Works with 3x-ui 2.x and 3.x: tested against 3x-ui 2.6.0, 2.9.4 and 3.9.0 with VLESS and Trojan inbounds.
- Safe webhooks: HMAC-SHA256 signatures with a 5-minute window, the invoice status is always re-read from the SnapEX Pay API, and each invoice is provisioned only once.
- Plans (days, USD price, traffic quota) in one environment variable. One container: FastAPI and SQLite.
Install
- In the SnapEX Pay merchant cabinet create an API key with the
invoices.readandinvoices.writescopes. - Download and unpack the archive, then in its folder run
cp .env.example .envand fill inSNAPEX_API_KEY,API_TOKEN,XUI_URL(with the web base path),XUI_USERNAMEandXUI_PASSWORD,XUI_INBOUND_IDandXUI_SUB_URL. - Start it:
docker compose up -d, then checkcurl http://localhost:8080/health. - Put the service behind HTTPS (nginx, Caddy, Traefik). In the cabinet add a webhook endpoint
https://<your service>/webhook, put its signing secret intoSNAPEX_WEBHOOK_SECRETand rundocker compose up -dagain. - From your bot or backend call
POST /v1/checkoutwithAuthorization: Bearer <API_TOKEN>, sendpay_urlto the customer and checkGET /v1/orders/{invoice_id}for the subscription link.
Settings
| SNAPEX_API_KEY, SNAPEX_WEBHOOK_SECRET | Merchant API key (invoices.read, invoices.write) and the webhook signing secret (whsec_…). |
|---|---|
| SNAPEX_ENVIRONMENT, SNAPEX_FEE_ON | live or test invoices; who pays the service fee — merchant or customer. |
| API_TOKEN | Bearer token for /v1/checkout and /v1/orders. |
| XUI_URL | Panel URL including the web base path, e.g. https://xui.example.com:2053/secretpath. |
| XUI_API_TOKEN | 3x-ui 3.x only: a panel API token used instead of username and password (for panels with two-factor login). |
| XUI_INBOUND_ID, XUI_SUB_URL | Inbound for new clients (VLESS, VMess, Trojan, Shadowsocks or Hysteria) and the subscription prefix. |
| PLANS | Comma-separated id:days:usd:traffic_bytes, 0 bytes = unlimited. |
Questions
Which 3x-ui versions are supported?
3x-ui 2.x and 3.x: both the new /panel/api/clients API and the older inbounds/addClient API. Tested against 2.6.0, 2.9.4 and 3.9.0.
What happens when a customer renews?
Send the same username again. The client keeps its UUID and subId, expiry is pushed forward, the client is re-enabled and traffic is reset for plans with a quota.
My panel has two-factor login. Will it work?
On 3x-ui 3.x, yes: set XUI_API_TOKEN (an admin-scope panel API token) instead of username and password.
Can one payment be provisioned twice?
No. Each invoice is provisioned only once, even if the webhook arrives twice or two copies arrive at the same time.
Is there a ready Telegram bot?
Yes, a separate SnapEX Pay Telegram bot for Marzban, 3x-ui and Remnawave. This service fits when you already have your own bot or site.
Other integrations
Ready to accept crypto?
Create a merchant account, get an API key and connect the module. 1% per payment, no monthly fee.