Search for a command to run...
This page introduces the core concepts behind the Integration Module: the roles involved, the descriptor at its center, and how an integration's options flow from configuration to runtime and into the admin UI. Later pages turn each idea into a step-by-step guide.
An integration involves two developer roles, with the store admin between them.
The provider and the consumer are usually the same package. A payment plugin declares its credentials as an integration, then reads them back in its payment logic. A consumer can also be unrelated code, such as an API route, a subscriber, or a scheduled job, that needs a configured integration's options.
A descriptor is a single declaration of an integration's metadata, options, settings sections, validation, and an optional connection test. You create it with .
For example:
providers/integration-acme/services/acme-integration.ts1import { defineIntegration, AbstractIntegrationProvider } from "@gorgo/medusa-integration"23const descriptor = defineIntegration({4 category: "payment",5 displayName: "acme.name",6 options: {7 apiKey: {8 type: "string",9 control: "secret",10 secret: true,11 required: true,12 label: "acme.apiKey"13 },14 sandbox: {15 type: "boolean",16 control: "switch",17 default: false,18 label: "acme.sandbox"19 },20 },21 sections: [22 {23 id: "credentials",24 title: "acme.credentials",25 options: ["apiKey", "sandbox"]26 },27 ],28})2930export class AcmeIntegration extends AbstractIntegrationProvider {31 static identifier = "acme"3233 get descriptor() {34 return descriptor35 }36}
The descriptor is the source of truth for the integration. The module uses it to generate the admin CRUD API, validate writes, render the settings UI, and define what consumers resolve at runtime. You never write data models, routes, or forms.
The Integration Module is provider-agnostic. It does not care what the options are for.
If a store admin should be able to manage a setting, it can be an integration.
Every integration has a stable identifier, such as , set as the provider's . Each registration is keyed by a of the form:
A consumer resolves options by identifier and instance, so the same code can target the right one.
An integration's options move through a predictable path. An author declares them in the descriptor, an admin configures them, the module validates them, they become live once the integration is enabled and complete, and a consumer resolves them at runtime. A connection test can check them against the third-party service along the way.
The module generates the admin CRUD API from the descriptor and validates every write. Validation covers per-option rules, such as types, ranges, and patterns, along with cross-section rules that span the whole configuration. There is nothing to build for each integration.
Options become live only when the integration is both enabled and complete, meaning it passes full validation. An incomplete draft or a disabled integration never resolves, so half-finished configuration cannot leak into runtime.
Options marked are encrypted at rest with AES-256-GCM and never reach the browser. The admin API masks them and reports only whether each one is set. Saving a secret as blank keeps its stored value instead of clearing it.
A descriptor can declare an optional connection test that checks credentials against the third-party service. Admins run it on demand, and a scheduled job re-checks configured integrations periodically.
Consumers read typed, validated, and decrypted options, with descriptor defaults applied. An incomplete or disabled integration resolves to nothing rather than partial data. Resolved options are cached briefly and refreshed whenever the configuration changes.
The module generates the admin UI for an integration from its descriptor, so there are no pages to build.
Options are grouped into settings sections and rendered with Medusa's LayoutComposer as reorderable cards, in a single- or two-column layout.
When the generated Admin UI is not enough, you can build any UI for your options with custom admin widgets. These are standard Medusa admin widgets built on the same and injection-zone mechanism you already use elsewhere, so there's nothing new to learn. The module exposes injection zones on each integration's page (for example ), and a widget targeting one of them receives the resolved and reads and writes the integration's options directly.
Descriptor labels, hints, and titles are i18n keys. Ship translations with your integration and the settings UI is localized automatically.
This builds on Medusa's standard admin i18n, so there's nothing new to learn. Register your translations the usual way and the keys resolve against the admin's active language, falling back to English when a key is missing. Custom widgets localize the same way, using the same message catalog as the generated form.