hyperswitch-prism

May 11, 2026 ยท View on GitHub

Hyperswitch Prism โ€” Node.js SDK

A high-performance, type-safe Node.js SDK for payment processing through Hyperswitch Prism. Connect to 100+ payment processors through a single, unified API.

npm version License: MIT


Table of Contents


๐Ÿค– For AI Assistants

Use curl to fetch the SDK reference:

curl -fsSL https://raw.githubusercontent.com/juspay/hyperswitch-prism/main/llm/llm.txt

This file contains complete SDK documentation including installation, payment operations, error handling, connector configuration, field probe data, and examples for all 100+ connectors.

AI Assistant Context

This SDK is part of Hyperswitch Prism โ€” a unified connector library for payment processors.

What This SDK Does

  1. Request Transformation: Converts unified payment requests to connector-specific formats
  2. Response Normalization: Transforms connector responses back to a unified schema
  3. Error Handling: Provides consistent error types (IntegrationError, ConnectorError, NetworkError) regardless of connector

Architecture

Your Node.js App
       โ”‚
       โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Service Clients (PaymentClient, CustomerClient, etc.)       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
                            โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ConnectorClient (undici connection pool + HTTP execution)   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
                            โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  koffi FFI Bindings (connector-service-ffi.node)             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
                            โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Rust Core (connector transformation logic)                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
                            โ–ผ
              Payment Processor APIs

Key Files

FilePurpose
src/index.tsPublic API exports (clients, types, errors)
src/connector-client.tsHTTP execution layer with undici
src/ffi/connector-service-ffi.tskoffi FFI bindings
src/proto/payment_pb.tsProtobuf message definitions

Package & Import

  • Package Name: hyperswitch-prism
  • Installation: npm install hyperswitch-prism
  • Import: import { PaymentClient, types } from 'hyperswitch-prism'

Installation

npm install hyperswitch-prism

Requirements:

  • Node.js 18+ (LTS recommended)
  • macOS (x64, arm64), Linux (x64, arm64), or Windows (x64)

Quick Start

import { PaymentClient, types } from 'hyperswitch-prism';

const config: types.ConnectorConfig = {
  connectorConfig: {
    // Configure your connector credentials here
    // See connector documentation for specific auth patterns
  }
};

const client = new PaymentClient(config);

const response = await client.authorize({
  merchantTransactionId: 'txn_001',
  amount: { minorAmount: 1000, currency: types.Currency.USD },
  captureMethod: types.CaptureMethod.AUTOMATIC,
  paymentMethod: {
    card: {
      cardNumber: { value: '4111111111111111' },
      cardExpMonth: { value: '12' },
      cardExpYear: { value: '2027' },
      cardCvc: { value: '123' },
      cardHolderName: { value: 'John Doe' },
    }
  },
  address: { billingAddress: {} },
  authType: types.AuthenticationType.NO_THREE_DS,
  returnUrl: 'https://example.com/return',
  orderDetails: [],
  testMode: true,
});

console.log('Status:', response.status);
console.log('Transaction ID:', response.connectorTransactionId);

Connector Authentication

Each connector uses a different authentication scheme. All configs are set inside connectorConfig as a single key matching the connector name.

See the SDK reference for complete connector authentication patterns:

curl -fsSL https://raw.githubusercontent.com/juspay/hyperswitch-prism/main/llm/llm.txt

Common authentication patterns include:

// Single API Key
{ connectorConfig: { [connectorName]: { apiKey: { value: '...' } } } }

// API Key + Merchant Account
{ connectorConfig: { [connectorName]: { apiKey: { value: '...' }, merchantAccount: { value: '...' } } } }

// Client ID + Secret (OAuth-style)
{ connectorConfig: { [connectorName]: { clientId: { value: '...' }, clientSecret: { value: '...' } } } }

// Username + Password
{ connectorConfig: { [connectorName]: { username: { value: '...' }, password: { value: '...' } } } }

All Service Clients

