Skip to content

Quickstart (5 min)

This guide walks you from zero to a working payment in 5 minutes. You’ll generate a post-quantum key pair, create a bounded spend envelope, and execute a real payment.

Prerequisites

  • @pqsafe/agent-pay installed (installation guide)
  • A PQSafe account with at least one active rail configured
  • Node.js ≥ 18
  1. Generate a key pair

    ML-DSA-65 key generation is async and requires ~50ms on modern hardware.

    import { generateKeyPair } from '@pqsafe/agent-pay'
    const { publicKey, secretKey } = await generateKeyPair()
    // Store secretKey securely — treat it like a private key
    // publicKey is safe to log, share with your issuer, or embed in metadata
    console.log('Public key (hex):', publicKey.slice(0, 32) + '...')
  2. Create a spend envelope

    A spend envelope defines the cryptographic authorization bounds for a payment. The agent can only spend within these bounds.

    import { createSpendEnvelope } from '@pqsafe/agent-pay'
    const envelope = createSpendEnvelope({
    maxAmount: 50, // Maximum USD the agent may spend
    currency: 'USD',
    allowedRails: ['airwallex'],
    allowedRecipients: ['anthropic.com'],
    validUntil: new Date(Date.now() + 3_600_000), // Expires in 1 hour
    agentId: 'my-agent-v1',
    memo: 'Anthropic API credits top-up',
    })
  3. Sign the envelope

    Signing produces a 6,586-character ML-DSA-65 signature bound to the canonical JSON of the envelope.

    import { createSignedEnvelope } from '@pqsafe/agent-pay'
    const signed = createSignedEnvelope(envelope, secretKey)
    console.log('Signature length:', signed.signature.length) // 6586 hex chars
    console.log('Envelope ID:', signed.envelopeId)
  4. Execute the payment

    import { executeAgentPayment } from '@pqsafe/agent-pay'
    const result = await executeAgentPayment(signed, {
    recipient: 'anthropic.com/billing',
    amount: 25, // Must be ≤ envelope.maxAmount
    memo: 'API credits — monthly top-up',
    })
    console.log('Payment status:', result.status) // 'settled' | 'pending' | 'failed'
    console.log('Rail used:', result.rail) // 'airwallex'
    console.log('Transaction ID:', result.txId)
    console.log('Ledger entry:', result.ledgerHash)
  5. Verify in the ledger

    Every payment is appended to the immutable ledger automatically.

    import { submitToLedger, buildLedgerRecord } from '@pqsafe/agent-pay'
    const record = buildLedgerRecord(signed, result)
    const ledgerEntry = await submitToLedger(record)
    console.log('Ledger hash:', ledgerEntry.hash)
    console.log('Sequence:', ledgerEntry.sequence)

Complete example

import {
generateKeyPair,
createSpendEnvelope,
createSignedEnvelope,
executeAgentPayment,
buildLedgerRecord,
submitToLedger,
} from '@pqsafe/agent-pay'
async function quickstart() {
// 1. Key pair
const { publicKey, secretKey } = await generateKeyPair()
// 2. Envelope
const envelope = createSpendEnvelope({
maxAmount: 50,
currency: 'USD',
allowedRails: ['airwallex'],
allowedRecipients: ['anthropic.com'],
validUntil: new Date(Date.now() + 3_600_000),
agentId: 'quickstart-agent',
})
// 3. Sign
const signed = createSignedEnvelope(envelope, secretKey)
// 4. Execute
const result = await executeAgentPayment(signed, {
recipient: 'anthropic.com/billing',
amount: 25,
memo: 'Quickstart test payment',
})
// 5. Ledger
await submitToLedger(buildLedgerRecord(signed, result))
return result
}
quickstart().then(r => console.log('Done:', r.status))

Expected output

Public key (hex): a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4...
Signature length: 6586
Envelope ID: env_01J3X...
Payment status: settled
Rail used: airwallex
Transaction ID: txn_airwallex_...
Ledger entry: 0xabc123...
Done: settled

Next steps