ERPNext Integration

Configure ERPNext CRM integration for lead management and customer portal data.

Last updated: 31 January 2026

ERPNext Integration

EthosPower AI integrates with ERPNext for CRM functionality, customer data, and business operations. This guide covers setup and configuration.

Overview

The ERPNext integration provides:

  • Lead Creation - Contact form submissions create CRM leads
  • Customer Portal - Dashboard shows projects, tasks, and invoices
  • MCP Access - Claude Code can query ERPNext directly

Prerequisites

  • ERPNext instance (v14+) with REST API enabled
  • API user with appropriate permissions
  • Network access from Cloudflare Workers to ERPNext

API Configuration

Generate API Credentials

  1. Log into ERPNext as Administrator
  2. Navigate to Settings > User
  3. Select or create an API user
  4. Go to API Access section
  5. Generate API Key and Secret

Configure Wrangler Secrets

# Set ERPNext credentials
wrangler secret put ERPNEXT_URL <<< "https://erp.yourdomain.org"
wrangler secret put ERPNEXT_API_KEY <<< "your-api-key"
wrangler secret put ERPNEXT_API_SECRET <<< "your-api-secret"

Use heredoc syntax (<<<) to avoid empty values from pipe issues.

Authentication Pattern

The ERPNext client uses token authentication:

import { ERPNextClient } from "@/lib/erpnext";

const client = new ERPNextClient({
  baseUrl: env.ERPNEXT_URL,
  apiKey: env.ERPNEXT_API_KEY,
  apiSecret: env.ERPNEXT_API_SECRET,
});

// Token format: "token {api_key}:{api_secret}"

Graceful Degradation

The integration uses graceful degradation - if ERPNext is unavailable, core functionality continues:

// Contact form example
const leadResult = await createLead(formData, env);

// If ERPNext not configured or unavailable, skip silently
if (!leadResult.success) {
  console.log("ERPNext unavailable, continuing without lead creation");
}

// Email notification still sent
await sendEmail(formData);

Available Operations

Lead Creation

await client.createDocument("Lead", {
  lead_name: "Company Name",
  email_id: "contact@example.com",
  source: "Website",
  notes: "Inquiry about AI consulting",
});

Query Documents

const leads = await client.getDocuments("Lead", {
  filters: [["status", "=", "Open"]],
  fields: ["name", "lead_name", "email_id"],
  limit: 10,
});

Customer Portal Queries

// Get customer's projects
const projects = await client.getDocuments("Project", {
  filters: [["customer", "=", customerId]],
  fields: ["name", "project_name", "status", "percent_complete"],
});

// Get customer's invoices
const invoices = await client.getDocuments("Sales Invoice", {
  filters: [["customer", "=", customerId]],
  fields: ["name", "posting_date", "grand_total", "status"],
});

MCP Server Access

Claude Code has direct ERPNext access via the erpnext MCP server:

# List DocTypes
mcp-cli call erpnext/get_doctypes '{}'

# Get Lead fields
mcp-cli call erpnext/get_doctype_fields '{"doctype": "Lead"}'

# Query documents
mcp-cli call erpnext/get_documents '{"doctype": "Lead", "limit": 5}'

Caching Strategy

Dashboard data is cached in Cloudflare KV to reduce ERPNext load:

Data Type TTL Cache Key Pattern
Projects 5 min erpnext:projects:{custId}
Tasks 5 min erpnext:tasks:{projId}
Invoices 15 min erpnext:invoices:{custId}

Troubleshooting

Authentication Errors

Verify credentials:

curl -X GET "https://erp.yourdomain.org/api/resource/User"   -H "Authorization: token api_key:api_secret"

Empty API Secret

If ERPNEXT_API_SECRET is empty after setting:

# Wrong - can result in empty value
echo "secret" | wrangler secret put ERPNEXT_API_SECRET

# Correct - use heredoc
wrangler secret put ERPNEXT_API_SECRET <<< "secret"

Permission Denied

Ensure API user has roles with read/write access to required DocTypes:

  • Lead (read, write, create)
  • Project (read)
  • Task (read)
  • Sales Invoice (read)
  • Customer (read)
erpnextcrmapiintegration