Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.monkepay.xyz/llms.txt

Use this file to discover all available pages before exploring further.

Basic usage

const monkePay = MonkePayHono({
  apiKeyId: process.env.MONKEPAY_API_KEY_ID!,
  apiKeySecret: process.env.MONKEPAY_API_KEY_SECRET!,
  price: '0.001',
  onPayment: async (payment) => {
    console.log(`Payment received from ${payment.agentAddress}`)
    console.log(`Amount: ${payment.amountUSDC} USDC`)
    console.log(`Tx: ${payment.txHash}`)
    console.log(`Endpoint: ${payment.endpoint}`)
  },
})

PaymentEvent

interface PaymentEvent {
  agentAddress: string  // agent's wallet address e.g. '0xabc...123'
  amountUSDC: string    // amount paid e.g. '0.001'
  txHash: string        // on-chain transaction hash
  timestamp: Date       // when the payment was processed
  endpoint: string      // request path e.g. '/api/data'
}

Error handling

onPayment errors are caught silently — they never interrupt the response or surface to the agent. If your callback throws, the agent still receives their 200 OK. If onPayment is failing, use onError to catch those failures:
const monkePay = MonkePayHono({
  apiKeyId: process.env.MONKEPAY_API_KEY_ID!,
  apiKeySecret: process.env.MONKEPAY_API_KEY_SECRET!,
  price: '0.001',
  onPayment: async (payment) => {
    await db.insert('payments', payment) // if this throws...
  },
  onError: async (error) => {
    if (error.code === 'ON_PAYMENT_CALLBACK_FAILED') {
      // ...it's caught here
      await alerts.notify(`onPayment failed: ${error.message}`)
    }
  },
})

Common use cases

Usage tracking

onPayment: async (payment) => {
  await db.insert('usage_events', {
    agentAddress: payment.agentAddress,
    endpoint: payment.endpoint,
    amountUSDC: payment.amountUSDC,
    txHash: payment.txHash,
    createdAt: payment.timestamp,
  })
},

Webhook forwarding

onPayment: async (payment) => {
  await fetch('https://your-webhook-endpoint.com/payments', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payment),
  })
},

Rate limiting or access control

onPayment: async (payment) => {
  // Track spend per agent for analytics
  await redis.hincrby(
    `agent:${payment.agentAddress}:spend`,
    payment.endpoint,
    parseFloat(payment.amountUSDC) * 1_000_000, // store as integer
  )
},

Logging

onPayment: async (payment) => {
  logger.info('payment_received', {
    agent: payment.agentAddress.slice(0, 10) + '...',
    amount: payment.amountUSDC,
    endpoint: payment.endpoint,
    tx: payment.txHash,
  })
},

Timing

onPayment fires after settlement is confirmed and the response header is injected, but before the response is sent to the agent. It runs asynchronously inline — if your callback is slow, it adds latency to the response. For high-throughput endpoints, avoid slow synchronous operations in onPayment. Use a queue or fire-and-forget pattern for anything latency-sensitive:
onPayment: async (payment) => {
  // Fire and forget — don't await
  void queue.push('payment_received', payment)
},