import {
  PaymentClient,
  CustomerClient,
  PaymentMethodClient,
  MerchantAuthenticationClient,
  PaymentMethodAuthenticationClient,
  RecurringPaymentClient,
  RefundClient,
  DisputeClient,
  PayoutClient,
  EventClient,
  GrpcPaymentClient,
  GrpcCustomerClient,
  types,
  IntegrationError,
  ConnectorError,
  NetworkError,
} from 'hyperswitch-prism';
ClientMethods
PaymentClientauthorize(), capture(), refund(), void(), createOrder(), get(), sync(), incrementalAuthorization()
RefundClientget(), createRefund(), updateRefund()
CustomerClientcreate()
PaymentMethodClienttokenize()
MerchantAuthenticationClientcreateServerAuthenticationToken(), createClientAuthenticationToken(), createServerSessionAuthenticationToken()
PaymentMethodAuthenticationClientpreAuthenticate(), authenticate(), postAuthenticate()
RecurringPaymentClientsetup(), charge(), revoke()
DisputeClientaccept(), defend(), submitEvidence(), get()
PayoutClientPayout operations
EventClienthandleEvent() (webhook processing)

Payment Flows

Authorize with Auto Capture

const client = new PaymentClient(config);

const response = await client.authorize({
  merchantTransactionId: 'txn_001',
  amount: { minorAmount: 1000, currency: types.Currency.USD },
  captureMethod: types.CaptureMethod.AUTOMATIC,
  paymentMethod: {
    card: {
      cardNumber: { value: '4111111111111111' },
      cardExpMonth: { value: '12' },
      cardExpYear: { value: '2027' },
      cardCvc: { value: '123' },
      cardHolderName: { value: 'John Doe' },
    }
  },
  address: { billingAddress: {} },
  authType: types.AuthenticationType.NO_THREE_DS,
  returnUrl: 'https://example.com/return',
  orderDetails: [],
  testMode: true,
});
// response.status === 8 (CHARGED) on success

Authorize + Manual Capture

// Step 1: Authorize only
const authResponse = await client.authorize({
  // ...
  captureMethod: types.CaptureMethod.MANUAL,
});
// authResponse.status === 6 (AUTHORIZED)

// Step 2: Capture later
const captureResponse = await client.capture({
  merchantCaptureId: 'cap_001',
  connectorTransactionId: authResponse.connectorTransactionId!,
  amountToCapture: { minorAmount: 1000, currency: types.Currency.USD },
  testMode: true,
});
// captureResponse.status === 8 (CHARGED) or 20 (PENDING) โ€” both are success

Refund

const refundResponse = await client.refund({
  merchantRefundId: 'ref_001',
  connectorTransactionId: authResponse.connectorTransactionId!,
  refundAmount: { minorAmount: 500, currency: types.Currency.USD },
  paymentAmount: 1000,
  reason: 'RETURN',
  testMode: true,
});
// refundResponse.status === 4 (REFUND_SUCCESS) or 3 (REFUND_PENDING) โ€” both are success

Void (Cancel Authorization)

const voidResponse = await client.void({
  merchantVoidId: 'void_001',
  connectorTransactionId: authResponse.connectorTransactionId!,
  cancellationReason: 'Customer cancelled',
  testMode: true,
});
// voidResponse.status === 11 (VOIDED)

Status Codes Reference

PaymentStatus

The response.status field is always a number, not a string:

// โŒ Always false โ€” response.status is a number
if (response.status === 'CHARGED') { ... }

// โœ… Correct โ€” compare against the numeric enum constant
if (response.status === types.PaymentStatus.CHARGED) { ... }

Important: a FAILURE status is returned in the response body โ€” it does NOT throw an exception. Always check response.status explicitly.

PaymentStatus and RefundStatus are two separate enums with overlapping integer values. Use types.PaymentStatus for authorize/capture/void responses and types.RefundStatus for refund responses.

NameValueMeaning
PAYMENT_STATUS_UNSPECIFIED0Unknown
STARTED1Payment initiated
AUTHENTICATION_PENDING4Awaiting 3DS redirect
AUTHENTICATION_SUCCESSFUL53DS passed
AUTHENTICATION_FAILED23DS failed
AUTHORIZED6Auth succeeded, not yet captured
AUTHORIZATION_FAILED7Auth declined
CHARGED8Captured / auto-captured successfully
PARTIAL_CHARGED17Partially captured
CAPTURE_INITIATED13Async capture in progress
CAPTURE_FAILED14Capture failed
VOIDED11Authorization voided/cancelled
VOID_INITIATED12Async void in progress
VOID_FAILED15Void failed
PENDING20Processing / async
FAILURE21Soft decline โ€” check response.error
ROUTER_DECLINED3Declined by routing layer
EXPIRED26Payment expired
PARTIALLY_AUTHORIZED25Partial authorization
UNRESOLVED19Requires manual review

