npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@houlak/drynex-sdk

v1.2.0

Published

TypeScript SDK for Drynex Payment Gateway

Readme

Drynex SDK

npm version License: MIT TypeScript

A modern TypeScript SDK for integrating with the Drynex Payment Gateway. This SDK provides a type-safe and developer-friendly way to interact with Drynex's payment processing services.

⚠️ This SDK is in ALPHA stage and is not intended for public use.
Access and usage are strictly limited to teams authorized by Drynex.

📋 Table of Contents

✨ Features

  • 🔒 Full TypeScript support with comprehensive type definitions
  • 🚀 SDK functionalities:
    • Automatic token management (generation and refresh)
    • Organization Management
      • Create and manage organizations
      • Group related business entities
    • Merchant Management
      • Create, update, and delete merchants
      • Configure payment rails (VISA, Mastercard)
      • Set up merchant profiles and settings
    • Payment Instruments
      • Tokenize and store payment methods
      • Manage card information securely
      • Support for multiple payment methods
    • Payment Processing
      • Authorization with PAN or token
      • Automatic and manual capture modes
      • Payment cancellation
      • Refund processing
      • Payment verification
      • Installment support
    • Webhook Management
      • Configure webhook endpoints
      • Set up event notifications
      • Manage webhook secrets
  • ⚡ Modern async/await API
  • 🛡️ Built-in error handling
  • 📚 Comprehensive documentation
  • 🔐 Secure token management
  • 🌐 Multi-currency support
  • 🏢 Multi-tenant architecture

📦 Installation

# Using npm
npm install @houlak/drynex-sdk

# Using yarn
yarn add @houlak/drynex-sdk

# Using pnpm
pnpm add @houlak/drynex-sdk

🚀 Quick Start

import { DrynexClient, DrynexTypes } from '@houlak/drynex-sdk';

// Create the DrynexClient instance with your credentials
// The client will automatically handle token management
const drynexClientConfig: DrynexTypes.ClientConfig = {
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  environment: DrynexTypes.Enums.Environment.SANDBOX, // or PRODUCTION
};

const drynexClient = new DrynexClient(drynexClientConfig);

// Now you can use the DrynexClient instance
const createOrganizationRequest: DrynexTypes.RequestTypes.CreateOrganizationRequest = {
  name: 'My Organization',
};

const createOrganizationResponse: DrynexTypes.ApiResponse<DrynexTypes.ResponseTypes.OrganizationDTO> =
  await drynexClient.organizations.create(createOrganizationRequest);

if (!createOrganizationResponse.success || !createOrganizationResponse.data) {
  throw new Error('Create organization failed');
}

const organization: DrynexTypes.ResponseTypes.OrganizationDTO = createOrganizationResponse.data;

const createMerchantRequest: DrynexTypes.RequestTypes.CreateMerchantRequest = {
  name: 'My Store',
  organization_id: organization.id,
  country: 'US',
  city: 'New York',
  state: 'NY',
  billing_address: {
    street: '123 Main St',
    city: 'New York',
    state: 'NY',
    country: 'US',
    postal_code: '10001',
  },
  location_address: {
    street: '123 Main St',
    city: 'New York',
    state: 'NY',
    country: 'US',
    postal_code: '10001',
  },
  classification_mode: 'retail',
  default_currency: 'USD',
  supported_currencies: ['USD', 'EUR'],
  activity: 'retail',
  alias: 'my-store-ny',
  email: '[email protected]',
  external_id: 'ext_123',
  phone: '+1234567890',
  tax_id: '123456789',
  rails: {
    VISA: {
      category_code: '5411',
      payfac_id: 'payfac_123',
    },
    MASTERCARD: {
      category_code: '5411',
      payfac_id: 'payfac_123',
    },
  },
};

const createMerchantResponse: DrynexTypes.ApiResponse<DrynexTypes.ResponseTypes.MerchantDTO> =
  await drynexClient.merchants.create(createMerchantRequest);

if (!createMerchantResponse.success || !createMerchantResponse.data) {
  throw new Error('Create merchant failed');
}

