Appearance
Invoice Management
This example demonstrates how to integrate with the Engagifii API using JavaScript.
Code Example
javascript
/**
* Engagifii Revenue API - Node.js Integration Example
* Invoice Management System
*
* This example demonstrates a complete invoice management integration
* including authentication, invoice creation, payment processing, and error handling.
*/
const axios = require('axios');
const dotenv = require('dotenv');
// Load environment variables
dotenv.config();
/**
* Revenue API Client Class
* Handles authentication, request management, and error handling
*/
class RevenueAPIClient {
constructor(config) {
this.baseURL = config.baseURL || 'https://engagifii-prod-revenue.azurewebsites.net';
this.clientId = config.clientId;
this.clientSecret = config.clientSecret;
this.tenantCode = config.tenantCode;
this.apiVersion = config.apiVersion || '1.0';
this.accessToken = null;
this.tokenExpiry = null;
// Create axios instance with defaults
this.client = axios.create({
baseURL: this.baseURL,
timeout: 30000,
headers: {
'Content-Type': 'application/json',
'tenant-code': this.tenantCode,
'api-version': this.apiVersion
}
});
// Add request interceptor for authentication
this.client.interceptors.request.use(
async (config) => {
const token = await this.getValidToken();
config.headers.Authorization = `Bearer ${token}`;
return config;
},
(error) => Promise.reject(error)
);
// Add response interceptor for error handling
this.client.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
// Token expired, refresh and retry
this.accessToken = null;
const originalRequest = error.config;
const token = await this.getValidToken();
originalRequest.headers.Authorization = `Bearer ${token}`;
return this.client(originalRequest);
}
// Format error for better handling
const formattedError = this.formatError(error);
return Promise.reject(formattedError);
}
);
}
/**
* Get valid access token (refresh if needed)
*/
async getValidToken() {
if (!this.accessToken || Date.now() >= this.tokenExpiry - 60000) {
await this.refreshToken();
}
return this.accessToken;
}
/**
* Refresh OAuth access token
*/
async refreshToken() {
try {
const response = await axios.post(
`${this.baseURL}/oauth/token`,
new URLSearchParams({
grant_type: 'client_credentials',
client_id: this.clientId,
client_secret: this.clientSecret,
scope: 'revenue.api.full'
}),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
);
this.accessToken = response.data.access_token;
this.tokenExpiry = Date.now() + (response.data.expires_in * 1000);
console.log('✓ Token refreshed successfully');
} catch (error) {
console.error('Failed to refresh token:', error.message);
throw error;
}
}
/**
* Format API errors for better debugging
*/
formatError(error) {
if (error.response?.data?.error) {
const apiError = error.response.data.error;
const err = new Error(apiError.message || 'API Error');
err.code = apiError.code;
err.details = apiError.details;
err.requestId = apiError.requestId;
err.status = error.response.status;
return err;
}
return error;
}
// ============= Invoice Operations =============
/**
* Create a new invoice
*/
async createInvoice(invoiceData) {
const response = await this.client.post('/api/1.0/invoice/manual', {
customerType: invoiceData.customerType,
customerId: invoiceData.customerId,
invoiceDate: invoiceData.invoiceDate || new Date().toISOString().split('T')[0],
dueDate: invoiceData.dueDate,
items: invoiceData.items,
notes: invoiceData.notes,
sendEmail: invoiceData.sendEmail || false,
emailTo: invoiceData.emailTo
});
return response.data;
}
/**
* Get invoice details
*/
async getInvoice(invoiceId) {
const response = await this.client.get(`/api/1.0/invoice/${invoiceId}`);
return response.data;
}
/**
* List invoices with filtering
*/
async listInvoices(filters = {}) {
const response = await this.client.get('/api/1.0/invoice', {
params: {
page: filters.page || 1,
pageSize: filters.pageSize || 20,
status: filters.status,
customerId: filters.customerId,
fromDate: filters.fromDate,
toDate: filters.toDate,
sortBy: filters.sortBy || 'invoiceDate',
sortOrder: filters.sortOrder || 'desc'
}
});
return response.data;
}
/**
* Send invoice to customer
*/
async sendInvoice(invoiceId, emailOptions = {}) {
const response = await this.client.post(`/api/1.0/invoice/send/${invoiceId}`, {
emailTo: emailOptions.to,
emailCc: emailOptions.cc,
emailSubject: emailOptions.subject,
emailMessage: emailOptions.message,
attachPdf: emailOptions.attachPdf !== false
});
return response.data;
}
/**
* Mark invoice as void
*/
async voidInvoice(invoiceId, reason) {
const response = await this.client.post(`/api/1.0/invoice/${invoiceId}/void`, {
reason: reason,
notifyCustomer: true
});
return response.data;
}
// ============= Payment Operations =============
/**
* Process payment for invoices
*/
async processPayment(paymentData) {
const response = await this.client.post('/api/1.0/payment', {
paymentMethod: paymentData.method,
amount: paymentData.amount,
paymentDate: paymentData.date || new Date().toISOString().split('T')[0],
invoices: paymentData.invoices,
creditCard: paymentData.creditCard,
billingAddress: paymentData.billingAddress,
notes: paymentData.notes
});
return response.data;
}
/**
* Get payment details
*/
async getPayment(paymentId) {
const response = await this.client.get(`/api/1.0/payment/${paymentId}`);
return response.data;
}
/**
* Process refund
*/
async processRefund(paymentId, amount, reason) {
const response = await this.client.post(`/api/1.0/payment/${paymentId}/refund`, {
amount: amount,
reason: reason,
notifyCustomer: true
});
return response.data;
}
// ============= Credit Note Operations =============
/**
* Create credit note
*/
async createCreditNote(creditNoteData) {
const response = await this.client.post('/api/1.0/creditNote', {
customerId: creditNoteData.customerId,
customerType: creditNoteData.customerType,
creditNoteDate: creditNoteData.date || new Date().toISOString().split('T')[0],
creditNoteType: creditNoteData.type || 'Refund',
items: creditNoteData.items,
reason: creditNoteData.reason,
relatedInvoiceId: creditNoteData.invoiceId
});
return response.data;
}
/**
* Apply credit note to invoices
*/
async applyCreditNote(creditNoteId, applications) {
const response = await this.client.post(`/api/1.0/creditNote/${creditNoteId}/apply`, {
invoices: applications
});
return response.data;
}
// ============= Subscription Operations =============
/**
* Create subscription
*/
async createSubscription(subscriptionData) {
const response = await this.client.post('/api/1.0/subscription', {
customerId: subscriptionData.customerId,
customerType: subscriptionData.customerType,
planId: subscriptionData.planId,
startDate: subscriptionData.startDate,
billingCycle: subscriptionData.billingCycle || 'Monthly',
price: subscriptionData.price,
autoRenew: subscriptionData.autoRenew !== false,
paymentMethodId: subscriptionData.paymentMethodId
});
return response.data;
}
/**
* Cancel subscription
*/
async cancelSubscription(subscriptionId, reason, type = 'EndOfBillingPeriod') {
const response = await this.client.post(`/api/1.0/subscription/${subscriptionId}/cancel`, {
cancellationType: type,
reason: reason
});
return response.data;
}
// ============= Reporting Operations =============
/**
* Generate report
*/
async generateReport(reportType, parameters) {
const response = await this.client.post('/api/1.0/report/generate', {
reportId: reportType,
parameters: parameters,
format: 'json'
});
return response.data;
}
/**
* Get account balance
*/
async getAccountBalance(customerId, customerType) {
const response = await this.client.get(
`/api/1.0/account/balance/statistics/${customerType}/${customerId}`
);
return response.data;
}
}
/**
* Example Usage - Complete Invoice Workflow
*/
async function exampleInvoiceWorkflow() {
// Initialize API client
const api = new RevenueAPIClient({
clientId: process.env.ENGAGIFII_CLIENT_ID,
clientSecret: process.env.ENGAGIFII_CLIENT_SECRET,
tenantCode: process.env.ENGAGIFII_TENANT_CODE
});
try {
console.log('Starting Invoice Management Workflow\n');
console.log('=====================================\n');
// 1. Create a new invoice
console.log('1. Creating new invoice...');
const invoice = await api.createInvoice({
customerType: 'Person',
customerId: '123e4567-e89b-12d3-a456-426614174000',
dueDate: '2024-02-15',
items: [
{
itemName: 'Professional Services',
description: 'Consulting services for January 2024',
quantity: 10,
unitPrice: 150.00
},
{
itemName: 'Support Package',
description: 'Monthly support package',
quantity: 1,
unitPrice: 500.00
}
],
notes: 'Payment due within 30 days'
});
console.log(`✓ Invoice created: ${invoice.invoiceNumber}`);
console.log(` Amount: $${invoice.totalAmount}`);
console.log(` Status: ${invoice.status}\n`);
// 2. Send invoice to customer
console.log('2. Sending invoice to customer...');
await api.sendInvoice(invoice.invoiceId, {
to: ['customer@example.com'],
subject: `Invoice ${invoice.invoiceNumber} from Your Company`,
message: 'Please find attached your invoice. Thank you for your business!'
});
console.log('✓ Invoice sent successfully\n');
// 3. Process payment
console.log('3. Processing payment...');
const payment = await api.processPayment({
method: 'CreditCard',
amount: invoice.totalAmount,
invoices: [
{
invoiceId: invoice.invoiceId,
amount: invoice.totalAmount
}
],
creditCard: {
cardNumber: '4111111111111111',
cardholderName: 'John Doe',
expiryMonth: '12',
expiryYear: '2025',
cvv: '123'
},
billingAddress: {
street1: '123 Main St',
city: 'New York',
state: 'NY',
postalCode: '10001',
country: 'US'
}
});
console.log(`✓ Payment processed: ${payment.paymentId}`);
console.log(` Transaction ID: ${payment.transactionId}`);
console.log(` Status: ${payment.status}\n`);
// 4. Verify invoice is paid
console.log('4. Verifying invoice status...');
const updatedInvoice = await api.getInvoice(invoice.invoiceId);
console.log(`✓ Invoice status: ${updatedInvoice.status}`);
console.log(` Paid amount: $${updatedInvoice.paidAmount}`);
console.log(` Balance: $${updatedInvoice.balanceAmount}\n`);
// 5. Generate invoice report
console.log('5. Generating revenue report...');
const report = await api.generateReport('revenue-summary', {
fromDate: '2024-01-01',
toDate: '2024-01-31',
groupBy: 'customer'
});
console.log(`✓ Report generated: ${report.reportId}\n`);
// 6. Check customer balance
console.log('6. Checking customer account balance...');
const balance = await api.getAccountBalance(
'123e4567-e89b-12d3-a456-426614174000',
'Person'
);
console.log(`✓ Customer Balance:`);
console.log(` Total Revenue: $${balance.totalRevenue}`);
console.log(` Outstanding: $${balance.outstandingBalance}`);
console.log(` Available Credit: $${balance.availableCredit}\n`);
console.log('=====================================');
console.log('Workflow completed successfully!');
} catch (error) {
console.error('\n❌ Error occurred:');
console.error(` Code: ${error.code}`);
console.error(` Message: ${error.message}`);
if (error.details) {
console.error(' Details:');
error.details.forEach(detail => {
console.error(` - ${detail.field}: ${detail.message}`);
});
}
if (error.requestId) {
console.error(` Request ID: ${error.requestId}`);
}
}
}
// Run example if this file is executed directly
if (require.main === module) {
exampleInvoiceWorkflow();
}
// Export for use in other modules
module.exports = {
RevenueAPIClient,
exampleInvoiceWorkflow
};Usage Notes
- Make sure to replace placeholder values with your actual API credentials
- Install required dependencies before running this code
- Refer to the main API documentation for detailed endpoint information
Download
Download this example: invoice-management.js