Checking status safely:

const response = await client.authorize(request);

if (response.status === types.PaymentStatus.FAILURE) {
  console.error('Declined:', response.error?.message, response.error?.code);
} else if (response.status === types.PaymentStatus.CHARGED ||
           response.status === types.PaymentStatus.AUTHORIZED) {
  console.log('Success:', response.connectorTransactionId);
} else if (response.status === types.PaymentStatus.AUTHENTICATION_PENDING) {
  console.log('Redirect to:', response.redirectionData);
}

RefundStatus

NameValueMeaning
REFUND_STATUS_UNSPECIFIED0Unknown
REFUND_FAILURE1Refund failed
REFUND_MANUAL_REVIEW2Pending manual review
REFUND_PENDING3Processing
REFUND_SUCCESS4Completed
REFUND_TRANSACTION_FAILURE5Transaction-level failure

REFUND_PENDING is a normal success state for many connectors. Treat both REFUND_PENDING and REFUND_SUCCESS as successful outcomes.


Error Handling

The SDK raises exceptions only for hard failures (network errors, invalid configuration, serialization errors). Soft payment declines come back as an in-band status: FAILURE in the response body.

import { IntegrationError, ConnectorError, NetworkError, types } from 'hyperswitch-prism';

try {
  const response = await client.authorize(request);

  if (response.status === types.PaymentStatus.FAILURE) {
    console.error('Payment declined:', response.error?.message);
    return;
  }

} catch (error) {
  if (error instanceof IntegrationError) {
    // Request-phase error: bad config, missing required field, serialization failure
    console.error('Integration error:', error.errorCode, error.message);

  } else if (error instanceof ConnectorError) {
    // Response-phase error: connector returned unexpected format, transform failed
    console.error('Connector error:', error.errorCode, error.message);

  } else if (error instanceof NetworkError) {
    // Network-level: timeout, connection refused, DNS failure
    console.error('Network error:', error.message);
  }
}

response.error is a Protobuf Object โ€” Not JSON-Serializable

// โŒ Throws or produces empty object
res.json({ error: response.error });
JSON.stringify(response.error);

// โœ… Extract the primitive fields you need
res.json({
  error: {
    message: response.error?.message,
    code: response.error?.code,
    reason: response.error?.reason,
  }
});

Common Error Codes

CodeTypeCauseFix
MISSING_REQUIRED_FIELD: browser_infoIntegrationErrorConnector requires browserInfoAdd browserInfo to request
INVALID_CONFIGURATIONIntegrationErrorWrong credentials or missing required config fieldCheck connector config fields
CLIENT_INITIALIZATIONIntegrationErrorSDK failed to initialize native libraryCheck platform compatibility
CONNECT_TIMEOUTNetworkErrorCould not reach connectorCheck network / proxy config
RESPONSE_TIMEOUTNetworkErrorConnector took too longIncrease totalTimeoutMs
TOTAL_TIMEOUTNetworkErrorRequest exceeded total timeoutIncrease totalTimeoutMs

Advanced Configuration

Timeouts

const client = new PaymentClient(config, {
  http: {
    totalTimeoutMs: 30000,
    connectTimeoutMs: 10000,
    responseTimeoutMs: 25000,
    keepAliveTimeoutMs: 60000,
  }
});

Proxy

const client = new PaymentClient(config, {
  http: {
    proxy: {
      httpsUrl: 'https://proxy.company.com:8443',
      bypassUrls: ['http://localhost']
    }
  }
});

Per-Request Overrides

const response = await client.authorize(request, {
  http: { totalTimeoutMs: 60000 }
});

Connection Pooling

Create the client once and reuse it:

// Good: create once, reuse
const client = new PaymentClient(config);
for (const payment of payments) {
  await client.authorize(payment);
}

CA Certificate Pinning

const client = new PaymentClient(config, {
  http: {
    caCert: fs.readFileSync('ca.pem', 'utf8')
  }
});

Building from Source

# Clone the repository
git clone https://github.com/juspay/hyperswitch-prism.git
cd hyperswitch-prism/sdk/javascript

# Build native library, generate bindings, and pack
make pack

# Run tests
make test-pack

# With live API credentials
STRIPE_API_KEY=sk_test_xxx make test-pack