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

```typescript
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 |

!!!warning Protect Your Private Key
The `activeKey` has full transfer authority over your account. Only use this in secure server-side environments. Never expose it in client-side JavaScript.
!!!

---

## HivePay x402 Transaction Structure

The signed transaction must contain **exactly one `transfer_operation`** — the full session amount to the merchant. HivePay does not deduct anything from individual transactions; merchants are billed monthly for processed volume (see [Billing](/payments/fees/)).

The `402` response includes the session ID in the `extra` field:

```json
{
  "extra": {
    "sessionId": "cmj7b2rg10004d2rimvum8kaz"
  }
}
```

The transfer must match:

| Field | Value |
|-------|-------|
| `from` | Payer account |
| `to` | Merchant account (`payTo` in the requirements) |
| `amount` | `maxAmountRequired` (full session amount) |
| `memo` | `pos-{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

```typescript
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 { sessionId } = requirements.extra;

  // Step 3: Build the single-operation transaction
  const ops = [
    ['transfer', {
      from: account,
      to: requirements.payTo,
      amount: requirements.maxAmountRequired, // full session amount goes to the merchant
      memo: `pos-${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;
}
```

!!!success Note
When using Hive Keychain, the transaction is broadcast directly by the wallet extension. HivePay's block scanner will detect the transfer and mark the session as completed, just like a normal Hive checkout payment.
!!!

---

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

```typescript
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.

```typescript
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.

+++ TypeScript
```typescript
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}`);
}
```
+++ PHP
```php
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

- [x402 Protocol Specification](https://github.com/coinbase/x402) — the open standard by Coinbase
- [@hiveio/x402 on npm](https://www.npmjs.com/package/@hiveio/x402) — the Hive implementation by Ecency
- [hive-x402 on GitHub](https://github.com/ecency/hive-x402) — source code and documentation
- [Hive CAIP-2 Namespace](https://github.com/ChainAgnostic/namespaces/pull/174) — Hive's registration in the cross-chain standard
