Auto-provision a virtual Visa card to complete an online purchase. Use when user asks to buy something and needs payment, or explicitly mentions cypher-pay/agent-pay. Handles onboarding (email OTP + KYC — once ever), token generation (once per device), funding, card creation, 3DS, and card lifecycle.
90
90%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Risky
Do not use without reviewing
Zero-dependency TypeScript client for the CypherHQ Agent-Pay virtual card API. Build AI agents that issue programmable Visa cards, fund them with fiat, and make real purchases — with spend limits, 3DS handling, and card lifecycle management.
LLM agents need a way to pay for things without a human swiping a card. @cypherhq/agent-pay gives your agent a programmatic interface to:
Framework-agnostic. Zero npm dependencies — uses only Node.js built-ins (fetch, node:crypto).
npm install @cypherhq/agent-pay
# or: yarn add | pnpm add | bun addRequires Node.js ≥ 22.13.
import { createClient } from '@cypherhq/agent-pay';
const ap = createClient({ token: process.env.AGENT_PAY_TOKEN });
// 1. Check balance
const cents = await ap.getBalanceCents();
console.log(`Available: $${(cents / 100).toFixed(2)}`);
// 2. Create a card with a $50 per-transaction cap
const { cardId } = await ap.createCardAndResolve({
tag: `order-${Date.now()}`,
purpose: 'Buy headphones',
maxPerTransactionAmount: 50,
});
try {
// 3. Reveal card details for checkout — NEVER log these
const { pan, cvv, expiry } = await ap.revealCard(cardId);
// ... pass pan/cvv/expiry to merchant checkout ...
// 4. Auto-approve any 3DS challenge
await ap.pollAndApprove3ds(cardId);
} finally {
// 5. Always cancel after use, even on failure
await ap.cancelCard(cardId);
}Bot tokens are provisioned via agentpay.cypherhq.io. Pass via env or config:
// Option A: environment
// AGENT_PAY_TOKEN=agt_...
const ap = createClient();
// Option B: explicit
const ap = createClient({ token: 'agt_...' });For first-time onboarding (OTP → bot token), see SKILL.md.
| Option | Env var | Default | Notes |
|---|---|---|---|
token | AGENT_PAY_TOKEN | — | Required. Must start with agt_. |
baseUrl | AGENT_PAY_BASE_URL | https://arch.cypherd.io/v1 | Override for self-hosted or staging. |
const ap = createClient(config);
// Balance + funding
ap.getBalanceCents()
ap.getFundingUrl(usdAmount)
// Cards
ap.createCardAndResolve({ tag, purpose, maxPerTransactionAmount, dailyLimitUsd, monthlyLimitUsd })
ap.revealCard(cardId) // SECRET — never log
ap.cancelCard(cardId, reason?)
ap.freezeCard(cardId) // reusable-card mode only
ap.listAllCards()
ap.listCardsByTag(tag)
// 3DS
ap.pollAndApprove3ds(cardId, { timeoutMs?, intervalMs? })
// Limits + rules
ap.patchRules({ maxCards, dailyLimit, monthlyLimit, maxTransactionAmount })
// Transactions + analytics
ap.getCardTransactions(cardId, opts?)
ap.getAllTransactions(opts?)
ap.getSpendStats({ startDate, endDate })Full surface and JSDoc available via TypeScript autocomplete. Integration walkthrough in SKILL.md.
Two error types, both with a type discriminant:
import { AgentPayAuthError, AgentPayApiError } from '@cypherhq/agent-pay';
try {
await ap.getBalanceCents();
} catch (err) {
if (err instanceof AgentPayAuthError) {
// 401 — token invalid or expired
} else if (err instanceof AgentPayApiError) {
console.error(`API ${err.status} on ${err.path}: ${err.body}`);
}
}revealCard().try/finally. Use freezeCard only in reusable-card mode.agt_ — anything else is rejected immediately.To report a security issue, see SECURITY.md.
MIT © CypherHQ