PebblePayPebblePayAPI Docs
v1.0

Documentation

All Docs
All systems operational

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/v1

Quick Start

Get up and running in under 5 minutes

1

Get your API key

Sign up and generate your API key from the Integration page.

2

Create an order

POST to /api/v1/orders with amount and get a checkout URL.

3

Handle webhooks

Receive real-time notifications when payments complete.

Your first API call

bash
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:

bash
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 NumberBrandResult
4000 0000 0000 0002VisaSuccess
4000 0000 0000 1091VisaSuccess with 3DS
5200 0000 0000 0007MastercardSuccess
5200 0000 0000 1096MastercardSuccess with 3DS
4000 0000 0000 0069VisaDeclined (Expired)
4000 0000 0000 0119VisaDeclined (Insufficient Funds)
4000 0000 0000 0259Visa3DS 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:

json
{
  "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.

1

Add the script to your website

Drop this before the closing </body> tag:

html
<script src="https://payments.pebblepay.io/js/pebblepay.js" data-store="YOUR_STORE_ID"></script>
2

Add a pay button anywhere

Any element with data-pebblepay becomes a payment button:

html
<!-- 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 -->
3

Handle the result (optional)

Listen for payment events:

javascript
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

html
<!-- 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

jsx
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

Apple PayGoogle PayCard PaymentsMobile OptimizedFraud ProtectionWebhooksCustom Branding3D Secure

Perfect for social media bios, email invoices, WhatsApp payments, selling without a website, donations, tips, and freelance work.

Your Checkout URL

text
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

text
# 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:

text
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

Card PaymentsCard ValidationMobile OptimizedDark ThemeAuto Redirect30-min SessionsEvent MessagesFraud Protection

Embed URL

text
https://payments.pebblepay.io/checkout/embed?store_id=YOUR_STORE_ID

URL Parameters

store_idrequired
Your store ID (required)
amount
Payment amount (0.50 - 50,000). If omitted, customer enters amount.
currency
Currency code (default: USD).
success_url
Redirect URL after successful payment.
ref
Your order/invoice reference for tracking.

Basic Embed

html
<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:

html
<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

html
<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

html
<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.

bash
# 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

POST/api/v1/orders

Create a checkout session

Creates a new checkout session and returns a URL where your customer can complete payment. Sessions expire after 1 hour.

Parameters

amount
numberPayment amount in USD (0.50 - 50,000). Required unless variant_id is provided.
variant_id
stringLicense key variant ID. Price is pulled from dashboard (secure, cannot be overridden). See License Keys docs.
product_name
stringName of the product/service
order_reference
stringYour internal order ID
customer_email
stringCustomer email for receipts
customer_name
stringCustomer full name
coupon_code
stringCoupon code to auto-apply at checkout (e.g., "SUMMER25")
return_url
stringRedirect URL after successful payment (alias: success_url)
cancel_url
stringRedirect URL if payment cancelled
webhook_url
stringURL to receive webhook notification on payment completion
metadata
objectCustom key-value pairs (returned in webhooks)
bash
curl -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

GET/api/v1/orders

List all orders

Returns a paginated list of all your transactions. Use query parameters to filter and paginate.

Parameters

status
stringFilter by status: completed, pending, failed, refunded, refund_pending
order_reference
stringFilter by your order reference
order_id
stringFilter by PebblePay order ID
limit
integerResults per page (1-100, default: 50)
offset
integerResults to skip for pagination
bash
# 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

GET/api/v1/orders/:id

Get order details

Retrieves details of a specific order by transaction ID, order ID (PP-XXXX-XXXXXX), or checkout session ID.

bash
# 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

POST/api/v1/coupons

Create Coupon

Create a new coupon code for discounts. Coupons can be percentage-based or fixed amount.

Parameters

coderequired
stringUnique coupon code (auto-uppercased)
discount_typerequired
string"percentage" or "fixed"
discount_valuerequired
numberDiscount amount (1-100 for percentage, USD for fixed)
description
stringOptional description for internal reference
min_amount
numberMinimum order amount to use coupon (USD)
max_uses
integerTotal redemption limit (null = unlimited)
max_uses_per_customer
integerPer-customer limit (e.g., 1 = each customer can use once)
expires_at
stringISO 8601 expiration date
bash
curl -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"
  }'
GET/api/v1/coupons

List Coupons

Retrieve all coupons for your account with optional filtering.

Parameters

active
string"true" or "false" to filter by status
limit
integerMax results (default 50, max 100)
offset
integerPagination offset
bash
curl https://payments.pebblepay.io/api/v1/coupons?active=true \
  -H "Authorization: Bearer YOUR_API_KEY"
GET/api/v1/coupons/:id

Get Coupon

Retrieve a specific coupon by ID.

Parameters

idrequired
stringCoupon ID
bash
curl https://payments.pebblepay.io/api/v1/coupons/coup_a1b2c3d4 \
  -H "Authorization: Bearer YOUR_API_KEY"
PUT/api/v1/coupons/:id

Update Coupon

Update a coupon's settings. Note: code, discount_type, and discount_value cannot be changed after creation.

Parameters

description
stringUpdated description
min_amount
numberUpdated minimum amount
max_uses
integerUpdated usage limit (null = unlimited)
max_uses_per_customer
integerPer-customer limit (null = unlimited)
expires_at
stringUpdated expiration date
is_active
booleanEnable or disable the coupon
bash
curl -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
  }'
DELETE/api/v1/coupons/:id

Delete Coupon

Permanently delete a coupon. This action cannot be undone.

Parameters

idrequired
stringCoupon ID to delete
bash
curl -X DELETE https://payments.pebblepay.io/api/v1/coupons/coup_a1b2c3d4 \
  -H "Authorization: Bearer YOUR_API_KEY"

Refunds

Process refunds programmatically

POST/api/v1/orders/:id/refund

Refund an order

Refunds a completed order. The refund is processed immediately. Net amount is returned to your balance.

Parameters

reason
stringReason for the refund
bash
curl -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 successful
payment.refundedPayment was refunded
payment.disputedCustomer opened dispute
payment.failedPayment attempt failed

Payload Example

json
{
  "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 verification
X-Webhook-IdUnique transaction ID for deduplication
Content-Typeapplication/json

Verify Signatures

Verify the X-Webhook-Signature to ensure the webhook came from PebblePay.

javascript
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

StatusMeaning
200Request successful
201Resource created
400Bad request - check parameters
401Unauthorized - invalid API key
403Forbidden - account not approved
404Resource not found
500Internal server error
json
{
  "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.

View Security & PCI DSS DetailsTerms of ServiceAcceptable Use Policy

Ready to integrate?

Get your API key and start accepting payments in minutes.