Node.js SDK

Beta

The Orvion Node.js SDK provides seamless integration with Express for creating payment-protected API endpoints using the x402 protocol.

Installation

npm install @orvion/sdk

Quick Start

import express from 'express'
import { orvionInit, requirePayment } from '@orvion/sdk/express'

const app = express()

// Initialize Orvion
orvionInit({
  apiKey: process.env.ORVION_API_KEY!,
})

// Protect an endpoint
app.get('/api/premium',
  requirePayment({ amount: '0.10', currency: 'USDC' }),
  (req, res) => {
    res.json({ message: 'Premium content!', paid: req.payment.amount })
  }
)

app.listen(3000)

orvionInit

Initialize the Orvion SDK with your API key and configuration.

Configuration

FieldTypeRequiredDescriptionExample
apiKeystringOptionalYour Orvion API key (required)
baseUrlstring?OptionalCustom API base URL (default: https://api.orvion.sh)
cacheTtlSecondsnumberOptionalRoute cache TTL in seconds (default: 60)
transactionHeaderstringOptionalHeader for transaction ID (default: 'X-Transaction-Id')
customerHeaderstringOptionalHeader for customer ID (default: 'X-Customer-Id')

Example

orvionInit({
  apiKey: process.env.ORVION_API_KEY!,
  cacheTtlSeconds: 120,  // Cache routes for 2 minutes
  transactionHeader: 'X-Payment-Id',  // Custom header name
})

requirePayment Middleware

Protect Express routes with payment requirements.

Parameters

FieldTypeRequiredDescriptionExample
amountstring?OptionalPrice per request (e.g., '0.10')
currencystringOptionalCurrency code (default: 'USD')
allowAnonymousboolean?OptionalAllow requests without customer ID (default: true)
customerResolverFunction?OptionalFunction to extract customer ID from request
hostedCheckoutbooleanOptionalRedirect to pay.orvion.sh instead of 402 (default: false)
returnUrlstring?OptionalReturn URL after hosted checkout payment

Examples

// Basic usage
app.get('/api/basic',
  requirePayment({ amount: '0.01', currency: 'USDC' }),
  (req, res) => {
    res.json({ data: '...' })
  }
)

// With metadata
app.get('/api/premium',
  requirePayment({
    amount: '1.00',
    currency: 'USDC',
  }),
  (req, res) => {
    res.json({ data: '...', paid: req.payment.amount })
  }
)

// Hosted checkout mode
app.get('/premium',
  requirePayment({
    amount: '1.00',
    currency: 'USDC',
    hostedCheckout: true,
  }),
  (req, res) => {
    res.json({ message: 'Premium content!' })
  }
)

Pre-built Payment Router (NEW in v0.2)

The SDK provides a pre-built router that adds all payment endpoints automatically - no boilerplate needed!

Usage

import { OrvionClient } from '@orvion/sdk'
import { createPaymentRouter } from '@orvion/sdk/express'

const client = new OrvionClient({ apiKey: process.env.ORVION_API_KEY! })

// Add all payment endpoints with one line!
app.use('/api/payments', createPaymentRouter(client))

This adds the following endpoints:

| Endpoint | Method | Description | |----------|--------|-------------| | /api/payments/confirm | POST | Confirm wallet payment with tx_hash | | /api/payments/cancel/:id | POST | Cancel a pending charge | | /api/payments/state/:id | GET | Get charge state for payment widgets | | /api/payments/charge/:id | GET | Get full charge details |

Available Routers

import {
  createPaymentRouter,   // Payment operations
  createHealthRouter,    // Health check endpoint
  createFullRouter,      // All endpoints combined
} from '@orvion/sdk/express'

// Payment router only
app.use('/api/payments', createPaymentRouter(client))

// Health router only
app.use('/api', createHealthRouter(client))

// Combined router (payments + health)
app.use('/api/orvion', createFullRouter(client))

OrvionClient

The client provides direct API access for all payment operations.

New Methods (v0.2)

import { OrvionClient } from '@orvion/sdk'

const client = new OrvionClient({ apiKey: 'your-api-key' })

// Health check & API key validation
const health = await client.healthCheck()
console.log(`Organization: ${health.organizationId}`)
console.log(`API Key Valid: ${health.apiKeyValid}`)

// Create a charge
const charge = await client.createCharge({
  amount: '0.10',
  currency: 'USDC',
  description: 'API access',
})

// Get charge details
const chargeDetails = await client.getCharge(charge.id)

// Get charge state (optimized for UI widgets)
const state = await client.getChargeState(charge.id)
console.log(`Status: ${state.status}`)
console.log(`Recipient: ${state.recipientAddress}`)

// Confirm wallet payment
const result = await client.confirmPayment({
  transactionId: charge.id,
  txHash: 'blockchain_tx_signature...',
})
console.log(`Success: ${result.success}`)

// Cancel a pending charge
const cancelled = await client.cancelCharge(charge.id)

// Verify a payment
const verification = await client.verifyCharge({
  transactionId: charge.id,
  resourceRef: 'my-resource',
})

All Client Methods

| Method | Description | |--------|-------------| | createCharge() | Create a new payment charge | | verifyCharge() | Verify a payment transaction | | getCharge() | Get charge details by ID | | getChargeState() | Get UI-optimized charge state | | confirmPayment() | Confirm wallet payment with tx_hash | | cancelCharge() | Cancel a pending charge | | healthCheck() | Validate API key & get org info | | getRoutes() | Get protected route configurations | | matchRoute() | Match a request to a protected route |


TypeScript Types

Core Types

import type {
  Charge,           // Payment charge
  VerifyResult,     // Payment verification result
  PaymentInfo,      // Payment info attached to request
  RouteConfig,      // Protected route configuration
} from '@orvion/sdk'

New Types (v0.2)

import type {
  ConfirmResult,      // Result of wallet payment confirmation
  ChargeState,        // UI state for payment widgets
  HealthInfo,         // API health & organization info
  WalletPaymentInfo,  // Wallet payment details
  PaymentMethodInfo,  // Available payment methods
} from '@orvion/sdk'

Helper Functions

import {
  extractWalletPaymentInfo,  // Parse wallet info from x402_requirements
  extractPaymentMethods,     // Get available payment methods
} from '@orvion/sdk'

// Parse payment methods from x402_requirements
const charge = await client.createCharge({ amount: '0.10', currency: 'USDC' })
const methods = extractPaymentMethods(charge.x402Requirements)

console.log(`Available methods: ${methods.methods}`)  // ["solana"]
if (methods.solana) {
  console.log(`Recipient: ${methods.solana.recipientAddress}`)
  console.log(`Token: ${methods.solana.tokenAddress}`)
}

Accessing Payment Info

After successful payment verification, payment details are available on req.payment:

app.get('/api/premium',
  requirePayment({ amount: '0.10', currency: 'USDC' }),
  (req, res) => {
    const { payment } = req
    
    res.json({
      transactionId: payment.transactionId,
      amount: payment.amount,
      currency: payment.currency,
      customerRef: payment.customerRef,
    })
  }
)

PaymentInfo Type

interface PaymentInfo {
  transactionId: string
  amount: string
  currency: string
  customerRef?: string
  resourceRef?: string
  routeId?: string
  verifiedAt?: string
}

Complete Example (Minimal)

This example shows how thin your app can be with the SDK:

import express from 'express'
import { OrvionClient } from '@orvion/sdk'
import {
  orvionInit,
  requirePayment,
  createPaymentRouter,
} from '@orvion/sdk/express'

const app = express()
app.use(express.json())

const client = new OrvionClient({ apiKey: process.env.ORVION_API_KEY! })

// Initialize Orvion
orvionInit({ apiKey: process.env.ORVION_API_KEY! })

// Add pre-built payment router (confirm, cancel, state, charge endpoints)
app.use('/api/payments', createPaymentRouter(client))

// Protected endpoint - that's it!
app.get('/api/premium',
  requirePayment({ amount: '0.01', currency: 'USDC' }),
  (req, res) => {
    res.json({ access: 'granted', message: 'Welcome to premium!' })
  }
)

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000')
})

Error Handling

import { OrvionClient, OrvionAPIError, OrvionAuthError } from '@orvion/sdk'

try {
  const client = new OrvionClient({ apiKey: 'your-api-key' })
  const charge = await client.createCharge({ amount: '0.10', currency: 'USDC' })
} catch (error) {
  if (error instanceof OrvionAuthError) {
    console.error('Invalid API key')
  } else if (error instanceof OrvionAPIError) {
    console.error(`API Error: ${error.statusCode} - ${error.message}`)
  } else {
    console.error('Unexpected error:', error)
  }
}

Request Type Extensions

The SDK extends the Express Request type to include payment info:

declare global {
  namespace Express {
    interface Request {
      payment?: PaymentInfo
      orvionClient?: OrvionClient
    }
  }
}

For TypeScript users, the types are automatically available after importing from @orvion/sdk/express.


Related Documentation