Creating Payments
Learn how to create payment sessions and redirect customers to checkout.
Basic Payment
Create a simple payment with amount, currency, and description:
import { HivePay } from '@hivepay/client';
const hivepay = new HivePay({ apiKey: 'sk_live_xxx' });
const payment = await hivepay.payments.create({
amount: '10500', // 10.500 (in satoshis/smallest unit)
currency: 'HBD', // 'HIVE' or 'HBD'
description: 'Order #123' // Shown to customer
});
console.log(payment.id); // Payment ID
console.log(payment.checkoutUrl); // Hosted checkout page URL
console.log(payment.status); // 'pending'
curl -X POST https://hivepay.me/api/public/payments \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": "10500",
"currency": "HBD",
"description": "Order #123"
}'
From a Product Price
Instead of an inline amount, charge a reusable catalog price by passing priceId (with an optional quantity), or lineItems for a multi-item cart. All line items must share the same currency.
// Single price
const payment = await hivepay.payments.create({ priceId: 'price_xxx', quantity: 2 });
// Multiple line items
const cart = await hivepay.payments.create({
lineItems: [
{ priceId: 'price_plan' },
{ priceId: 'price_addon', quantity: 3 }
]
});
$payment = $hivepay->payments->create(['priceId' => 'price_xxx', 'quantity' => 2]);
The session snapshots the total amount, currency, and description, so it stays valid even if the product or price is later edited or archived.
Amount Format
Amounts are specified as strings in the smallest unit (satoshis):
Both HIVE and HBD use 3 decimal precision.
Payment Options
Redirect URLs
Specify where to redirect customers after payment:
const payment = await hivepay.payments.create({
amount: '10500',
currency: 'HBD',
description: 'Order #123',
redirectUrl: 'https://yourstore.com/order/123/success',
cancelUrl: 'https://yourstore.com/order/123/cancelled'
});
curl -X POST https://hivepay.me/api/public/payments \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": "10500",
"currency": "HBD",
"description": "Order #123",
"redirectUrl": "https://yourstore.com/order/123/success",
"cancelUrl": "https://yourstore.com/order/123/cancelled"
}'
Pre-fill the payer's Hive account
If you already know which Hive account your customer will pay from, pass senderHiveAccount to pre-fill the payment form. The customer still reviews and confirms the account before signing — this step is never skipped. A leading @ is stripped and the account name is validated.
const payment = await hivepay.payments.create({
amount: '10500',
currency: 'HBD',
description: 'Order #123',
senderHiveAccount: 'alice'
});
curl -X POST https://hivepay.me/api/public/payments \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": "10500",
"currency": "HBD",
"description": "Order #123",
"senderHiveAccount": "alice"
}'
On the checkout page the customer sees who they are paying (recipientHiveAccount, the merchant's payout account) as fine print beneath the account field.
Custom Metadata
Attach custom data to a payment for your reference:
const payment = await hivepay.payments.create({
amount: '10500',
currency: 'HBD',
description: 'Order #123',
metadata: {
orderId: '12345',
customerId: 'cust_abc',
items: ['item1', 'item2']
}
});
// Metadata is returned with the payment
console.log(payment.metadata.orderId); // '12345'
Payment Response
A successful payment creation returns:
{
"id": "cmj7b2rg10004d2rimvum8kaz",
"slug": "order-12345-a1b2c3d4",
"redirectUrl": "https://hivepay.me/for/order-12345-a1b2c3d4"
}
Redirecting to Checkout
After creating a payment, redirect the customer to the checkout URL:
// Create payment on your server, then redirect
window.location.href = payment.checkoutUrl;
const handleCheckout = async () => {
const payment = await createPayment(); // Your server call
window.location.href = payment.checkoutUrl;
};
<button onClick={handleCheckout}>Pay with Hive</button>
<a href="https://hivepay.me/for/{paymentId}">Complete Payment</a>
After Payment
When the payment is completed or cancelled:
- Customer is redirected to your
redirectUrlorcancelUrl - A webhook is sent to your configured endpoint
- You can check the status using the payment ID
Best Practice
Always verify payment status via webhook or API before fulfilling orders. Don't rely solely on the redirect.
AML Limits
AML limits apply to the customer's Hive account, not to your merchant account — creating payments is never blocked by AML.
After the customer enters their Hive account and picks a payment method, HivePay checks the account's single payment and cumulative volume against the thresholds. If a limit is exceeded, the customer does not receive the transfer memo, so no funds are moved. They are asked to contact [email protected] to complete KYC verification.
For you, the payment ends in the failed status with failureReason: "aml_limit", and you receive the regular failed webhook. The payment's activity history shows an "AML Limit Reached" entry.
Error Handling
import { isHivePayError } from '@hivepay/client';
try {
const payment = await hivepay.payments.create({
amount: '10500',
currency: 'HBD',
description: 'Order #123'
});
} catch (error) {
if (isHivePayError(error)) {
if (error.isForbidden()) {
// Merchant account is inactive
console.error('Forbidden:', error.message);
} else if (error.isValidation()) {
console.error('Invalid payment data:', error.message);
} else if (error.isAuthError()) {
console.error('Invalid API key');
} else {
console.error('Payment creation failed:', error.message);
}
}
}