Node.js

Official TypeScript / Node.js SDK for the Pine Labs Online Payment Gateway — published on npm as pinelabs-node.

pinelabs-node is the official TypeScript / Node.js SDK for the Pine Labs Online Payment Gateway (Plural). It is generated from the same OpenAPI spec that powers this documentation, so every operation, request, and response model is fully typed.

  • Package: pinelabs-node on npm
  • Runtime: Node.js ≥ 18
  • Module format: ESM-only
ESM-only

This package ships as ES modules. Use import from a project with "type": "module", or use dynamic import(). Calling require("pinelabs-node") in CommonJS will fail with ERR_PACKAGE_PATH_NOT_EXPORTED.

Install

Bash
npm install pinelabs-node

Quickstart

The Pine Labs API uses OAuth2 with the client_credentials grant. Exchange your client_id / client_secret for an access token, then pass it to PinelabsApiClient.

Ts
import { PinelabsApiClient } from "pinelabs-node";
 
const baseUrl = "https://pluraluat.v2.pinepg.in"; // UAT
// const baseUrl = "https://api.pluralpay.in";     // Production
 
// 1. Get a token (the auth call itself does not need a bearer token)
const auth = new PinelabsApiClient({ baseUrl, token: "" });
 
const tokenResponse = await auth.authentication.generateToken({
  grant_type: "client_credentials",
  client_id: process.env.PINELABS_CLIENT_ID!,
  client_secret: process.env.PINELABS_CLIENT_SECRET!,
});
 
// 2. Build an authenticated client
const client = new PinelabsApiClient({
  baseUrl,
  token: tokenResponse.access_token,
});
 
// 3. Call any operation
const order = await client.orders.createOrder({
  merchant_order_reference: "order-001",
  order_amount: { value: 50000, currency: "INR" }, // ₹500.00
  // ...see the API reference for the full schema
});
 
console.log(order);

Environments

EnvironmentBase URL
UAThttps://pluraluat.v2.pinepg.in
Productionhttps://api.pluralpay.in

Pass the URL via baseUrl. The exported PinelabsApiEnvironment enum currently only contains Production; for UAT, set baseUrl explicitly.

Auto-refreshing token

For long-running services, cache the token and refresh it before it expires. Pass a function instead of a string to token — it will be invoked on every request, including the auth call itself, so guard against re-entrancy:

Ts
import { PinelabsApiClient } from "pinelabs-node";
 
const baseUrl = "https://pluraluat.v2.pinepg.in";
const auth = new PinelabsApiClient({ baseUrl, token: "" });
 
let cached: { value: string; expiresAt: number } | undefined;
let fetching = false;
 
async function getToken(): Promise<string | undefined> {
  // Re-entrancy guard: the auth endpoint itself doesn't need a token.
  if (fetching) return undefined;
 
  // Refresh ~30s before expiry
  if (cached && Date.now() < cached.expiresAt - 30_000) {
    return cached.value;
  }
 
  fetching = true;
  try {
    const r = await auth.authentication.generateToken({
      grant_type: "client_credentials",
      client_id: process.env.PINELABS_CLIENT_ID!,
      client_secret: process.env.PINELABS_CLIENT_SECRET!,
    });
    cached = {
      value: r.access_token,
      expiresAt: Date.now() + r.expires_in * 1000,
    };
    return cached.value;
  } finally {
    fetching = false;
  }
}
 
const client = new PinelabsApiClient({ baseUrl, token: getToken });
 
// Every call now picks up a fresh token automatically.
await client.orders.getOrderById({ order_id: "ord-123" });
Don't skip the re-entrancy guard

Without the fetching flag the token supplier will recurse into itself when the auth call fires — your process will hang silently with no output and no error.

Sub-clients

PinelabsApiClient exposes one sub-client per API tag. All are lazy-loaded.

Sub-clientPurpose
client.authenticationOAuth token generation
client.ordersCreate, capture, cancel, and fetch orders
client.refundsCreate and look up refunds
client.settlementsSettlement reports + UTR lookup
client.checkoutHosted-checkout related operations
client.paymentLinksSingle + bulk payment links
client.cardPaymentsDirect card payment + OTP flow
client.bnplBuy-Now-Pay-Later eligibility and flows
client.convenienceFeeConvenience-fee config and computation
client.eChallansGovernment e-challan integration
client.applePayApple Pay session + decryption
client.internationalPaymentsCross-border (DCC / MCC) payments
client.customersCustomer profile management
client.tokenizationCard / network tokenization
client.payoutsPayouts: balance, create, cancel, list
client.subscriptionsPlansRecurring-billing plans
client.subscriptionsSubscriptionsSubscription lifecycle
client.subscriptionsPresentationsSubscription debit presentations
client.payByPointsLoyalty / points-based payments
client.affordabilitySuiteEMI / offer eligibility
client.splitSettlementsSplit settlements between sub-merchants

For the full operation list and request/response schemas, see the API reference.

Error handling

The SDK exports two typed error classes. Catch them to distinguish HTTP failures from network timeouts:

Ts
import {
  PinelabsApiClient,
  PinelabsApiError,
  PinelabsApiTimeoutError,
} from "pinelabs-node";
 
try {
  await client.orders.getOrderById({ order_id: "missing" });
} catch (err) {
  if (err instanceof PinelabsApiError) {
    console.error("HTTP", err.statusCode, err.body);
  } else if (err instanceof PinelabsApiTimeoutError) {
    console.error("Request timed out");
  } else {
    throw err;
  }
}

PinelabsApiError exposes statusCode, body (parsed JSON when the server returns JSON), and headers.

Per-request options

Every operation accepts an optional second argument for ad-hoc overrides:

Ts
await client.orders.createOrder(
  { merchant_order_reference: "order-002", order_amount: { value: 1000, currency: "INR" } },
  {
    timeoutInSeconds: 10,
    maxRetries: 0,
    abortSignal: AbortSignal.timeout(8000),
    headers: { "x-correlation-id": "req-abc" },
  },
);

Useful for per-call timeouts, propagating trace IDs, or disabling retries on idempotency-sensitive flows.

TypeScript usage

The package ships full .d.ts declarations. Recommended tsconfig.json settings for consumers:

JSON
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": ["ES2023", "DOM", "DOM.Iterable"],
    "strict": true
  }
}

The DOM / DOM.Iterable libs are required because the SDK's fetch shims reference Headers.entries() and HeadersIterator.

Source & support

For the agent-toolkit (LangChain, Vercel AI SDK, OpenAI Agents, Anthropic, Claude Agent SDK), see pinelabs-agent-toolkit. For the command-line interface, see pinelabs-cli.

New chat
Responses are generated using AI and may contain mistakes.
Hi! I'm Pine, your AI developer assistant. Ask me anything about Pine Labs APIs, integrations, or troubleshooting.

Tip: you can create a new chat with + E