Client Integration

Build apps and AI agents that can pay for HivePay checkout URLs automatically.


Overview

There are two ways to pay for HivePay x402-enabled checkout URLs:

  1. Automated — use HiveX402Client for server-side apps and AI agents that hold a private key
  2. Browser — use buildPaymentTransaction() + a wallet extension (Hive Keychain, HiveAuth) for browser-based apps

Automated Client (Server-side)

The HiveX402Client wraps the native fetch() API and transparently handles the 402 -> sign -> retry flow.

import { HiveX402Client } from '@hiveio/x402/client';

const client = new HiveX402Client({
  account: 'alice',
  activeKey: '5K...',   // Hive active private key (WIF format)
  maxPayment: 15.0      // Max HBD per request (default: 1.0)
});

// Pay for a HivePay checkout URL
const response = await client.fetch('https://hivepay.me/for/order-abc123');
const data = await response.json();

console.log(data.txId);      // On-chain transaction ID
console.log(data.payer);     // "alice"
console.log(data.sessionId); // HivePay session ID

Configuration

Option Type Default Description
account string Required Hive account name
activeKey string Required Active private key in WIF format
maxPayment number 1.0 Maximum HBD per single request

HivePay x402 Transaction Structure

Unlike standard x402 (single transfer), HivePay x402 requires two transfer operations in the signed transaction — one for the merchant's net amount and one for HivePay's fee.

The 402 response includes the breakdown in the extra field:

{
  "extra": {
    "sessionId": "cmj7b2rg10004d2rimvum8kaz",
    "feeAccount": "hivepay",
    "feeAmount": "0.158 HBD",
    "netAmount": "10.342 HBD"
  }
}

The signed transaction must contain:

Operation to amount memo
Transfer 1 Merchant account (payTo) netAmount pos-{sessionId}
Transfer 2 Fee account (extra.feeAccount) feeAmount Fee for {sessionId}

Browser Client

For browser-based apps, you cannot embed private keys. Instead, use the library's building blocks with an external wallet signer.

With Hive Keychain

import { parseRequirements } from '@hiveio/x402/client';

async function payForCheckout(checkoutUrl: string, account: string) {
  // Step 1: Request the checkout URL, get 402 requirements
  const initialResponse = await fetch(checkoutUrl);

  if (initialResponse.status !== 402)
    return initialResponse; // Not a 402 or already paid

  // Step 2: Parse payment requirements from the response
  const body = await initialResponse.json();
  const requirements = body.accepts[0];
  const { feeAccount, feeAmount, netAmount } = requirements.extra;

  // Step 3: Build the two-operation transaction using Hive Keychain
  const ops = [
    ['transfer', {
      from: account,
      to: requirements.payTo,
      amount: netAmount,
      memo: `pos-${requirements.extra.sessionId}`
    }],
    ['transfer', {
      from: account,
      to: feeAccount,
      amount: feeAmount,
      memo: `Fee for ${requirements.extra.sessionId}`
    }]
  ];

  // Step 4: Sign with Hive Keychain
  const signResult = await new Promise((resolve, reject) => {
    window.hive_keychain.requestBroadcast(
      account,
      ops,
      'Active',
      (response) => {
        if (response.success) resolve(response);
        else reject(new Error(response.message));
      }
    );
  });

  // Payment is broadcast — HivePay detects it via block scanning
  return signResult;
}

AI Agent Integration

x402 is designed for autonomous machine-to-machine payments. AI agents can use the automated client to complete HivePay payment sessions without human intervention.

import { HiveX402Client } from '@hiveio/x402/client';

// Create a client for your AI agent
const agent = new HiveX402Client({
  account: 'my-ai-agent',
  activeKey: process.env.HIVE_ACTIVE_KEY!,
  maxPayment: 50.0  // Budget limit per request
});

// Example: An AI agent that pays for premium API access
async function purchaseApiAccess(merchantApiUrl: string) {
  // Merchant creates a payment session
  const session = await fetch(`${merchantApiUrl}/create-payment`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ plan: 'premium', duration: '1month' })
  }).then(r => r.json());

  // Agent pays via x402 using the checkout URL
  const paymentResult = await agent.fetch(session.checkoutUrl);
  const confirmation = await paymentResult.json();

  console.log(`Paid ${confirmation.payer} -> tx: ${confirmation.txId}`);
  return confirmation;
}

Budget Control

Use maxPayment to limit how much an agent can spend per request. If a resource costs more than the limit, the client throws an error instead of paying.

const client = new HiveX402Client({
  account: 'my-agent',
  activeKey: '5K...',
  maxPayment: 1.0  // Only allow payments up to 1.000 HBD
});

// This will throw if the session charges more than 1.000 HBD
try {
  await client.fetch('https://hivepay.me/for/expensive-item-xyz');
} catch (error) {
  console.error('Payment exceeds budget:', error.message);
}

Programmatic Verify & Settle (SDK)

If you build your own x402 transaction signing and don't use HiveX402Client, you can call the HivePay verify and settle endpoints directly through the @hivepay/client SDK.

This is useful when you want full control over transaction construction, or when integrating x402 into an existing backend pipeline.

import { HivePay } from '@hivepay/client';

const hivepay = new HivePay({ apiKey: 'sk_live_xxx' });

// After constructing and signing the transaction yourself:
const payload = {
  x402Version: 1 as const,
  scheme: 'exact' as const,
  network: 'hive:mainnet',
  payload: {
    signedTransaction: mySignedTx,
    nonce: crypto.randomUUID()
  }
};

// Optional: verify first (does NOT broadcast)
const check = await hivepay.payments.x402Verify('session_id', payload);
if (!check.isValid) {
  throw new Error(check.invalidReason);
}

// Settle: verify + broadcast + mark session completed
const result = await hivepay.payments.x402Settle('session_id', payload);
if (result.success) {
  console.log(`Paid! TX: ${result.txId}, Payer: ${result.payer}`);
}
use HivePay\HivePay;

$hivepay = new HivePay(['apiKey' => 'sk_live_xxx']);

$payload = [
    'x402Version' => 1,
    'scheme' => 'exact',
    'network' => 'hive:mainnet',
    'payload' => [
        'signedTransaction' => $mySignedTx,
        'nonce' => bin2hex(random_bytes(16)),
    ],
];

// Optional: verify first (does NOT broadcast)
$check = $hivepay->payments->x402Verify('session_id', $payload);
if (!$check['isValid']) {
    throw new RuntimeException($check['invalidReason']);
}

// Settle: verify + broadcast + mark session completed
$result = $hivepay->payments->x402Settle('session_id', $payload);
if ($result['success']) {
    echo "Paid! TX: {$result['txId']}, Payer: {$result['payer']}";
}

Error Handling

Common errors when making x402 payments:

Error Cause Solution
Payment exceeds maxPayment Session amount exceeds budget Increase maxPayment or use a smaller payment
Nonce already spent Replay attack or duplicate request Retry with a fresh request
Signature does not match Wrong key or account Verify the activeKey matches the account
Transaction has expired Payment took too long Retry immediately — transactions expire after 5 minutes
Merchant has x402 disabled Merchant opted out of x402 Use the browser checkout flow instead
Session is expired Payment session timed out (30 min) Ask the merchant to create a new session
Session is in 'completed' status Session already paid No action needed — payment was already successful

External Resources