@felloh-org/node-sdk
v1.0.1
Published
Official Node.js SDK for the Felloh payment API
Downloads
13
Readme
@felloh-org/node-sdk
Official Node.js SDK for the Felloh payments API.
Installation
npm install @felloh-org/node-sdkRequires Node.js 18 or later.
Quick Start
import { FellohClient } from '@felloh-org/node-sdk';
const client = new FellohClient({
publicKey: process.env.FELLOH_PUBLIC_KEY,
privateKey: process.env.FELLOH_PRIVATE_KEY,
});
const bookings = await client.bookings.list({
organisation: 'your-org-id',
});
console.log(bookings.data);Configuration
const client = new FellohClient({
publicKey: 'your-public-key', // required
privateKey: 'your-private-key', // required
baseUrl: 'https://api.felloh.com', // optional, default shown
timeout: 30000, // optional, request timeout in ms
maxRetries: 2, // optional, retries on 5xx/network errors
tokenRefreshBuffer: 60, // optional, seconds before expiry to refresh token
logger: (entry) => { // optional, called after every request
console.log(`${entry.method} ${entry.url} ${entry.statusCode} ${entry.durationMs}ms`);
},
});Usage
Bookings
// List (with filters)
const bookings = await client.bookings.list({
organisation: 'org-id',
keyword: '[email protected]',
take: 20,
});
// Auto-paginate
for await (const booking of client.bookings.listAll({ organisation: 'org-id' })) {
console.log(booking.id);
}
// Get single
const booking = await client.bookings.get('booking-id');
// Create
const created = await client.bookings.create({
organisation: 'org-id',
booking_reference: 'REF-001',
customer_name: 'James Dean',
email: '[email protected]',
currency: 'GBX',
gross_amount: 100000, // amounts in lowest denomination (pence)
});
// Update
await client.bookings.update('booking-id', { customer_name: 'Jane Dean' });
// Delete
await client.bookings.delete('booking-id');Transactions
// List with filters
const transactions = await client.transactions.list({
organisation: 'org-id',
statuses: ['COMPLETE'],
date_from: '2024-01-01',
date_to: '2024-12-31',
});
// Refund
await client.transactions.refund('transaction-id', { amount: 5000 });
// Complete pre-auth
await client.transactions.complete('transaction-id');
// Reverse pre-auth
await client.transactions.reverse('transaction-id');
// Re-assign to different booking
await client.transactions.reassign('transaction-id', { booking_id: 'booking-id' });Payment Links
const link = await client.paymentLinks.create({
customer_name: 'John Doe',
email: '[email protected]',
organisation: 'org-id',
amount: 50000,
type: 'CARD',
});Customers
const customer = await client.customers.create({
organisation: 'org-id',
customer_name: 'Jane Smith',
email: '[email protected]',
address_1: '123 High Street',
city: 'London',
county: 'Greater London',
post_code: 'SW1A 1AA',
});All Resources
| Resource | Property |
|---|---|
| Organisations | client.organisations |
| Bookings | client.bookings |
| Booking Components | client.bookingComponents |
| Transactions | client.transactions |
| Customers | client.customers |
| Payment Links | client.paymentLinks |
| Ecommerce | client.ecommerce |
| Refunds | client.refunds |
| Charges | client.charges |
| Chargebacks | client.chargebacks |
| Credit Notes | client.creditNotes |
| Suppliers | client.suppliers |
| Beneficiaries | client.beneficiaries |
| Disbursements | client.disbursements |
| Ledger | client.ledger |
| Acquirer Settlement | client.batches |
| API Keys | client.apiKeys |
| Audit | client.audit |
| AISP | client.aisp |
| Scheduled Payments | client.scheduledPayments |
| Enums | client.enums |
Pagination
All list endpoints support manual pagination via skip and take parameters:
const page = await client.bookings.list({ organisation: 'org-id', skip: 0, take: 20 });
console.log(page.meta.count); // total countMost resources also provide a listAll() method that returns an AsyncIterable for automatic pagination:
import { toArray } from '@felloh-org/node-sdk';
// Iterate one by one
for await (const booking of client.bookings.listAll({ organisation: 'org-id' })) {
console.log(booking.id);
}
// Or collect all into an array
const all = await toArray(client.bookings.listAll({ organisation: 'org-id' }));Webhook Verification
import { verifyWebhookSignature, assertWebhookSignature } from '@felloh-org/node-sdk';
// Returns boolean
const isValid = verifyWebhookSignature({
payload: rawRequestBody,
signature: req.headers['x-signature'],
secret: 'your-webhook-secret',
});
// Or throw on failure
assertWebhookSignature({
payload: rawRequestBody,
signature: req.headers['x-signature'],
secret: 'your-webhook-secret',
});Error Handling
The SDK throws typed errors for different HTTP status codes:
import {
FellohError,
FellohNotFoundError,
FellohValidationError,
} from '@felloh-org/node-sdk';
try {
await client.bookings.get('non-existent');
} catch (err) {
if (err instanceof FellohNotFoundError) {
console.log('Booking not found');
}
if (err instanceof FellohError) {
console.log(err.statusCode); // HTTP status code
console.log(err.errors); // API error details
console.log(err.meta); // Response metadata including request_id
}
}| Error Class | Status Code |
|---|---|
| FellohAuthenticationError | 401 |
| FellohForbiddenError | 403 |
| FellohNotFoundError | 404 |
| FellohValidationError | 422 |
| FellohRateLimitError | 429 |
| FellohServerError | 5xx |
| FellohNetworkError | Network failures |
Logging
Pass a logger callback to observe every HTTP request:
import type { LogEntry } from '@felloh-org/node-sdk';
const client = new FellohClient({
publicKey: '...',
privateKey: '...',
logger: (entry: LogEntry) => {
console.log(`${entry.method} ${entry.url} → ${entry.statusCode} (${entry.durationMs}ms)`);
},
});Each LogEntry includes method, url, statusCode, durationMs, and attempt (retry count).
Token Management
The SDK automatically handles JWT token acquisition and refresh. Tokens are cached and proactively refreshed before expiry. No manual token management is needed.
Development
npm install
npm test # unit tests
npm run test:integration # integration tests (requires sandbox credentials)
npm run build # compile ESM + CJS
npm run typecheck # type check without emittingLicense
MIT - see LICENSE for details.
