API Reference
Accept crypto payments with a simple REST API. Create checkout sessions, manage orders, process refunds, and receive real-time webhooks.
https://payments.pebblepay.io/api/v1Quick Start
Get up and running in under 5 minutes
Get your API key
Sign up and generate your API key from the Integration page.
Create an order
POST to /api/v1/orders with amount and get a checkout URL.
Handle webhooks
Receive real-time notifications when payments complete.
Your first API call
curl -X POST https://payments.pebblepay.io/api/v1/orders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 29.99,
"product_name": "Premium License",
"customer_email": "customer@example.com"
}'The response includes a checkout_url — redirect your customer there to complete payment.
Test Mode
Test your integration without processing real payments
How Test Mode Works
Test payments go through the full payment flow (including webhooks) but don't affect your balance or revenue. Test transactions are marked with a purple "Test" badge in your dashboard and include is_test: true in webhook payloads.
Enable Test Mode
Add testMode: true to your API request or checkout link:
curl -X POST https://payments.pebblepay.io/api/v1/orders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 29.99,
"product_name": "Test Purchase",
"customer_email": "test@example.com",
"testMode": true
}'Test Card Numbers
Use these card numbers to simulate different payment scenarios:
| Card Number | Brand | Result |
|---|---|---|
4000 0000 0000 0002 | Visa | Success |
4000 0000 0000 1091 | Visa | Success with 3DS |
5200 0000 0000 0007 | Mastercard | Success |
5200 0000 0000 1096 | Mastercard | Success with 3DS |
4000 0000 0000 0069 | Visa | Declined (Expired) |
4000 0000 0000 0119 | Visa | Declined (Insufficient Funds) |
4000 0000 0000 0259 | Visa | 3DS Authentication Failed |
Test Card Details
- Expiry Date: Any future date (e.g., 12/30)
- CVV: Any 3 digits (e.g., 123)
- Name: Any name
- Address: Any valid address format
Test Webhooks
Test mode webhooks include an is_test field so you can identify test transactions:
{
"event": "payment.completed",
"order_id": "PP-2603-ABC123",
"amount": 29.99,
"currency": "USD",
"customer_email": "test@example.com",
"is_test": true,
"timestamp": "2026-03-15T10:30:00Z"
}Important
Always check the is_test field in your webhook handler. Don't fulfill orders or grant access for test payments in production!
Frontend SDK (pebblepay.js)
The fastest way to add payments to any website - no backend required
Works Everywhere
HTML sites, WordPress, Wix, Squarespace, Webflow, Shopify (custom pages), React, Vue, Angular, or any framework.
Add the script to your website
Drop this before the closing </body> tag:
<script src="https://payments.pebblepay.io/js/pebblepay.js" data-store="YOUR_STORE_ID"></script>
Add a pay button anywhere
Any element with data-pebblepay becomes a payment button:
<!-- Option 1: Standard checkout with custom amount --> <button data-pebblepay="checkout" data-amount="49.99" data-product="Premium License" data-success-url="https://yoursite.com/success" data-webhook-url="https://yoursite.com/api/webhooks"> Buy Now - $49.99 </button> <!-- Option 2: Secure pricing with variant_id (price from dashboard) --> <button data-pebblepay="checkout" data-variant-id="var_abc123" data-success-url="https://yoursite.com/success"> Buy License </button> <!-- Available attributes --> <!-- data-amount: Payment amount in USD (ignored if data-variant-id is set) --> <!-- data-variant-id: License variant ID - price is pulled from dashboard (secure) --> <!-- data-product: Product/service name --> <!-- data-coupon: Coupon code to apply --> <!-- data-success-url: Redirect URL after success (alias: data-return-url) --> <!-- data-cancel-url: Redirect URL if cancelled --> <!-- data-webhook-url: URL to receive POST notification --> <!-- data-reference: Your order/invoice reference -->
Handle the result (optional)
Listen for payment events:
window.addEventListener('message', (e) => {
if (e.data.type === 'pebblepay:payment_complete') {
console.log('Payment succeeded!', e.data.transactionId)
// Deliver product, show success, etc.
}
if (e.data.type === 'pebblepay:payment_failed') {
console.log('Payment failed:', e.data.error)
}
})WordPress / WooCommerce
Add to footer.php or use a code snippets plugin
<!-- Add before </body> --> <script src="https://payments.pebblepay.io/js/pebblepay.js" data-store="YOUR_STORE_ID"></script>
React / Next.js
Use the Script component
import Script from 'next/script' <Script src="https://payments.pebblepay.io/js/pebblepay.js" data-store="YOUR_STORE_ID" />
Checkout Links
Direct customers to a hosted payment page with a simple URL
Features
Perfect for social media bios, email invoices, WhatsApp payments, selling without a website, donations, tips, and freelance work.
Your Checkout URL
https://payments.pebblepay.io/checkout/YOUR_STORE_ID
URL Parameters
amountPayment amount (0.50 - 50,000). Ignored if variant_id is set. If omitted, customer enters amount.variant_idLicense variant ID - price is pulled from dashboard (secure, cannot be manipulated).productProduct or service name displayed on checkout.couponCoupon code to pre-apply a discount.refYour order/invoice reference for tracking (e.g., INV-001).return_urlRedirect URL after successful payment (alias: success_url).cancel_urlRedirect URL if customer cancels.Secure Pricing with variant_id
When using variant_id, the price is always pulled from your dashboard - not from URL parameters. This prevents customers from modifying the checkout URL to pay less. Any amount parameter will be ignored.
Examples
# Fixed price product https://payments.pebblepay.io/checkout/YOUR_STORE_ID?amount=49.99&product=Premium%20Plan # Secure pricing with variant_id (price from dashboard - recommended) https://payments.pebblepay.io/checkout/YOUR_STORE_ID?variant_id=var_abc123 # With coupon code https://payments.pebblepay.io/checkout/YOUR_STORE_ID?variant_id=var_abc123&coupon=SAVE20 # With redirect after payment https://payments.pebblepay.io/checkout/YOUR_STORE_ID?amount=29.99&product=Course&return_url=https://yoursite.com/success # Full hosted checkout flow with order reference https://payments.pebblepay.io/checkout/YOUR_STORE_ID?amount=99.99&product=Order&ref=INV-001&return_url=https://yoursite.com/success # Pay-what-you-want (donations) https://payments.pebblepay.io/checkout/YOUR_STORE_ID?product=Donation
Webhooks are configured in your Dashboard Settings and sent server-side for all payments.
After Payment Redirect
When using return_url, customers are redirected with these query parameters:
https://yoursite.com/success ?order_id=abc123 &transaction_id=txn_xyz789 &amount=49.99 &status=completed
Webhook Notifications
When a payment completes, we automatically send a signed webhook to your configured URL. Configure your webhook endpoint in your Dashboard Settings.
Events: payment.completed, payment.failed, payment.refunded
Security: Signed with HMAC-SHA256 via X-Webhook-Signature header
Retries: Failed deliveries are retried automatically
Embed Checkout
Display the checkout directly on your website with an iframe
Features
Embed URL
https://payments.pebblepay.io/checkout/embed?store_id=YOUR_STORE_ID
URL Parameters
store_idrequiredamountcurrencysuccess_urlrefBasic Embed
<iframe src="https://payments.pebblepay.io/checkout/embed?store_id=YOUR_STORE_ID&amount=49.99" width="100%" height="600" frameborder="0" allow="payment" style="border-radius: 12px; max-width: 480px;"> </iframe>
Listen for Payment Events
The embedded checkout posts messages when payment completes:
<script>
window.addEventListener('message', (event) => {
// Verify origin for security
if (event.origin !== 'https://payments.pebblepay.io') return
if (event.data.type === 'pebblepay:payment_complete') {
console.log('Payment successful!', event.data)
// event.data contains: transactionId, amount, orderId
// Redirect or show success message
window.location.href = '/thank-you?order=' + event.data.orderId
}
if (event.data.type === 'pebblepay:payment_failed') {
console.log('Payment failed', event.data.error)
}
})
</script>Modal/Popup Style
<div id="checkout-modal" style=" position: fixed; inset: 0; background: rgba(0,0,0,0.8); display: flex; align-items: center; justify-content: center; z-index: 9999; "> <iframe src="..." width="400" height="600" /> </div>
Responsive Embed
<div style="
position: relative;
padding-bottom: 150%;
max-width: 400px;
">
<iframe
src="..."
style="
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
"
/>
</div>Authentication
Secure your API requests with Bearer tokens
Keep your API key secure
Never expose your API key in client-side code or public repositories. All API calls should be made from your server.
# Using Authorization header (recommended) curl https://payments.pebblepay.io/api/v1/orders \ -H "Authorization: Bearer sk_live_your_api_key_here" # Alternative: Using X-Api-Key header curl https://payments.pebblepay.io/api/v1/orders \ -H "X-Api-Key: sk_live_your_api_key_here"
Create Order
Generate a checkout session for payment
/api/v1/ordersCreate a checkout session
Creates a new checkout session and returns a URL where your customer can complete payment. Sessions expire after 1 hour.
Parameters
amountvariant_idproduct_nameorder_referencecustomer_emailcustomer_namecoupon_codereturn_urlcancel_urlwebhook_urlmetadatacurl -X POST https://payments.pebblepay.io/api/v1/orders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 49.99,
"product_name": "Premium Subscription",
"order_reference": "ORD-2024-001",
"customer_email": "john@example.com",
"coupon_code": "SUMMER25",
"return_url": "https://yoursite.com/success",
"webhook_url": "https://yoursite.com/webhooks/pebblepay"
}'List Orders
Retrieve all your transactions
/api/v1/ordersList all orders
Returns a paginated list of all your transactions. Use query parameters to filter and paginate.
Parameters
statusorder_referenceorder_idlimitoffset# List all orders curl "https://payments.pebblepay.io/api/v1/orders?limit=50" \ -H "Authorization: Bearer YOUR_API_KEY" # Filter by status curl "https://payments.pebblepay.io/api/v1/orders?status=completed" \ -H "Authorization: Bearer YOUR_API_KEY" # Find by order reference curl "https://payments.pebblepay.io/api/v1/orders?order_reference=ORD-2024-001" \ -H "Authorization: Bearer YOUR_API_KEY"
Get Order
Retrieve a single transaction by ID
/api/v1/orders/:idGet order details
Retrieves details of a specific order by transaction ID, order ID (PP-XXXX-XXXXXX), or checkout session ID.
# By transaction ID curl "https://payments.pebblepay.io/api/v1/orders/txn_abc123" \ -H "Authorization: Bearer YOUR_API_KEY" # By order ID curl "https://payments.pebblepay.io/api/v1/orders/PP-1234-567890" \ -H "Authorization: Bearer YOUR_API_KEY"
Coupons
Create and manage discount coupons programmatically
/api/v1/couponsCreate Coupon
Create a new coupon code for discounts. Coupons can be percentage-based or fixed amount.
Parameters
coderequireddiscount_typerequireddiscount_valuerequireddescriptionmin_amountmax_usesmax_uses_per_customerexpires_atcurl -X POST https://payments.pebblepay.io/api/v1/coupons \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "LUCKY27",
"discount_type": "percentage",
"discount_value": 27,
"description": "Lucky discount - one per customer",
"max_uses_per_customer": 1,
"expires_at": "2026-12-31T23:59:59Z"
}'/api/v1/couponsList Coupons
Retrieve all coupons for your account with optional filtering.
Parameters
activelimitoffsetcurl https://payments.pebblepay.io/api/v1/coupons?active=true \ -H "Authorization: Bearer YOUR_API_KEY"
/api/v1/coupons/:idGet Coupon
Retrieve a specific coupon by ID.
Parameters
idrequiredcurl https://payments.pebblepay.io/api/v1/coupons/coup_a1b2c3d4 \ -H "Authorization: Bearer YOUR_API_KEY"
/api/v1/coupons/:idUpdate Coupon
Update a coupon's settings. Note: code, discount_type, and discount_value cannot be changed after creation.
Parameters
descriptionmin_amountmax_usesmax_uses_per_customerexpires_atis_activecurl -X PUT https://payments.pebblepay.io/api/v1/coupons/coup_a1b2c3d4 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"max_uses_per_customer": 2,
"is_active": false
}'/api/v1/coupons/:idDelete Coupon
Permanently delete a coupon. This action cannot be undone.
Parameters
idrequiredcurl -X DELETE https://payments.pebblepay.io/api/v1/coupons/coup_a1b2c3d4 \ -H "Authorization: Bearer YOUR_API_KEY"
Refunds
Process refunds programmatically
/api/v1/orders/:id/refundRefund an order
Refunds a completed order. The refund is processed immediately. Net amount is returned to your balance.
Parameters
reasoncurl -X POST "https://payments.pebblepay.io/api/v1/orders/txn_abc123/refund" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Customer requested refund" }'Webhooks
Receive real-time payment notifications
Webhooks notify your server when events happen. Configure your webhook URL in your dashboard.
payment.completedPayment successfulpayment.refundedPayment was refundedpayment.disputedCustomer opened disputepayment.failedPayment attempt failedPayload Example
{
"event": "payment.completed",
"transaction_id": "txn_abc123...",
"order_id": "PP-1234-567890",
"status": "completed",
"amount": 49.99,
"fee_amount": 2.50,
"net_amount": 47.49,
"currency": "USD",
"customer_email": "john@example.com",
"customer_name": "John Doe",
"product_name": "Premium Subscription",
"order_reference": "ORD-2024-001",
"metadata": { "plan": "premium", "user_id": "123" },
"timestamp": "2024-02-24T13:00:00Z"
}Security: Always Verify Signatures
Your Webhook Signing Key is in Dashboard → Settings. Without signature verification, attackers who discover your webhook URL could fake payment confirmations. Always verify the X-Webhook-Signature header before fulfilling orders.
Webhook Headers
Every webhook includes these headers:
X-Webhook-SignatureHMAC-SHA256 signature for verificationX-Webhook-IdUnique transaction ID for deduplicationContent-Typeapplication/jsonVerify Signatures
Verify the X-Webhook-Signature to ensure the webhook came from PebblePay.
const crypto = require('crypto');
// Get your signing key from Dashboard > Settings
const WEBHOOK_SECRET = process.env.PEBBLEPAY_WEBHOOK_SECRET;
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expected, 'hex')
);
}
// In your webhook handler:
app.post('/webhooks/pebblepay', (req, res) => {
const signature = req.headers['x-webhook-signature'];
// CRITICAL: Always verify the signature!
if (!verifyWebhook(req.body, signature, WEBHOOK_SECRET)) {
console.error('Invalid webhook signature - possible attack!');
return res.status(401).send('Invalid signature');
}
const { event, transaction_id, is_test } = req.body;
// Skip fulfillment for test payments
if (is_test) {
console.log('Test payment received:', transaction_id);
return res.status(200).send('OK');
}
if (event === 'payment.completed') {
// Fulfill the order
}
res.status(200).send('OK');
});Error Handling
Understanding API errors
| Status | Meaning |
|---|---|
| 200 | Request successful |
| 201 | Resource created |
| 400 | Bad request - check parameters |
| 401 | Unauthorized - invalid API key |
| 403 | Forbidden - account not approved |
| 404 | Resource not found |
| 500 | Internal server error |
{
"error": "amount is required and must be between 0.50 and 50000.00"
}PCI DSS Compliance
Important: Card Data Handling
PebblePay is PCI DSS compliant and handles all cardholder data securely. As a seller, you must follow these requirements:
Use PebblePay-Hosted Checkout
All card data must be collected through our hosted checkout pages (redirect, popup, or iframe). This keeps your systems out of PCI scope.
Never Collect Card Data Directly
Do not create your own card input forms or attempt to submit card data to our APIs from your domain. This is strictly prohibited and will result in account termination.
Approved Integration Methods
Use the /api/v1/orders endpoint to create checkout sessions, then redirect customers or embed our checkout using the provided checkout_url.
