e-conomic
Sync customers, orders, and invoices with e-conomic
medusa-plugin-economic-plus
A Medusa v2 plugin that keeps your store and your e-conomic agreement in sync — customers, products, draft invoices, and credit notes, with write-back from e-conomic and a dedicated admin console.
- Placed orders become draft invoices; accepted returns become credit notes
- Booked/edited invoices in e-conomic sync back into Medusa via webhooks
- Every sync is recorded, observable, and retriable from the admin
Features
- Customers → e-conomic — customers are created/updated with a stored identity map, so the same customer is never duplicated
- Products → e-conomic — variants sync as products, with base-currency and currency-specific prices, and optional VAT-inclusive netting
- Orders → draft invoices — VAT and sales account per line are resolved from the customer's VAT zone plus a tax-code → product-group mapping
- Returns → credit notes — an accepted return becomes a draft credit note referencing the original order
- Write-back — inbound webhooks sync booked/updated invoices and customer/product edits back into Medusa
- Resilient HTTP client — retry with backoff + jitter on 429/5xx, Copy to clipboard
Retry-Aftersupport, timeouts, pagination, and POSTs that are never blind-retried (so invoices are never duplicated) - Operations console — an admin page and per-entity widgets for sync status, retries, and push/pull on demand
- Nightly reconciliation — verifies booking status and flags entities deleted in e-conomic
- Fail-closed security — the webhook endpoint refuses all traffic until a shared secret is set, and compares tokens in constant time
Requirements
- Medusa v2 (Copy to clipboard
@medusajs/framework 2.13.5) - Node.js Copy to clipboard
>=20 - An e-conomic agreement with API access (an App Secret Token and an Agreement Grant Token)
- A publicly reachable backend URL (for write-back webhooks)
Installation
12npm install medusa-plugin-economic-plus# or: pnpm add medusa-plugin-economic-plus / yarn add medusa-plugin-economic-plus
Run migrations to create the plugin's tables:
1npx medusa db:migrate
Setup
Add the following environment variables:
123ECONOMIC_APP_SECRET_TOKEN=your_app_secret_tokenECONOMIC_AGREEMENT_GRANT_TOKEN=your_agreement_grant_tokenECONOMIC_WEBHOOK_SECRET=your_shared_secret # required for write-back
Then register the plugin in Copy to clipboardmedusa-config.ts:
12345678910111213141516171819import { defineConfig } from "@medusajs/framework/utils"module.exports = defineConfig({// ...plugins: [{resolve: "medusa-plugin-economic-plus",options: {appSecretToken: process.env.ECONOMIC_APP_SECRET_TOKEN,agreementGrantToken: process.env.ECONOMIC_AGREEMENT_GRANT_TOKEN,webhookSecret: process.env.ECONOMIC_WEBHOOK_SECRET,// optional tuning — see ConfigurationpaymentTermsNumber: 1,layoutNumber: 19,defaultProductGroupNumber: 1,},},],})
Options are validated on startup — invalid values throw a descriptive error before the server boots.
Finally, finish the mapping setup in Settings → E-conomic:
- VAT zones — map each customer country (or Copy to clipboard
*as a catch-all) to an e-conomic VAT zone. Exact rows win over Copy to clipboard*. - Tax code → product group — required for taxed invoice lines; a line with an unmapped tax code is rejected.
- Shipping product — the e-conomic product number shipping costs post to.
- Discount product — the e-conomic product number order discounts post to.
- Webhooks — set the secret, expose your backend, and register (see Webhooks).
Configuration
Required
Option Type Description Copy to clipboardappSecretToken Copy to clipboardstring e-conomic App Secret Token (Copy to clipboardX-AppSecretToken) Copy to clipboardagreementGrantToken Copy to clipboardstring e-conomic Agreement Grant Token (Copy to clipboardX-AgreementGrantToken)
Invoice & product defaults
Option Type Default Description Copy to clipboardpaymentTermsNumber Copy to clipboardint — Payment terms applied to draft invoices Copy to clipboardlayoutNumber Copy to clipboardint — Layout applied to draft invoices Copy to clipboardcustomerGroupNumber Copy to clipboardint — Customer group new customers are created in Copy to clipboardshippingProductNumber Copy to clipboardstring — Product number shipping lines post to Copy to clipboarddiscountProductNumber Copy to clipboardstring — Product number discount lines post to Copy to clipboarddefaultProductGroupNumber Copy to clipboardint Copy to clipboard1 Fallback group when a product syncs without tax context Copy to clipboarduntaxedProductGroupNumber Copy to clipboardint — Opt-in: group for lines with no tax code. Unset = reject them Copy to clipboardcatalogPricesTaxInclusive Copy to clipboardboolean Copy to clipboardfalse Set Copy to clipboardtrue if Medusa prices include VAT (e-conomic Copy to clipboardsalesPrice is ex-VAT) Copy to clipboardcatalogVatRate Copy to clipboardnumber Copy to clipboard25 VAT rate (%) used to net prices when the above is Copy to clipboardtrue
Sync, webhooks & networking
Option Type Default Description Copy to clipboardsyncCustomers / Copy to clipboardsyncProducts / Copy to clipboardsyncOrders Copy to clipboardboolean Copy to clipboardtrue Per-entity sync toggles Copy to clipboardwebhookSecret Copy to clipboardstring — Shared secret for inbound webhooks. Required for write-back Copy to clipboardbaseUrl Copy to clipboardstring (URL) Copy to clipboardhttps://restapi.e-conomic.com e-conomic REST API base URL Copy to clipboardmaxRetries Copy to clipboardint (0–10) Copy to clipboard3 Retries on transient (429/5xx) failures Copy to clipboardretryBaseDelayMs Copy to clipboardint (100–30k) Copy to clipboard500 Backoff base delay Copy to clipboardrequestTimeoutMs Copy to clipboardint (1k–120k) Copy to clipboard15000 Per-request timeout
Environment variables
Options can also be resolved from the environment:
Variable Maps to Copy to clipboardECONOMIC_APP_SECRET_TOKEN Copy to clipboardappSecretToken Copy to clipboardECONOMIC_AGREEMENT_GRANT_TOKEN Copy to clipboardagreementGrantToken Copy to clipboardECONOMIC_WEBHOOK_SECRET Copy to clipboardwebhookSecret Copy to clipboardECONOMIC_PAYMENT_TERMS_NUMBER Copy to clipboardpaymentTermsNumber Copy to clipboardECONOMIC_LAYOUT_NUMBER Copy to clipboardlayoutNumber Copy to clipboardECONOMIC_CUSTOMER_GROUP_NUMBER Copy to clipboardcustomerGroupNumber Copy to clipboardECONOMIC_SHIPPING_PRODUCT_NUMBER Copy to clipboardshippingProductNumber Copy to clipboardECONOMIC_DISCOUNT_PRODUCT_NUMBER Copy to clipboarddiscountProductNumber Copy to clipboardECONOMIC_DEFAULT_PRODUCT_GROUP_NUMBER Copy to clipboarddefaultProductGroupNumber Copy to clipboardECONOMIC_UNTAXED_PRODUCT_GROUP_NUMBER Copy to clipboarduntaxedProductGroupNumber Copy to clipboardECONOMIC_CATALOG_PRICES_TAX_INCLUSIVE Copy to clipboardcatalogPricesTaxInclusive Copy to clipboardECONOMIC_CATALOG_VAT_RATE Copy to clipboardcatalogVatRate Copy to clipboardECONOMIC_REQUEST_TIMEOUT_MS Copy to clipboardrequestTimeoutMs
How It Works
Subscribers react to Medusa events and call the module service, which talks to e-conomic through a typed HTTP client. Every sync is recorded in a mapping table (Copy to clipboardmedusa_id ↔ Copy to clipboardeconomic_id) with its status, so failures are visible, retriable, and reconcilable.
You do in Medusa In e-conomic Create / edit a customer Customer created or updated (never duplicated) Create / edit a product or variant Product created or updated with prices Place an order Draft invoice created Update / cancel an order Draft invoice updated or cancelled Accept a return Draft credit note created against the original order
The outbound flow is event-driven and idempotent; the inbound flow is webhook-driven.
Write-back
e-conomic event Effect in Medusa Copy to clipboardINVOICE_BOOKED Booked invoice data synced into order metadata Copy to clipboardINVOICE_UPDATED Updated invoice data synced into order metadata Copy to clipboardCUSTOMER_UPDATED Edits synced onto the matching Medusa customer Copy to clipboardPRODUCT_UPDATED Edits synced onto the matching Medusa product
Webhooks
e-conomic can't send admin JWTs or sign bodies, so the inbound endpoint is authenticated with a shared secret in the Copy to clipboardX-Economic-Webhook-Token header (Copy to clipboard?token= is accepted as a fallback), compared in constant time.
1POST /economic/webhook
If Copy to clipboardwebhookSecretis not configured, the endpoint rejects every request with Copy to clipboard503— no booked-invoice event is silently lost, and e-conomic will redeliver once you set it.
Register the webhooks once the secret and a public URL are in place:
12curl -X POST https://<your-backend>/admin/economic/webhooks \-H "Authorization: Bearer <admin-token>"
Status codes are chosen so e-conomic only redelivers transient failures: Copy to clipboard401 invalid token, Copy to clipboard400 bad payload (terminal), Copy to clipboard5xx retryable, Copy to clipboard200 handled or ignored.
Reconciliation
A scheduled job (Copy to clipboardeconomic-reconciliation, daily at 02:00) refreshes the booking status of synced invoices and flags mappings whose e-conomic entity no longer exists as stale. It never re-creates or mutates data — remediation stays a human decision, surfaced in the admin. Run it on demand with Copy to clipboardPOST /admin/economic/reconciliation.
Admin UI
- Settings → E-conomic — sync status overview, VAT-zone mappings, tax-code → product-group mappings, and shipping/discount product configuration.
- Order, Customer, and Product widgets — show the e-conomic sync status of the record you're viewing, with inline push/retry actions.
API Endpoints
All routes are under Copy to clipboard/admin/economic and require admin authentication.
Method Route Description Copy to clipboardGET Copy to clipboard/sync Aggregate sync status overview Copy to clipboardGET Copy to clipboard/settings Effective (non-secret) plugin settings Copy to clipboardGET · Copy to clipboardPOST Copy to clipboard/retry List retriable failures · retry them Copy to clipboardPOST Copy to clipboard/reconciliation Run reconciliation on demand Copy to clipboardPOST Copy to clipboard/webhooks Register e-conomic webhooks Copy to clipboardGET Copy to clipboard/vat-zones List e-conomic VAT zones Copy to clipboardGET · Copy to clipboardPOST Copy to clipboard/vat-zone-maps List · create country → VAT-zone mappings Copy to clipboardPUT · Copy to clipboardDELETE Copy to clipboard/vat-zone-maps/:id Update · delete a mapping Copy to clipboardGET · Copy to clipboardPOST Copy to clipboard/product-group-maps List · create tax-code → product-group mappings Copy to clipboardPUT · Copy to clipboardDELETE Copy to clipboard/product-group-maps/:id Update · delete a mapping Copy to clipboardGET · Copy to clipboardPUT Copy to clipboard/shipping-mapping Get · set the shipping product Copy to clipboardGET · Copy to clipboardPUT Copy to clipboard/discount-mapping Get · set the discount product Copy to clipboardGET · Copy to clipboardPOST Copy to clipboard/customers/status · Copy to clipboard/customers/push Customer status · push Copy to clipboardGET · Copy to clipboardPOST Copy to clipboard/products/status · Copy to clipboard/products/push · Copy to clipboard/products/pull Product status · push · pull Copy to clipboardGET · Copy to clipboardPOST Copy to clipboard/orders/status · Copy to clipboard/orders/push · Copy to clipboard/orders/pull · Copy to clipboard/orders/cancel Invoice status · push · pull · cancel Copy to clipboardGET Copy to clipboard/customers/failed · Copy to clipboard/products/failed · Copy to clipboard/orders/failed Failed syncs per entity
The public inbound endpoint is Copy to clipboardPOST /economic/webhook (no admin auth; secured by the shared secret).
Exports
1234567891011121314151617181920import {economicModule,ECONOMIC_MODULE,EconomicModuleService,EconomicClient,EconomicApiError,MappingService,ProductSyncService,InvoiceSyncService,ReturnSyncService,resolveEconomicOptions,resolveEconomicOptionsFromEnv,} from "medusa-plugin-economic-plus"import type {EconomicOptions,EconomicCustomer,EconomicProduct,EconomicDraftInvoice,MappingRecord,
Mapper helpers (Copy to clipboardtoEconomicCustomerCreate, Copy to clipboardtoEconomicDraftInvoice, Copy to clipboardtoEconomicCreditNote, …) are exported as well.
Development
12345npm installnpm run build # medusa plugin:buildnpm run dev # medusa plugin:developnpm run typecheck # tsc --noEmit (server + admin)npm test # 218 unit tests across 22 suites
A live end-to-end smoke test against the e-conomic sandbox is skipped by default; enable it with credentials:
1234ECONOMIC_E2E=1 \ECONOMIC_APP_SECRET_TOKEN=... \ECONOMIC_AGREEMENT_GRANT_TOKEN=... \npm test
License
MIT

