Client Initialization
First, create an InventPay client instance:Copy
import { InventPayClient } from "@inventpay/sdk";
const client = new InventPayClient({
apiKey: process.env.INVENTPAY_API_KEY!,
});
Payments
Create a Payment
Create a fixed-currency payment:Copy
const payment = await client.payments.create({
amount: "100.00",
currency: "BTC",
description: "Order #12345",
callbackUrl: "https://yoursite.com/webhooks/inventpay",
metadata: {
orderId: "12345",
customerId: "cust_abc123",
},
});
console.log("Payment Address:", payment.paymentAddress);
console.log("Amount to pay:", payment.amount, payment.currency);
The
metadata field can store any JSON-serializable data and will be returned
in webhooks.Get Payment Status
Copy
const payment = await client.payments.get("pmt_1234567890");
console.log("Status:", payment.status);
console.log("Paid:", payment.isPaid);
console.log("Confirmed:", payment.isConfirmed);
// Check specific statuses
if (payment.status === "pending") {
console.log("Waiting for payment...");
} else if (payment.status === "confirmed") {
console.log("Payment confirmed!");
}
List Payments
Copy
// List all payments
const payments = await client.payments.list();
// List with pagination
const paymentsPage1 = await client.payments.list({
limit: 20,
page: 1,
});
// List with filters
const recentPayments = await client.payments.list({
status: "confirmed",
currency: "BTC",
limit: 10,
});
Invoices
Create an Invoice
Create a multi-currency invoice:Copy
const invoice = await client.invoices.create({
amount: "1000.00",
currency: "USD",
description: "Premium Subscription",
callbackUrl: "https://yoursite.com/webhooks/inventpay",
metadata: {
subscriptionId: "sub_xyz789",
plan: "premium",
},
});
console.log("Invoice URL:", invoice.hostedUrl);
// Available payment options
invoice.paymentOptions.forEach((option) => {
console.log(`Pay ${option.amount} ${option.currency}`);
});
Get Invoice Status
Copy
const invoice = await client.invoices.get("inv_1234567890");
console.log("Status:", invoice.status);
console.log("Selected currency:", invoice.selectedCurrency);
console.log("Amount paid:", invoice.amountPaid);
List Invoices
Copy
const invoices = await client.invoices.list({
status: "pending",
limit: 20,
});
Balances
Get All Balances
Copy
const balances = await client.balances.getAll();
balances.forEach((balance) => {
console.log(`${balance.currency}: ${balance.available}`);
});
Get Balance by Currency
Copy
const btcBalance = await client.balances.getByCurrency("BTC");
console.log("Available:", btcBalance.available);
console.log("Pending:", btcBalance.pending);
console.log("Total:", btcBalance.total);
Get Transaction History
Copy
const transactions = await client.balances.getTransactions("BTC", {
limit: 50,
page: 1,
});
transactions.forEach((tx) => {
console.log(`${tx.type}: ${tx.amount} ${tx.currency}`);
});
Withdrawals
Create a Withdrawal
Copy
const withdrawal = await client.withdrawals.create({
amount: "0.5",
currency: "BTC",
address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
network: "bitcoin",
});
console.log("Withdrawal ID:", withdrawal.id);
console.log("Status:", withdrawal.status);
console.log("Fee:", withdrawal.fee);
Always verify the withdrawal address before submitting. Cryptocurrency
transactions are irreversible.
Get Withdrawal Status
Copy
const withdrawal = await client.withdrawals.get("wth_1234567890");
console.log("Status:", withdrawal.status);
if (withdrawal.status === "completed") {
console.log("Transaction hash:", withdrawal.transactionHash);
}
List Withdrawals
Copy
const withdrawals = await client.withdrawals.list({
currency: "BTC",
status: "completed",
limit: 20,
});
Webhook Handling
Verify Webhook Signature
Copy
import express from "express";
import { InventPayClient } from "@inventpay/sdk";
const app = express();
const client = new InventPayClient({
apiKey: process.env.INVENTPAY_API_KEY!,
});
app.post(
"/webhooks/inventpay",
express.raw({ type: "application/json" }),
async (req, res) => {
const signature = req.headers["x-inventpay-signature"] as string;
const payload = req.body.toString();
try {
// Verify the webhook signature
const event = client.webhooks.verify(payload, signature);
// Handle the event
switch (event.type) {
case "payment.confirmed":
console.log("Payment confirmed:", event.data);
// Update your database, fulfill order, etc.
break;
case "payment.failed":
console.log("Payment failed:", event.data);
// Handle failed payment
break;
case "invoice.paid":
console.log("Invoice paid:", event.data);
// Activate subscription, etc.
break;
case "withdrawal.completed":
console.log("Withdrawal completed:", event.data);
// Update balance display, etc.
break;
}
res.status(200).send("OK");
} catch (error) {
console.error("Webhook verification failed:", error);
res.status(400).send("Invalid signature");
}
}
);
Type-Safe Event Handling
Copy
import type { WebhookEvent } from "@inventpay/sdk";
function handleWebhook(event: WebhookEvent) {
switch (event.type) {
case "payment.confirmed":
// TypeScript knows event.data is a Payment
console.log("Payment amount:", event.data.amount);
break;
case "invoice.paid":
// TypeScript knows event.data is an Invoice
console.log("Invoice currency:", event.data.selectedCurrency);
break;
case "withdrawal.completed":
// TypeScript knows event.data is a Withdrawal
console.log("Withdrawal hash:", event.data.transactionHash);
break;
}
}
Error Handling
Try-Catch Pattern
Copy
import { InventPayError } from "@inventpay/sdk";
try {
const payment = await client.payments.create({
amount: "100.00",
currency: "BTC",
});
} catch (error) {
if (error instanceof InventPayError) {
// API error
console.error("API Error:", {
status: error.statusCode,
code: error.code,
message: error.message,
});
// Handle specific errors
if (error.statusCode === 401) {
console.error("Invalid API key");
} else if (error.statusCode === 429) {
console.error("Rate limit exceeded");
}
} else {
// Network or other error
console.error("Unexpected error:", error);
}
}
Error Types
Copy
import {
InventPayError,
AuthenticationError,
RateLimitError,
ValidationError,
} from '@inventpay/sdk';
try {
const payment = await client.payments.create({ ... });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Authentication failed');
} else if (error instanceof RateLimitError) {
console.error('Rate limit exceeded, retry after:', error.retryAfter);
} else if (error instanceof ValidationError) {
console.error('Validation failed:', error.errors);
} else if (error instanceof InventPayError) {
console.error('API error:', error.message);
}
}
Advanced Usage
Pagination
Copy
// Manual pagination
let page = 1;
let hasMore = true;
while (hasMore) {
const payments = await client.payments.list({
limit: 100,
page,
});
// Process payments
payments.forEach((payment) => {
console.log(payment.id);
});
hasMore = payments.length === 100;
page++;
}
Parallel Requests
Copy
// Fetch multiple resources in parallel
const [balances, payments, withdrawals] = await Promise.all([
client.balances.getAll(),
client.payments.list({ limit: 10 }),
client.withdrawals.list({ limit: 10 }),
]);
Request Cancellation
Copy
const controller = new AbortController();
// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);
try {
const payment = await client.payments.create(
{
amount: "100",
currency: "BTC",
},
{
signal: controller.signal,
}
);
} catch (error) {
if (error.name === "AbortError") {
console.log("Request cancelled");
}
}
Idempotency
Prevent duplicate payments using idempotency keys:Copy
const payment = await client.payments.create(
{
amount: "100.00",
currency: "BTC",
},
{
idempotencyKey: "order-12345", // Unique key per operation
}
);
// Making the same request again will return the same payment
const samePayment = await client.payments.create(
{
amount: "100.00",
currency: "BTC",
},
{
idempotencyKey: "order-12345",
}
);
console.log(payment.id === samePayment.id); // true
TypeScript Features
Type Guards
Copy
import type { Payment, Invoice } from "@inventpay/sdk";
function processTransaction(transaction: Payment | Invoice) {
if ("paymentAddress" in transaction) {
// TypeScript knows this is a Payment
console.log("Payment address:", transaction.paymentAddress);
} else {
// TypeScript knows this is an Invoice
console.log("Hosted URL:", transaction.hostedUrl);
}
}
Generics
Copy
async function fetchResource<T>(fetcher: () => Promise<T>): Promise<T | null> {
try {
return await fetcher();
} catch (error) {
console.error("Failed to fetch:", error);
return null;
}
}
const payment = await fetchResource(() => client.payments.get("pmt_123"));
Utility Types
Copy
import type { Payment } from "@inventpay/sdk";
// Extract only the fields you need
type PaymentSummary = Pick<Payment, "id" | "amount" | "currency" | "status">;
// Make all fields optional
type PartialPayment = Partial<Payment>;
// Make all fields required
type RequiredPayment = Required<Payment>;
Best Practices
Always use environment variables for API keys
Implement proper error handling for all API calls
Use webhooks for payment notifications instead of polling
Verify webhook signatures to ensure authenticity
Store metadata with payments for easier tracking
Use idempotency keys for critical operations
Implement retry logic for network failures
Log errors and monitor API responses
Test with sandbox environment before production
Keep the SDK updated to the latest version
Common Patterns
Payment Flow with Webhook
Copy
// 1. Create payment
const payment = await client.payments.create({
amount: "100.00",
currency: "BTC",
description: "Order #12345",
callbackUrl: "https://yoursite.com/webhooks/inventpay",
metadata: { orderId: "12345" },
});
// 2. Show payment address to user
console.log(
"Please send",
payment.amount,
payment.currency,
"to",
payment.paymentAddress
);
// 3. Wait for webhook (in separate handler)
app.post("/webhooks/inventpay", async (req, res) => {
const event = client.webhooks.verify(
req.body,
req.headers["x-inventpay-signature"]
);
if (event.type === "payment.confirmed" && event.data.id === payment.id) {
// Payment confirmed! Fulfill order
await fulfillOrder(event.data.metadata.orderId);
}
res.status(200).send("OK");
});
Subscription Payment
Copy
// Create invoice for subscription
const invoice = await client.invoices.create({
amount: "29.99",
currency: "USD",
description: "Monthly Subscription",
metadata: {
userId: "user_123",
plan: "premium",
},
});
// Redirect user to invoice page
res.redirect(invoice.hostedUrl);
// Handle webhook when paid
app.post("/webhooks/inventpay", async (req, res) => {
const event = client.webhooks.verify(
req.body,
req.headers["x-inventpay-signature"]
);
if (event.type === "invoice.paid") {
const { userId, plan } = event.data.metadata;
await activateSubscription(userId, plan);
}
res.status(200).send("OK");
});