const merchant: DrynexTypes.ResponseTypes.MerchantDTO = createMerchantResponse.data;

const createInstrumentRequest: DrynexTypes.RequestTypes.CreateInstrumentRequest = {
  type: 'CARD',
  card: {
    number: '4242424242424242',
    expiration_month: '12',
    expiration_year: '2030',
    first_name: 'John',
    last_name: 'Doe',
    cvv: '123',
  },
  user_data: {
    billing_address: {
      street: '123 Main St',
      number: 'Apt 4B',
      city: 'New York',
      state: 'NY',
      zip_code: '10001',
      country: 'US',
    },
  },
};

const createInstrumentResponse: DrynexTypes.ApiResponse<DrynexTypes.ResponseTypes.InstrumentDTO> =
  await drynexClient.instruments.create(createInstrumentRequest);

if (!createInstrumentResponse.success || !createInstrumentResponse.data) {
  throw new Error('Create instrument failed');
}

const instrument: DrynexTypes.ResponseTypes.InstrumentDTO = createInstrumentResponse.data;

📋 API Reference

Authentication

The SDK handles authentication automatically. When you create an DrynexClient instance with your client credentials, it will:

  1. Generate an initial token using your credentials
  2. Automatically refresh the token before it expires (with a 5-minute buffer)
  3. Handle token reuse across all requests
  4. Manage concurrent token refresh requests
  5. Handle authentication errors gracefully

Creating an DrynexClient instance

The DrynexClient is the main entry point for interacting with the Drynex API. It requires your client credentials and an environment configuration.

import { DrynexClient, DrynexTypes } from '@houlak/drynex-sdk';

const clientConfig: DrynexTypes.ClientConfig = {
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  environment: DrynexTypes.Enums.Environment.SANDBOX, // or PRODUCTION
};

const drynexClient = new DrynexClient(clientConfig);

Organizations

organizations.create(data: CreateOrganizationRequest): Promise<ApiResponse<OrganizationDTO>>

Creates a new organization in the Drynex system. Organizations can have multiple merchants and are used to group related business entities.

const organization = await drynexClient.organizations.create({
  name: 'Acme Corp',
});

organizations.get(): Promise<ApiResponse<OrganizationDTO[]>>

Retrieves all organizations from the Drynex system.

const organizations = await drynexClient.organizations.get();

Merchants

merchants.create(data: CreateMerchantRequest): Promise<ApiResponse<MerchantDTO>>

Creates a new merchant in the Drynex system. This is the first step in setting up a new merchant account. The merchant will be associated with the specified organization and will be configured with the provided payment rails and settings.

const merchant = await drynexClient.merchants.create({
  name: 'My Store',
  organization_id: 'org_123',
  country: DrynexTypes.Enums.Country.UNITED_STATES,
  city: 'New York',
  state: 'NY',
  billing_address: {
    street: '123 Main St',
    city: 'New York',
    state: 'NY',
    country: DrynexTypes.Enums.Country.UNITED_STATES,
    postal_code: '10001',
  },
  location_address: {
    street: '123 Main St',
    city: 'New York',
    state: 'NY',
    country: DrynexTypes.Enums.Country.UNITED_STATES,
    postal_code: '10001',
  },
  classification_mode: 'retail',
  default_currency: DrynexTypes.Enums.Currency.USD,
  supported_currencies: [DrynexTypes.Enums.Currency.USD, DrynexTypes.Enums.Currency.EUR],
  activity: 'retail',
  alias: 'my-store-ny',
  email: '[email protected]',
  external_id: 'ext_123',
  phone: '+1234567890',
  tax_id: '123456789',
  rails: {
    [DrynexTypes.Enums.Rail.VISA]: {
      category_code: '5411',
      payfac_id: 'payfac_123',
    },
    [DrynexTypes.Enums.Rail.MASTERCARD]: {
      category_code: '5411',
      payfac_id: 'payfac_123',
    },
  },
});

merchants.getById(merchantId: string): Promise<ApiResponse<MerchantDTO>>

Retrieves a merchant's information by its unique identifier.

const merchant = await drynexClient.merchants.getById('merch_123456789');

