Docs
July 31, 2026
Product

Announcing the Integration Module for Medusa

A new Medusa module that lets plugins declare their settings so store admins can configure them right in the Admin – no medusa-config edits and redeploys.

Announcing the Integration Module for Medusa

At Gorgo, we've spent the past year building Medusa plugins that connect stores to third-party services such as payment providers, ERPs, and fulfillment carriers. Across every one of them, the same friction kept surfacing: getting an integration configured. Credentials, modes, and webhooks lived in and environment variables, so every change meant editing code and shipping a redeploy, and each plugin had to build its own settings screen from scratch.

Today we're announcing the Integration Module – a Medusa module that removes both chores. A plugin declares its settings once, and store admins configure them from a generated form in the Admin, with no edits, no redeploys, and secrets encrypted at rest.

The problem with plugin settings today

Configuring a Medusa plugin usually comes down to two chores, and both are more painful than they should be.

  • Settings live in and env vars: Every change (a new API key, switching from test to live) needs code access and a full redeploy, and secrets sit in plaintext.
  • Building a settings UI is a project of its own: A proper configuration experience means forms and modals, validation, API routes, and workflows, all written and maintained separately for every plugin.

Introducing the Integration Module

The Integration Module moves plugin settings out of code and into the Admin and the database. A plugin describes the settings it needs, a store admin fills in a form under Settings → Integrations, and at runtime the plugin reads a ready, validated, decrypted config.

As an author, you only describe the form. The module handles the UI, storage, encryption, and validation for you. And when a plugin needs something the generated form can't express, you can drop in a custom widget.

How it works

You declare a descriptor with that lists your options and their types, the sections they group into, and any validation rules. From that single declaration, the Admin generates the settings form: the right control for each field, validation, conditional visibility, and masked secrets. There's no UI to build.

A minimal provider is a descriptor plus the class that ships it:

src/providers/integration-acme/services/acme.ts
1import { AbstractIntegrationProvider, defineIntegration } from "@gorgo/medusa-integration"
2
3const descriptor = defineIntegration({
4 category: "payment",
5 displayName: "acme.name",
6 supportsMultipleInstances: true,
7 options: {
8 apiKey: {
9 type: "string",
10 required: true,
11 secret: true,
12 label: "acme.fields.apiKey",
13 },
14 mode: {
15 type: "enum",
16 values: ["test", "live"],
17 default: "test",
18 label: "acme.fields.mode",
19 },
20 },
21 sections: [
22 {
23 id: "credentials",
24 title: "acme.sections.credentials",
25 options: ["apiKey", "mode"]
26 },
27 ],
28 testConnection: async ({ options }) => {
29 const ok = await pingAcme(options.apiKey, options.mode)
30 return ok ? { status: "passed" } : { status: "failed", message: "Invalid API key" }
31 },
32})
33
34export class AcmeIntegrationProvider extends AbstractIntegrationProvider {
35 static identifier = "acme"
36 get descriptor() {
37 return descriptor
38 }
39}

Labels like are i18n keys, resolved from your plugin's translations.

Register the provider in : the integration module stores and encrypts its settings, and the consuming module (here, payments) reads them by matching .

medusa-config.ts
1module.exports = defineConfig({
2 plugins: [
3 {
4 resolve: "@acme/medusa-payment-acme",
5 options: {},
6 },
7 {
8 resolve: "@gorgo/medusa-integration",
9 options: {
10 encryptionKey: process.env.INTEGRATION_ENCRYPTION_KEY,
11 providers: [
12 {
13 resolve: "@acme/medusa-payment-acme/providers/integration-acme",
14 id: "acme-1",
15 },
16 ],
17 },
18 },
19 ],
20 modules: [
21 {
22 resolve: "@medusajs/medusa/payment",
23 options: {
24 providers: [
25 {
26 resolve: "@acme/medusa-payment-acme/providers/payment-acme",
27 id: "acme",
28 options: { id: "acme-1" }, // matches the integration provider id above
29 },
30 ],
31 },
32 },
33 ],
34})

At runtime, your plugin reads its configuration anywhere it runs with , and gets back a typed, decrypted object. Incomplete or disabled configurations never resolve, so a half-filled draft can't leak into production.

src/providers/payment-acme/services/acme.ts
1import { resolveIntegrationOptions } from "@gorgo/medusa-integration"
2
3const { apiKey, mode } = await resolveIntegrationOptions({ identifier: "acme" })

What you get

One descriptor gives your plugin a complete configuration experience:

  1. No-code configuration under Settings → Integrations, with no and no redeploys.
  2. Secrets encrypted at rest (AES-256-GCM), never sent to the browser.
  3. Rich option types and validation conditional visibility, read-only fields, and cross-field rules.
  4. Multiple instances of the same provider, for stores that run more than one account.
  5. A "Test connection" button right in the Admin.
  6. Custom widgets when you need UI beyond the generated form.
  7. Typed, decrypted config resolved at runtime.

For plugin authors

If you already maintain a Medusa plugin, adopting the module is mostly mechanical: move your existing options into a descriptor, and read them with where you currently read env vars. We migrated all of our own providers this way (payments, ERP, and fulfillment), and you can browse the complete setup in the all-integrations example.

The step-by-step guide walks through it end to end.

Discover integrations in the Admin

The module also ships a Browse catalog inside the Admin. Store admins discover available integrations and add them without touching code. Because the settings UI is generated, your plugin shows up with a clean, native interface, consistent with the rest of the dashboard.

Discover integrations in the Admin

Getting started

Install the module:

npm install @gorgo/medusa-integration

From there, register your providers and declare their settings. The full installation and usage guide is in the documentation, and the source is on GitHub.

What's next

The Integration Module is in beta, and we're actively expanding it: more built-in integrations and a growing catalog. If you maintain a Medusa plugin, we'd love to help you migrate it. If you run a Medusa store, give it a try and tell us what's missing. Join the conversation in our Telegram community. Issues and Pull Requests are always welcome on GitHub.