Skip to main content

Node.js SDK

Use the official OrcaRail Node.js SDK to accept crypto payments with minimal integration code. The SDK handles authentication, request formatting, and webhook signature verification.

Installation

Install the package from npm:

npm install @orcarail/node

Configuration

Create an OrcaRail client with your API key and secret. Optionally set a custom base URL (e.g., for local development) and timeout.

import OrcaRail from '@orcarail/node'

const orcarail = new OrcaRail(
process.env.ORCARAIL_API_KEY!, // e.g., "ak_live_xxx"
process.env.ORCARAIL_API_SECRET!, // e.g., "sk_live_xxx"
{
baseUrl: 'https://api.orcarail.com/api/v1', // optional; default
timeout: 30000, // optional; ms, default 30000
}
)

For local development, point baseUrl to your API:

const orcarail = new OrcaRail(apiKey, apiSecret, {
baseUrl: 'http://127.0.0.1:3000/api/v1',
timeout: 65000, // /complete can take up to ~65s
})

Commission (split and get your share)

API keys can have an optional commission percent (0–100). Set it in the Dashboard → API Keys or via PATCH /api/v1/api-keys/:id with commissionPercent. Payments created with that key will include the commission in the quote (visible to the payer) and the commission amount is sent to your withdrawal settings address when funds are withdrawn.

Payment Intents

Create a Payment Intent

Create a payment intent with amount, currency, token, network, and return/cancel URLs.

const intent = await orcarail.paymentIntents.create({
amount: '100.00',
currency: 'usd',
payment_method_types: ['crypto'],
tokenId: 1, // e.g., USDC
networkId: 1, // e.g., Ethereum
return_url: 'https://yourapp.com/success',
cancel_url: 'https://yourapp.com/cancel',
description: 'Order #12345',
metadata: { order_id: '12345' },
withdrawal_address: '0x...', // optional: override where funds are withdrawn; omit to use your account default
})

console.log(intent.id) // e.g., "550e8400-e29b-41d4-a716-446655440000"
console.log(intent.client_secret)
console.log(intent.payment_link?.link)

Confirm and Redirect to Pay

Confirm the intent to get the hosted pay URL, then redirect the customer:

const confirmed = await orcarail.paymentIntents.confirm(intent.id, {
client_secret: intent.client_secret!,
return_url: 'https://yourapp.com/success',
})

// Redirect user to confirmed.pay_url or nextAction.redirectToUrl.url

Retrieve a Payment Intent

Fetch the current state of a payment intent:

const intent = await orcarail.paymentIntents.retrieve(
'550e8400-e29b-41d4-a716-446655440000'
)
console.log(intent.status)

Update a Payment Intent

Update amount, metadata, URLs, or withdrawal address before the customer pays:

const updated = await orcarail.paymentIntents.update(
'550e8400-e29b-41d4-a716-446655440000',
{
amount: '150.00',
metadata: { order_id: '12345' },
withdrawal_address: '0x...', // optional: override withdrawal address for this payment
}
)

Cancel a Payment Intent

Cancel when the user abandons or hits your cancel URL:

const canceled = await orcarail.paymentIntents.cancel(
'550e8400-e29b-41d4-a716-446655440000'
)

Complete a Payment Intent

When the user lands on your success/return URL, mark the intent as processing (this triggers the payment_intent.processing webhook):

const completed = await orcarail.paymentIntents.complete(
'550e8400-e29b-41d4-a716-446655440000'
)

Pay by Slug

If you use payment links with slugs, you can get pay details and cancel by slug:

// Get pay details by slug
const pay = await orcarail.pay.get('pl_abc123')

// Cancel by slug
await orcarail.pay.cancel('pl_abc123')

Webhooks

Verify webhook signatures and parse events using the SDK.

Verify Signature

Use the raw request body and the x-webhook-signature header. The secret is your webhook secret (from your API key / dashboard).

import OrcaRail from '@orcarail/node'

const orcarail = new OrcaRail(apiKey, apiSecret)
const signature = req.headers['x-webhook-signature']
const rawBody = req.rawBody // must be raw string or Buffer, not parsed JSON

if (!orcarail.webhooks.verifySignature(rawBody, signature, webhookSecret)) {
return res.status(400).send('Invalid signature')
}

Construct Event (Verify and Parse)

Verify and parse in one step; throws if the signature is invalid:

const event = orcarail.webhooks.constructEvent(
rawBody,
req.headers['x-webhook-signature'],
webhookSecret
)

switch (event.type) {
case 'payment_intent.completed':
console.log('Payment succeeded:', event.data.object.id)
break
case 'payment_intent.processing':
console.log('Payment processing:', event.data.object.id)
break
case 'payment_intent.canceled':
console.log('Payment canceled:', event.data.object.id)
break
case 'payment_intent.requires_payment_method':
console.log('Payment needs method:', event.data.object.id)
break
default:
console.log('Unhandled event:', event.type)
}

Express Example

const express = require('express')
const OrcaRail = require('@orcarail/node').default

const app = express()
const orcarail = new OrcaRail(
process.env.ORCARAIL_API_KEY,
process.env.ORCARAIL_API_SECRET
)

// Use raw body for signature verification
app.post(
'/webhooks/orcarail',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = req.headers['x-webhook-signature']
const rawBody = req.body // Buffer

try {
const event = orcarail.webhooks.constructEvent(
rawBody,
signature,
process.env.ORCARAIL_WEBHOOK_SECRET
)
console.log('Event:', event.type, event.data.object.id)
res.status(200).json({ received: true })
} catch (err) {
res.status(400).send('Invalid signature')
}
}
)

Next.js (App Router) Example

In a Route Handler, read the raw body and verify:

import { NextRequest, NextResponse } from 'next/server'
import OrcaRail from '@orcarail/node'

const orcarail = new OrcaRail(
process.env.ORCARAIL_API_KEY!,
process.env.ORCARAIL_API_SECRET!
)

export async function POST(request: NextRequest) {
const rawBody = await request.text()
const signature = request.headers.get('x-webhook-signature') ?? ''

try {
const event = orcarail.webhooks.constructEvent(
rawBody,
signature,
process.env.ORCARAIL_WEBHOOK_SECRET!
)
// Handle event.type and event.data.object
return NextResponse.json({ received: true })
} catch {
return NextResponse.json({ error: 'Invalid signature' }, { status: 400 })
}
}

Error Handling

The SDK throws typed errors you can handle:

import OrcaRail, {
OrcaRailError,
OrcaRailAPIError,
OrcaRailAuthenticationError,
OrcaRailSignatureVerificationError,
} from '@orcarail/node';

try {
const intent = await orcarail.paymentIntents.create({ ... });
} catch (err) {
if (err instanceof OrcaRailAuthenticationError) {
console.error('Invalid API key or secret');
} else if (err instanceof OrcaRailAPIError) {
console.error('API error:', err.statusCode, err.message);
} else if (err instanceof OrcaRailSignatureVerificationError) {
console.error('Webhook signature invalid');
} else if (err instanceof OrcaRailError) {
console.error('OrcaRail error:', err.message);
}
}

Demo App

For a full integration example (create intent, redirect to pay, success page, complete, webhooks), see the open-source demo:

See Also