merchants.get(request: GetMerchantsRequest): Promise<ApiResponse<MerchantDTO[]>>

Lists all merchants for an organization with pagination support.

const merchants = await drynexClient.merchants.get({
  organization_id: 'org-d0j35vc4t5u70r4eso70',
  page: 1,
  page_size: 20,
  sort: 'created_at:desc',
});

merchants.update(merchantId: string, data: UpdateMerchantRequest): Promise<ApiResponse<MerchantDTO>>

Updates an existing merchant's information.

const updatedMerchant = await drynexClient.merchants.update('merch_123456789', {
  name: 'Updated Store Name',
  email: '[email protected]',
  phone: '+1987654321',
  billing_address: {
    street: '456 New St',
    city: 'Los Angeles',
    state: 'CA',
    country: DrynexTypes.Enums.Country.UNITED_STATES,
    postal_code: '90001',
  },
});

merchants.updateRails(merchantId: string, data: UpdateMerchantRailsRequest): Promise<ApiResponse<MerchantDTO>>

Updates the rails configuration for a merchant.

const updatedMerchant = await drynexClient.merchants.updateRails('merch_123456789', {
  [DrynexTypes.Enums.Rail.VISA]: {
    category_code: '1234',
    payfac_id: 'pfc-123',
    external_id: 'mer-ext-123',
    classification: 'micro-merchant',
    annual_volume: [
      {
        currency: DrynexTypes.Enums.Currency.COP,
        value: 10000000,
      },
    ],
    products: {
      [DrynexTypes.Enums.Product.DEBIT]: {
        network_merchant_id: 'VISA-123',
        enabled: true,
      },
      [DrynexTypes.Enums.Product.CREDIT]: {
        network_merchant_id: 'VISA-123',
        enabled: true,
      },
    },
  },
});

merchants.delete(merchantId: string): Promise<ApiResponse<void>>

Deletes a merchant from the Drynex system.

await drynexClient.merchants.delete('merch_123456789');

Payment Instruments

instruments.create(data: CreateInstrumentRequest): Promise<ApiResponse<InstrumentDTO>>

Creates a new payment instrument. The instrument is tokenized and stored securely in the Drynex system.

const card = await drynexClient.instruments.create({
  type: 'CARD',
  card: {
    number: '4242424242424242',
    expiration_month: '12',
    expiration_year: '2025',
    first_name: 'John',
    last_name: 'Doe',
    cvv: '123',
  },
  user_data: {
    billing_address: {
      street: '123 Main St',
      number: 'Apt 4B',
      city: 'New York',
      state: 'NY',
      zip_code: '10001',
      country: DrynexTypes.Enums.Country.UNITED_STATES,
    },
  },
});

instruments.get(): Promise<ApiResponse<InstrumentDTO[]>>

Retrieves all payment instruments associated with the merchant. This includes both active and inactive instruments, with their current status and details.

const instruments = await drynexClient.instruments.get();

instruments.getById(id: string): Promise<ApiResponse<InstrumentDTO>>

Retrieves detailed information about a specific payment instrument, including its type and status.

const instrument = await drynexClient.instruments.getById('instr_123');

instruments.update(id: string, data: UpdateInstrumentRequest): Promise<ApiResponse<InstrumentDTO>>

Updates an existing payment instrument's information. This can be used to update expiration dates, cardholder information, or other instrument details.

const updatedInstrument = await drynexClient.instruments.update('instr_123', {
  card: {
    expiration_month: '12',
    expiration_year: '2026',
    first_name: 'John',
    last_name: 'Smith',
  },
});

instruments.delete(id: string): Promise<ApiResponse<void>>

Permanently deletes a payment instrument from the system. This operation cannot be undone and will invalidate the instrument for future use.

await client.instruments.delete('instr_123');

Payments

payments.authorizeWithPan(data: AuthorizeWithPanRequest): Promise<ApiResponse<AuthorizePaymentDTO>>

Authorizes a payment transaction using PAN (Primary Account Number). This is used for direct card payments.

