Payment Buttons
Payment buttons let you accept Monero on any website — no backend, no plugins, no JavaScript. Paste a single HTML snippet and customers can pay with one click.
Quick Start
- Go to Dashboard → Buttons
- Choose a button style (Dark, Light, Orange, or Outline)
- Set the amount and currency
- Optionally add a description, customer fields, and link expiration
- Click Generate — copy the HTML snippet
- Paste it into your website
That's it. When a customer clicks the button, they're taken to a Rebel Pay payment page.
Finding Your Store ID
Payment buttons use your Store ID (not your API key) to identify your account. This is a public identifier — safe to embed in client-side HTML.
Find it at: Settings → API Keys — it's displayed at the top of the page.
Button Generator
The easiest way to create buttons is the visual generator in your dashboard. It handles all the details and gives you ready-to-paste HTML.
Options
| Option | Description |
|---|---|
| Style | Dark, Light, Orange, or Outline — choose what fits your site |
| Amount | Fixed payment amount (e.g. 25.00) |
| Currency | USD, EUR, or XMR |
| Description | What the customer is paying for (shown on the payment page) |
| Customer Fields | Collect name, email, order ID, or custom fields before payment |
| Link Expiration | Set when the payment link becomes invalid (hours or absolute date) |
Customer Fields
Collect customer information on the payment page before or during checkout.
Fields render as labeled inputs that the buyer fills out. Their responses are stored
in the charge's metadata.buyer_info
object and delivered in webhook payloads.
How It Works
Add a fields parameter to any payment URL with a
comma-separated list of field names. Each field renders as a text input on the
payment page. Field names must be lowercase alphanumeric with underscores
(a-z, 0-9,
_), max 30 characters each, up to 10 fields.
/pay/new?mid=YOUR_MERCHANT_ID&amount=25¤cy=usd&fields=email,name
Underscores in field names are displayed as spaces with title case.
For example, discord_username renders as "Discord Username"
and order_id renders as "Order Id".
Common Fields
The button generator offers these presets, but you can use any name you want:
name— customer's full nameemail— email address (rendered as an email input with validation)order_ref— your internal order reference
Custom Fields
Use any descriptive field name. Examples:
fields=discord_username,license_key,shipping_address
fields=company_name,vat_number,purchase_order
All field values are limited to 200 characters (254 for email), HTML-stripped, and rate-limited to prevent abuse.
Where Field Data Appears
Buyer responses are available in three places:
- Webhook payloads —
metadata.buyer_info.email,metadata.buyer_info.discord_username, etc. - API response — same path when fetching charge details
- Dashboard — visible in charge detail view
Webhook Example
{
"event": "charge.confirmed",
"data": {
"id": "ch_abc123...",
"amount": 25,
"currency": "USD",
"status": "confirmed",
"metadata": {
"description": "Pro Plan",
"buyer_fields": "email,discord_username",
"buyer_info": {
"email": "customer@example.com",
"discord_username": "player42"
}
}
}
}
Security
- Field names are validated: alphanumeric + underscores only, max 30 characters
- Values are HTML-stripped and length-limited server-side
- Form submissions are rate-limited (10/minute per IP)
- All button URLs are HMAC-signed — tampering with parameters returns a 403 error
- Buyer data is automatically pruned per your data retention policy
Link Expiration
By default, payment buttons work indefinitely. You can set an expiration so the button stops accepting new payments after a certain time — useful for limited-time offers, event tickets, or flash sales.
Two ways to set expiration:
- Hours from now — e.g. "24 hours" (the button generator calculates the absolute time)
- Absolute date/time — e.g. "2026-03-01T00:00:00Z"
After expiration, clicking the button shows an "This payment link has expired" message instead of creating a charge.
API Reference
If you need programmatic control — generating buttons dynamically, integrating with your own frontend, or building a custom checkout — use the button API directly.
Create Button Charge
POST /api/charges/button
Public endpoint — no API key required. Uses your Store ID instead.
Request Body:
{
"merchant_id": "681ca94c03a7...", // Required — from Settings → API Keys
"amount": 25.00, // Required
"currency": "USD", // Optional (default: USD)
"description": "Premium Plan", // Optional
"fields": ["name", "email"], // Optional — collect customer info
"buyer_fields": { // Optional — pre-filled field values
"name": "John Doe",
"email": "john@example.com",
"order_id": "ORD-123"
},
"expires_at": "2026-03-01T00:00:00Z", // Optional — absolute expiration
"expires_in": 24 // Optional — hours until expiration
}
Response:
{
"id": "ch_abc123def456",
"status": "pending",
"amount": 25.00,
"currency": "USD",
"amount_xmr": 0.071428,
"subaddress": "84Hv16y6x7BTie3ib...",
"pay_url": "/pay/ch_abc123def456",
"expires_at": "2026-02-16T09:00:00.000Z",
"created_at": "2026-02-16T08:00:00.000Z"
}
After creating the charge, redirect the customer to /pay/{charge_id}
to show the payment page with QR code and Monero address.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
merchant_id |
string | Yes | Your Store ID (from Settings) |
amount |
number | Yes | Payment amount |
currency |
string | No | USD, EUR, or XMR (default: USD) |
description |
string | No | Shown on payment page |
fields |
array | No | Field names to collect: ["name", "email", "order_id"] or any custom string |
buyer_fields |
object | No | Pre-filled values for fields (from form submission) |
expires_at |
string | No | ISO 8601 timestamp — link expires at this time |
expires_in |
number | No | Hours until expiration (alternative to expires_at) |
Examples
Simple Button (No Fields)
A basic "Pay $25" button — customer clicks and goes straight to payment:
curl -X POST https://your-server.com/api/charges/button \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "YOUR_MERCHANT_ID",
"amount": 25.00,
"currency": "USD",
"description": "T-shirt"
}'
With Customer Fields
Collect name and email before payment:
curl -X POST https://your-server.com/api/charges/button \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "YOUR_MERCHANT_ID",
"amount": 49.99,
"currency": "USD",
"description": "Annual License",
"fields": ["name", "email"],
"buyer_fields": {
"name": "Jane Smith",
"email": "jane@example.com"
}
}'
With Custom Fields
Collect anything you need — Discord handle, license key, shipping info:
curl -X POST https://your-server.com/api/charges/button \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "YOUR_MERCHANT_ID",
"amount": 9.99,
"currency": "USD",
"description": "Discord Premium Role",
"fields": ["email", "Discord Username"],
"buyer_fields": {
"email": "user@example.com",
"Discord Username": "user#1234"
}
}'
With Expiration
Create a time-limited payment link:
curl -X POST https://your-server.com/api/charges/button \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "YOUR_MERCHANT_ID",
"amount": 199.00,
"currency": "USD",
"description": "Early Bird Conference Ticket",
"fields": ["name", "email"],
"expires_in": 48
}'
Webhook Data
Customer field data is included in all webhook events for that charge, under
data.metadata.buyer_fields:
{
"event": "charge.confirmed",
"data": {
"id": "ch_abc123",
"amount": 49.99,
"currency": "USD",
"status": "confirmed",
"metadata": {
"description": "Annual License",
"buyer_fields": {
"name": "Jane Smith",
"email": "jane@example.com"
}
}
}
}
Use this to fulfill orders, send confirmations, or update your CRM. See Webhooks for the full event reference.
Security
- Store ID is public — safe to embed in HTML. It can only be used to create charges for your account; it cannot read data or perform any other actions.
- Never embed your API key — API keys have full read/write access to your account. Keep them server-side only.
- Rate limited — the button endpoint is rate-limited to prevent abuse.
- Charge validation — each charge gets a unique Monero subaddress. Payments are verified on-chain with 10 confirmations.
Next Steps
- Button Generator — create buttons visually
- Payment Requests — rate-at-payment-time invoices
- Webhooks — get notified when payments confirm
- Custom Integration — build your own payment flow