Merchant Configuration
Control x402 payment support for your HivePay merchant account.
Overview
x402 payments are enabled by default for all HivePay merchants. When enabled, x402-aware clients (AI agents, automated tools) can pay for your payment sessions directly through the checkout URL. When disabled, only browser-based checkout is available.
Toggle x402 Support
Via API
import { HivePay } from '@hivepay/client';
const hivepay = new HivePay({ apiKey: 'sk_live_xxx' });
// Disable x402 payments
await hivepay.merchants.update('your_merchant_id', {
x402Enabled: false
});
// Re-enable x402 payments
await hivepay.merchants.update('your_merchant_id', {
x402Enabled: true
});
use HivePay\HivePay;
$hivepay = new HivePay(['apiKey' => 'sk_live_xxx']);
// Disable x402 payments
$hivepay->merchants->update('your_merchant_id', [
'x402Enabled' => false,
]);
// Re-enable x402 payments
$hivepay->merchants->update('your_merchant_id', [
'x402Enabled' => true,
]);
# Disable x402 payments
curl -X POST https://hivepay.me/api/public/merchants/your_merchant_id \
-H "x-api-key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "x402Enabled": false }'
# Re-enable x402 payments
curl -X POST https://hivepay.me/api/public/merchants/your_merchant_id \
-H "x-api-key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "x402Enabled": true }'
Via Dashboard
Toggle the x402 Payments switch in your Dashboard Settings.
What Happens When Disabled
When x402 is disabled for your account:
- x402 clients receive a
403 Forbiddenerror when visiting your checkout URLs - Browser users still see the normal checkout page and can pay as usual
- Existing completed sessions are not affected
- You can re-enable x402 at any time
Client-Side Impact
If you disable x402 while automated clients are actively using your checkout URLs, their requests will start failing. Coordinate with your API consumers before disabling.
Fees
HivePay does not deduct anything from individual x402 payments. The full session amount is transferred to the merchant in a single Hive transfer. Merchants are billed for processed volume on a monthly cycle — see Billing.
The 402 response includes the session ID:
{
"extra": {
"sessionId": "cmj7b2rg10004d2rimvum8kaz"
}
}
The x402 client must sign a transaction with a single transfer_operation:
The transfer must be in the same currency as the payment session.
Security
HivePay performs several checks on every x402 payment:
- Session validation — the payment session must exist, be in
pendingstatus, and not expired - Merchant check — the merchant must have x402 enabled
- Transaction structure — exactly one transfer operation
- Recipient validation — the transfer goes to the merchant's Hive account
- Amount validation — the transfer meets or exceeds the session amount
- Currency validation — the transfer matches the session currency (HIVE or HBD)
- Nonce uniqueness — each payment nonce can only be used once (prevents replay attacks)
- Signature verification — the transaction signature is verified against the sender's on-chain active public keys
- Expiration check — the transaction must not be expired
API Endpoints
HivePay also exposes session-aware x402 endpoints for programmatic use:
Using the SDK
The @hivepay/client (TypeScript) and hivepay/client (PHP) SDKs provide built-in methods for the verify and settle endpoints:
import { HivePay } from '@hivepay/client';
const hivepay = new HivePay({ apiKey: 'sk_live_xxx' });
// Verify without broadcasting
const verify = await hivepay.payments.x402Verify('session_id', {
x402Version: 1,
scheme: 'exact',
network: 'hive:mainnet',
payload: { signedTransaction: tx, nonce: 'unique-nonce' }
});
if (verify.isValid) {
// Settle — broadcasts and completes the session
const settle = await hivepay.payments.x402Settle('session_id', {
x402Version: 1,
scheme: 'exact',
network: 'hive:mainnet',
payload: { signedTransaction: tx, nonce: 'unique-nonce' }
});
console.log(settle.txId, settle.payer);
}
use HivePay\HivePay;
$hivepay = new HivePay(['apiKey' => 'sk_live_xxx']);
$payload = [
'x402Version' => 1,
'scheme' => 'exact',
'network' => 'hive:mainnet',
'payload' => ['signedTransaction' => $tx, 'nonce' => 'unique-nonce'],
];
// Verify without broadcasting
$verify = $hivepay->payments->x402Verify('session_id', $payload);
if ($verify['isValid']) {
// Settle — broadcasts and completes the session
$settle = $hivepay->payments->x402Settle('session_id', $payload);
echo $settle['txId'] . ' ' . $settle['payer'];
}
# Verify
curl -X POST https://hivepay.me/api/public/x402/verify \
-H "Content-Type: application/json" \
-d '{
"sessionId": "cmj7b2rg10004d2rimvum8kaz",
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "hive:mainnet",
"payload": {
"signedTransaction": { ... },
"nonce": "a1b2c3d4e5f6..."
}
}
}'
# Settle
curl -X POST https://hivepay.me/api/public/x402/settle \
-H "Content-Type: application/json" \
-d '{
"sessionId": "cmj7b2rg10004d2rimvum8kaz",
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "hive:mainnet",
"payload": {
"signedTransaction": { ... },
"nonce": "a1b2c3d4e5f6..."
}
}
}'
Settle Response
{
"success": true,
"txId": "abc123def456...",
"payer": "alice"
}
Preferred Flow
For most use cases, the /for/[slug] middleware flow (described in the Quick Start) is simpler — the client just fetches the checkout URL and everything is handled automatically. The API endpoints and SDK methods above are for advanced integrations that need to separate verification from settlement.