const payment = await drynexClient.payments.authorizeWithPan({
  amount: {
    value: 25.25,
    currency: DrynexTypes.Enums.Currency.USD,
  },
  intent: DrynexTypes.Enums.PaymentIntent.AUTHORIZATION,
  trace_id: 'any-format-34324366',
  entry_mode: DrynexTypes.Enums.PaymentEntryMode.MANUAL,
  capture: {
    mode: DrynexTypes.Enums.CaptureMode.AUTOMATIC,
  },
  merchant_id: 'mer-d0r0b17npsai542l2400',
  installments: {
    quantity: 2,
    type: '03',
  },
  instrument: {
    type: 'CARD',
    card: {
      number: '4024007108904086',
      expiration_month: '12',
      expiration_year: '25',
      holder_name: 'John Doe',
      cvv: '123',
    },
    user_data: {
      billing_address: {
        street: '123 Main St',
        number: 'Apt 4B',
        city: 'New York',
        state: 'NY',
        zip_code: '10001',
        country: DrynexTypes.Enums.Country.UNITED_STATES,
        phone_number: '+1234567890',
      },
    },
  },
});

payments.authorizeWithToken(data: AuthorizeWithTokenRequest): Promise<ApiResponse<AuthorizePaymentDTO>>

Authorizes a payment transaction using a previously tokenized instrument.

const payment = await drynexClient.payments.authorizeWithToken({
  amount: {
    value: 25.25,
    currency: DrynexTypes.Enums.Currency.USD,
  },
  intent: DrynexTypes.Enums.PaymentIntent.AUTHORIZATION,
  trace_id: 'any-format-34324366',
  entry_mode: DrynexTypes.Enums.PaymentEntryMode.MANUAL,
  capture: {
    mode: DrynexTypes.Enums.CaptureMode.AUTOMATIC,
  },
  merchant_id: 'mer-d0r0b17npsai542l2400',
  installments: {
    quantity: 2,
    type: '03',
  },
  instrument: {
    id: 'instr_123456789',
  },
});

payments.capture(paymentId: string, data: CapturePaymentRequest): Promise<ApiResponse<CapturePaymentDTO>>

Captures a previously authorized payment. Only payments created with capture_manual mode can be captured.

const capture = await drynexClient.payments.capture('pay_123', {
  amount: {
    value: 25.25,
    currency: DrynexTypes.Enums.Currency.USD,
  },
});

payments.cancel(paymentId: string): Promise<ApiResponse<CancelPaymentDTO>>

Cancels a payment transaction.

const cancel = await drynexClient.payments.cancel('pay-d0v32ak2mts03heh7amg');

payments.refund(paymentId: string, data: RefundPaymentRequest): Promise<ApiResponse<RefundPaymentDTO>>

Refunds a payment transaction.

const refund = await drynexClient.payments.refund('pay-d0v32ak2mts03heh7amg', {
  amount: {
    value: 25.25,
    currency: DrynexTypes.Enums.Currency.USD,
  },
});

payments.verify(data: VerifyPaymentRequest): Promise<ApiResponse<AuthorizePaymentDTO>>

Verifies a payment instrument (card) status.

const verify = await drynexClient.payments.verify({
  intent: DrynexTypes.Enums.PaymentIntent.AUTHORIZATION,
  merchant_id: 'mer-d0r0b17npsai542l2400',
  trace_id: 'any-format-34324366',
  instrument: {
    type: 'CARD',
    card: {
      number: '4024007108904086',
      expiration_month: '12',
      expiration_year: '25',
      holder_name: 'John Doe',
      cvv: '123',
    },
    user_data: {
      billing_address: {
        street: '123 Main St',
        number: 'Apt 4B',
        city: 'New York',
        state: 'NY',
        zip_code: '10001',
        country: DrynexTypes.Enums.Country.UNITED_STATES,
        phone_number: '+1234567890',
      },
    },
  },
});

Webhooks

webhooks.create(data: CreateWebhookRequest): Promise<ApiResponse<WebhookDTO>>

Creates a new webhook configuration.

const webhook = await drynexClient.webhooks.create({
  url: 'https://example.com/webhook',
  events: [DrynexTypes.Enums.EventType.PAYMENT_AUTHORIZATION_PROCESSED],
  description: 'Webhook for payment events',
  rate_limit: 1,
});

