The ERPNext Medusa Integration manages the complete order lifecycle across both platforms. When a customer creates a cart in Medusa, ERPNext documents are created and updated at each stage — from initial quotation through to payment collection — with status pushed back to Medusa so the storefront stays current.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/aerele/medusa_integration/llms.txt
Use this file to discover all available pages before exploring further.
Order flow overview
Customer creates cart in Medusa
Medusa calls
POST /api/method/medusa_integration.api.create_quotation with the customer ID, items, and billing address. ERPNext creates a Quotation linked to the customer’s Lead or Customer record.ERP team reviews and prices the quotation
The ERP team sets item rates on the Quotation and moves it to “Ready for Customer Review” workflow state. This triggers
export_quotation_on_update(), which pushes the priced quote back to Medusa via POST /store/quotation-update.Customer approves in Medusa
Medusa calls
update_quotation() or update_quotation_new() with approval: "Approved". ERPNext submits the Quotation and, if create_so=true, immediately creates and submits a Sales Order plus a Payment Request.Invoice and delivery
When a Sales Invoice is submitted,
export_sales_invoice_on_update() triggers a status push to Medusa. When a Delivery Note is submitted, export_delivery_note_on_update() does the same.Document event hooks
All order-related hooks are registered inhooks.py:
create_quotation()
Called by Medusa when a customer cart needs an ERP-side quotation. The endpoint resolves the Medusacustomer_id to either an ERPNext Customer or Lead, then creates a Quotation with those items.
Request body:
- Items are resolved from
medusa_variant_idon the Website Item record. - Item tax templates are applied automatically from the Item’s tax configuration.
- Standard and negotiated prices are fetched via
fetch_standard_price()and stored on the Quotation items. - If
billing_addressis provided, an ERPNext Address record is created or updated and linked to the customer. - If
create_so=trueand the party is a Lead, a Customer record is created from the Lead first (assigned to the “Ecommerce Customer” group), and the Quotation is re-linked to the new Customer.
update_quotation()
Handles approval or rejection of a quotation. Called by Medusa after a customer acts on a priced quote.- Approved
- Rejected
Sets
workflow_state to "Approved", submits the Quotation, and stores the Medusa order ID.If create_so=true, it also:- Creates and submits a Sales Order from the Quotation.
- Creates a Payment Request linked to the Sales Order.
- Returns the payment URL so Medusa can redirect the customer.
update_quotation_new()
A newer update path that replaces the item list on the Quotation entirely before approving. This is used when the Medusa backend sends back a modified set of approved and unapproved items with explicit rates. In addition to replacingitems, it also:
- Populates
unapproved_itemswith items that were rejected. - Populates
custom_increased_itemswith items whose quantities changed. - Adds a delivery charge if the billing city is not Muscat (delivery charge amount sourced from
Homepage Landing). - Calls
export_quotation()immediately after saving to push the updated quote back to Medusa.
export_quotation()
Pushes a priced Quotation’s line items, totals, taxes, and delivery details back to Medusa. Called automatically viaexport_quotation_on_update() when the Quotation moves to “Ready for Customer Review”.
Endpoint called: POST /store/quotation-update?quot_id={medusa_quotation_id}
Payload structure:
export_sales_order()
Pushes Sales Order status and payment status to Medusa. Called on every submit, update, and post-submit update of an ecommerce Sales Order (wherefrom_ecommerce=1).
Endpoint called: POST /store/order-update?order_id={medusa_order_id}
payment_status is derived by looking up any submitted Sales Invoice linked to the order and using its status field.
export_sales_invoice_on_update()
Fires when a Sales Invoice is submitted (on_submit). It finds the linked Sales Order, verifies it has a medusa_order_id, and calls export_sales_order() to push the updated payment status.
export_delivery_note_on_update()
Fires when a Delivery Note is submitted. It finds the linked Sales Order from the Delivery Note items and callsexport_sales_order(), updating Medusa with the new order status (which will reflect partial or full delivery).
handle_payment_entry()
Fires onafter_insert, on_update, and on_submit of a Payment Entry. It finds all Sales Invoices referenced in the Payment Entry, checks whether each invoice has a medusa_order_id, and if so calls export_sales_invoice_on_update() to push the updated payment status.
Selling price validation bypass
ERPNext’s standardSalesOrder.validate_selling_price() rejects orders where item rates fall below the last purchase or valuation rate. Since Medusa-sourced orders may carry negotiated or pre-approved rates, the integration overrides this with CustomSalesOrder:
from_ecommerce flag is set to 1 on Quotations created via create_quotation() and propagated automatically to Sales Invoices and Delivery Notes via set_ecommerce_details_from_sales_order().
validate_medusa_order_id() runs before_insert on Sales Orders. If the Sales Order comes from an ecommerce Quotation but medusa_order_id is not yet set, it looks up the Quotation linked in the first item’s prevdoc_docname and copies the ID over automatically.