Command Palette

Search for a command to run...

Integration Provider Descriptor

An integration provider's descriptor is where you declare the integration's options, how they group into settings sections, their validation, and an optional connection test. This page is the full reference for every field you can put in one.

For the roles involved and how an option moves from the descriptor to a resolved value at runtime, see General Concepts.

defineIntegration

Create a descriptor with . It builds from your catalog, used for , defaults, and full validation.

providers/integration-my/services/my-integration.ts
1import { defineIntegration, AbstractIntegrationProvider } from "@gorgo/medusa-integration"
2
3const descriptor = defineIntegration({
4 category: "payment",
5 displayName: "my.name",
6 options: {
7 apiKey: {
8 type: "string",
9 control: "secret",
10 secret: true,
11 required: true,
12 label: "my.apiKey"
13 },
14 sandbox: {
15 type: "boolean",
16 control: "switch",
17 default: false,
18 label: "my.sandbox"
19 },
20 },
21 sections: [
22 {
23 id: "credentials",
24 title: "my.credentials",
25 options: ["apiKey", "sandbox"]
26 },
27 ],
28})
29
30export class MyIntegration extends AbstractIntegrationProvider {
31 static identifier = "my"
32
33 get descriptor() {
34 return descriptor
35 }
36}

This descriptor declares and , grouped into a single section. fails fast at load time in two cases: a section referencing an option id that isn't in , and an option whose mixes strings and numbers.

Option Fields

Each option in is an object shaped . The field determines the available values and the remaining fields that are common to every type:

Loading...

Type-Specific Fields

Some types have extra fields on top of the common ones:

  • : , ,
  • :
  • : , , , , ,
  • : ,
Loading...

Generated CRUD and Validation

The module generates the 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.

Cross-section rules are declared through the descriptor's . Unlike a single option's , it receives the whole assembled config and can flag an issue on any field:

providers/integration-my/services/my-integration.ts
1const descriptor = defineIntegration({
2 // ...
3 validate: (full, { addIssue }) => {
4 if (full.mode === "webhook" && !full.webhookSecret) {
5 addIssue({ path: ["webhookSecret"], message: "Required when mode is \"webhook\"" })
6 }
7 },
8})

Unlike or an option's own , this rule only runs during full validation (checking whether the integration is ready to be enabled), not when a single section is saved.

Enabled and Complete

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.

Secrets and Encryption

Options marked are encrypted at rest with AES-256-GCM and never reach the browser. The CRUD API masks them and reports only whether each one is set. Saving a secret as blank keeps its stored value instead of clearing it.

Encryption needs a key, set as when you register the module. See Integration Module Options for how to set it and what happens without one.

Connection Test

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 daily.

Add to the descriptor. It receives the already-resolved (decrypted) options and returns a status:

providers/integration-my/services/my-integration.ts
1const descriptor = defineIntegration({
2 // ...
3 testConnection: async ({ options }) => {
4 const res = await fetch("https://api.my.com/ping", {
5 headers: { Authorization: `Bearer ${options.apiKey}` },
6 })
7
8 if (!res.ok) {
9 return { status: "failed", message: `My responded with ${res.status}` }
10 }
11
12 return { status: "passed" }
13 },
14})

is one of , , or ; the optional is shown to the admin in the Admin next to the test result.

Runtime Options Resolution

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.

References

Edited Aug 21, 2026·Edit this page