Your warehouse manager updates a delivery status in ERPNext, and a WhatsApp message reaches the customer three seconds later — no manual copy-pasting, no missed notifications. That kind of tight integration is entirely achievable, but many teams underestimate what it actually takes to wire ERPNext reliably to the tools around it. This guide covers the practical patterns for connecting ERPNext to WhatsApp Business, payment gateways, and arbitrary third-party APIs using webhooks and REST — without creating a maintenance nightmare.
How ERPNext Exposes Its API Surface
ERPNext (built on the Frappe framework) gives you two primary integration paths: the REST API and Server-side Python hooks. Understanding the difference saves you from building the wrong thing.
- REST API — Every doctype automatically gets CRUD endpoints at
/api/resource/{DocType}. You can also expose custom Python functions via@frappe.whitelist(), reachable at/api/method/your_app.module.function_name. Authentication uses either API key + secret (for machine-to-machine) or session cookies (for browser clients). - Webhooks (outbound) — Frappe can fire HTTP POST requests on document events (after_insert, on_submit, on_cancel, etc.). You configure these in Setup → Integrations → Webhooks. The payload is a JSON representation of the document.
- Server Scripts / hooks.py — For logic that runs inside the ERPNext process, you write Python in
hooks.pyor use Frappe's Server Script doctype. This is where you call external APIs in response to internal events.
For most integrations, you'll combine all three: an inbound REST call triggers a document save, a webhook fires to notify an external system, and a server script handles the business logic in between.
Integrating ERPNext With WhatsApp Business API
WhatsApp Business Platform (Meta's Cloud API) uses HTTP POST requests, so the integration is straightforward at the transport level — but the sequencing matters.
Sending WhatsApp Notifications From ERPNext
The most common pattern is to send a template message when an ERPNext document reaches a certain status. Here's the core flow:
- Configure a Webhook on the target doctype (e.g., Sales Invoice) triggered on on_submit.
- Point the webhook to a relay service — either a small Python microservice or a direct Server Script — that formats the Meta API payload.
- The relay sends a POST to
https://graph.facebook.com/v19.0/{phone_number_id}/messageswith your approved template name and the dynamic variables. - Store the WhatsApp message ID returned by Meta against the ERPNext document for delivery tracking.
One important consideration: Meta's template messages require approval and use a fixed structure. Map your ERPNext field names to the template variables at the relay layer, not inside ERPNext itself — this keeps the ERPNext side clean when templates change.
Receiving WhatsApp Replies Into ERPNext
Inbound messages arrive at your webhook URL via Meta's webhook subscription. The relay service validates the X-Hub-Signature-256 header, parses the payload, and either creates an ERPNext document (e.g., a Communication or a custom Inbox doctype) or updates an existing one via the REST API. Use idempotency keys (Meta sends duplicate webhooks on retry) — a simple Redis SET-NX guard on the message ID prevents duplicate document creation.
Payment Gateway Integration Patterns
Connecting a payment gateway — Razorpay, Stripe, PayPal, or a regional processor — follows a well-worn pattern, but the edge cases are where teams get into trouble.
| Gateway Event | ERPNext Action | Risk to Handle |
|---|---|---|
| Payment captured | Submit Payment Entry, link to Sales Invoice | Webhook arrives before invoice is submitted |
| Payment failed | Update custom status field, notify customer | Duplicate webhook firing twice |
| Refund issued | Create Credit Note or Payment Entry (debit) | Currency mismatch on multi-currency invoices |
| Subscription renewed | Create new Sales Invoice, send receipt | ERPNext docstatus guard on already-submitted docs |
Always verify the webhook signature before acting — every major gateway provides a signature in the request headers. For Stripe it's Stripe-Signature; for Razorpay it's an HMAC-SHA256 of the payload. Reject unsigned requests at the edge, before they touch your Frappe database.
The Race Condition Problem
A common failure mode: the payment gateway fires its webhook milliseconds after the user submits the checkout form, but your ERPNext Sales Order isn't saved yet. Handle this with a short retry queue (Redis + a background worker) that retries the document lookup up to five times over thirty seconds before raising an alert. Don't retry blindly in the webhook handler itself — that ties up the HTTP connection and triggers gateway timeouts.
Connecting ERPNext to Generic Third-Party APIs
The same principles scale to any external system — a shipping provider, a CRM, an accounting platform, or a custom internal tool.
Outbound Calls: Server Scripts vs Microservices
For simple, low-frequency calls (a few hundred per day), Frappe's Server Script doctype works fine. You write Python directly in the ERPNext UI, and it executes in the Frappe worker process. For high-frequency or latency-sensitive calls, move the logic out to a dedicated microservice. ERPNext fires a webhook; the microservice does the heavy lifting and POSTs results back via the REST API. This decouples the external API's reliability from your core ERP process.
Storing Credentials Safely
Never hardcode API keys in Server Scripts or hooks.py. Use ERPNext's Custom Doctype approach: create a singleton settings document (e.g., "Integration Settings"), store keys in Password type fields (Frappe encrypts these at rest), and fetch them via frappe.get_cached_doc(). Rotate keys by updating a single document rather than hunting through code.
Error Handling and Observability
Log every outbound API call and its response to a custom doctype ("API Log" or similar). Include: timestamp, endpoint, HTTP status, latency, and a truncated response body. This makes debugging integration failures far less painful than parsing raw Error Log entries. Set up a scheduled job that scans for failed calls older than a threshold and raises a Frappe alert or sends an internal notification.
Authentication Strategies for Inbound REST Calls
When external systems call your ERPNext instance, you have three options:
- API Key + Secret — Best for server-to-server integrations. Generate a key pair in the User settings, pass them as headers (
Authorization: token key:secret). Assign a dedicated system user with only the minimum required permissions. - Token-based custom auth — For public-facing endpoints that don't belong to a specific user (e.g., a payment gateway callback), decorate a whitelisted function with
allow_guest=Trueand validate a shared secret from the request header inside the function body. - OAuth2 — Frappe supports OAuth2 out of the box for user-delegated access. Relevant if you're building an integration where end users authorize access to their own data.
A Note on Rate Limits and Reliability
External APIs rate-limit you. WhatsApp limits template sends per phone number per day. Payment gateways have per-second limits on their webhook acknowledgment expectations. Build your integration layer with explicit rate-limit awareness: use exponential backoff on 429/503 responses, add circuit breakers for APIs that go down for extended periods, and queue outbound calls through Redis rather than firing them synchronously in document save hooks.
Structuring Your Integration Codebase
A pattern that scales well for Frappe apps: keep all integration code in a dedicated Python module (e.g., integrations/whatsapp.py, integrations/stripe.py). Each module exposes a clean Python interface that the rest of your app calls — it knows nothing about webhooks or HTTP internals. The webhook handler is just a thin adapter that calls into this module. When the external API changes, you update one file.
Teams at Mexilet Technologies follow this same layered approach when building ERPNext integrations for clients — separating transport, authentication, business logic, and error handling into distinct layers rather than bundling everything into a single Server Script.
Frequently Asked Questions
Can ERPNext integrate with WhatsApp without a third-party plugin?
Yes, using Meta's WhatsApp Business Cloud API directly. You write a custom Frappe app or Server Script that sends HTTP POST requests to Meta's graph API and registers a webhook URL to receive inbound messages. No plugin is strictly required, though several community plugins exist that provide a UI layer over the same API calls.
How do I handle payment gateway webhooks securely in ERPNext?
Expose a @frappe.whitelist(allow_guest=True) function as your webhook endpoint. Inside the function, validate the gateway's signature header using HMAC before performing any database operation. Queue the actual processing to a background job so the webhook handler returns quickly — most gateways expect a 200 response within 5-10 seconds or they retry.
What's the safest way to store third-party API credentials in ERPNext?
Create a singleton custom doctype (one record for the entire system) with Password-type fields for secrets. Frappe encrypts Password fields at rest. Fetch credentials at runtime with frappe.get_cached_doc(). Never commit credentials to your repository or store them in frappe.conf unless it's an environment-level setting your deployment pipeline manages via environment variables.
Should I use Frappe Webhooks or Server Scripts for integrations?
Use Frappe Webhooks when the external system needs to be notified of a document event and the payload structure maps cleanly to what the external system expects. Use Server Scripts (or hooks.py in a custom app) when you need conditional logic, transformation, or when you want to call the external API and use its response within the same transaction. For anything complex or high-volume, move the logic to a proper custom app rather than Server Scripts.
When you're ready to build this, Mexilet can help — explore our ERP & ERPNext services and business automation solutions.
If you're planning an ERPNext integration — whether it's WhatsApp, a payment gateway, a shipping API, or a custom internal tool — reach out to Mexilet Technologies for a technical conversation. Our team has built production integrations across dozens of stacks and can help you design a solution that's reliable, maintainable, and ready to scale.
