Skip to main content

Make Payments with Web3.js

Make payments to Armory-protected APIs using Web3.js wallets. hooks are lifecycle callbacks. extensions are protocol fields on x402 payloads/challenges. They work together but are separate. When payment verification fails on retry (402), Armory surfaces server detail (for example insufficient_funds) in the thrown error.

Basic Payment

import { armoryPay } from '@armory-sh/client-web3';
import { Web3 } from 'web3';

const web3 = new Web3('https://...');
const account = web3.eth.accounts.wallet.add('0x...')[0];

const result = await armoryPay(
  { web3, account },
  'https://api.example.com/data',
  'base',
  'usdc'
);

console.log(result.data);

Armory object workflow

import { createArmory } from '@armory-sh/client-web3';
import { Web3 } from 'web3';

const web3 = new Web3('https://...');
const account = web3.eth.accounts.wallet.add('0x...')[0];

const armory = createArmory({
  wallet: { web3, account },
  chains: 'base',
  tokens: 'usdc',
  debug: true,
});

const premium = await armory.patch('https://api.example.com/premium', { tier: 'pro' });
const info = await armory.call('https://api.example.com/data');

console.log(premium.data, info.data);
The createArmory object exposes .get, .post, .put, .delete, .patch, .pay, and .call. When the API responds with a 402, it selects from accepts[]. Without hooks it uses the first compatible option; add @armory-sh/client-hooks to apply chain/token/cheapest preferences. Use .pay(url, { method: 'PATCH', body }) when you need to override the HTTP method and .call(url) for the default GET.

With Browser Wallet

const web3 = new Web3(window.ethereum);
const accounts = await web3.eth.requestAccounts();

const result = await armoryPay(
  { web3, account: accounts[0] },
  'https://api.example.com/data',
  'base',
  'usdc'
);