webhooks.get(): Promise<ApiResponse<WebhookDTO[]>>

Retrieves all webhook configurations.

const webhooks = await drynexClient.webhooks.get();

webhooks.getSecret(webhookId: string): Promise<ApiResponse<WebhookSecretDTO>>

Retrieves a webhook configuration's secret key by its ID.

const webhookSecret = await drynexClient.webhooks.getSecret('webhook_123');

📘 TypeScript Types

The SDK provides comprehensive TypeScript types that can be imported from the DrynexTypes namespace. This allows you to have full type safety and autocompletion when working with the SDK.

Available Types

import { DrynexTypes } from '@houlak/drynex-sdk';

// Enums
const environment = DrynexTypes.Enums.Environment.SANDBOX;
const country = DrynexTypes.Enums.Country.USA;
const rail = DrynexTypes.Enums.Rail.VISA;

// Request Types
const createMerchantRequest: DrynexTypes.RequestTypes.CreateMerchantRequest = {
  name: 'My Store',
  organization_id: 'org_123',
  // ... other merchant fields
};

const createInstrumentRequest: DrynexTypes.RequestTypes.CreateInstrumentRequest = {
  type: 'CARD',
  card: {
    number: '4242424242424242',
    expiration_month: '12',
    expiration_year: '2025',
    first_name: 'John',
    last_name: 'Doe',
    cvv: '123',
  },
};

// Response Types
const merchantResponse: DrynexTypes.ResponseTypes.MerchantDTO = {
  id: 'merch_123',
  name: 'My Store',
  // ... other merchant fields
};

const instrumentResponse: DrynexTypes.ResponseTypes.InstrumentDTO = {
  id: 'instr_123',
  type: 'CARD',
  // ... other instrument fields
};

Type Categories

The SDK's types are organized into several categories:

  1. Enums: Constants and enumerations used throughout the SDK

  2. Request Types: Types for API request payloads

  3. Response Types: Types for API response data

  4. API Response: Generic wrapper type for all API responses

    interface ApiResponse<T> {
      data: T | null;
      success: boolean;
      error?: {
        code: string;
        message: string;
        details?: Record<string, unknown>;
      };
    }

Type Safety Example

Here's an example of how the types help catch errors at compile time:

import { DrynexClient, DrynexTypes } from '@houlak/drynex-sdk';

const client = new DrynexClient({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  environment: DrynexTypes.Enums.Environment.SANDBOX,
});

// TypeScript will show an error if required fields are missing
const merchant = await client.merchants.create({
  name: 'My Store',
  // Error: missing required field 'organization_id'
});

// TypeScript will show an error if field types don't match
const instrument = await client.instruments.create({
  type: 'CARD',
  card: {
    number: 4242424242424242, // Error: number should be a string
    expiration_month: 12, // Error: should be a string
    expiration_year: 2025, // Error: should be a string
    first_name: 'John',
    last_name: 'Doe',
  },
});

// TypeScript will provide autocompletion for response fields
const response = await client.instruments.getById('ins_123');
if (response.success && response.data) {
  console.log(response.data.status); // Autocomplete available
  console.log(response.data.type); // Autocomplete available
  console.log(response.data.invalid_field); // Error: field doesn't exist
}

🛡️ Error Handling

The SDK provides built-in error handling with detailed error messages. All API responses are wrapped in an ApiResponse type:

interface ApiResponse<T> {
  data: T | null;
  success: boolean;
  error?: {
    code: string;
    message: string;
    details?: Record<string, unknown>;
  };
}

Example error handling:

try {
  const result = await drynexClient.organizations.create({
    name: 'Acme Corp',
  });

  if (!result.success) {
    console.error(`Error ${result.error?.code}: ${result.error?.message}`);
    if (result.error?.details) {
      console.error('Details:', result.error.details);
    }
    return;
  }

  // Use result.data safely here
  console.log('Organization created:', result.data);
} catch (error) {
  // Handle unexpected errors
  console.error('Unexpected error:', error);
}

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.