Skip to main content

Overview

The Fulfillment Module manages shipping and delivery operations including shipping profiles, service zones, geographic zones, shipping options with rule-based pricing, and fulfillment tracking. It provides a flexible system for configuring complex shipping scenarios. Key Features:
  • Shipping profile management
  • Service zones with geographic coverage
  • Rule-based shipping options
  • Multi-provider fulfillment support
  • Fulfillment tracking and labeling
  • Dynamic shipping calculations
  • Fulfillment set organization

When to Use

Use the Fulfillment Module when you need to:
  • Configure shipping options for products
  • Define geographic shipping zones
  • Calculate shipping costs based on rules (weight, price, etc.)
  • Manage multiple fulfillment providers
  • Create and track fulfillments
  • Generate shipping labels
  • Handle multi-location shipping
  • Support pickup and delivery options

Data Models

ShippingProfile

Groups products with similar shipping requirements.
id
string
required
Unique shipping profile identifier
name
string
required
Profile name (e.g., “Standard Products”, “Fragile Items”)
type
string
required
Profile type: default, gift_card, custom

ServiceZone

Defines a shipping service area with associated shipping options.
id
string
required
Unique service zone identifier
name
string
required
Service zone name
fulfillment_set_id
string
required
ID of the parent fulfillment set
geo_zones
GeoZone[]
Geographic areas covered by this zone
shipping_options
ShippingOption[]
Available shipping options in this zone

GeoZone

Defines a geographic area within a service zone.
id
string
required
Unique geo zone identifier
type
string
required
Zone type: country, province, city, zip
country_code
string
required
Two-letter ISO country code
province_code
string
Province or state code
city
string
City name
postal_expression
string
Regex pattern for postal codes
service_zone_id
string
required
ID of the parent service zone

ShippingOption

Represents a shipping method available to customers.
id
string
required
Unique shipping option identifier
name
string
required
Shipping option name (e.g., “Express Shipping”)
service_zone_id
string
required
ID of the service zone
shipping_profile_id
string
required
ID of the shipping profile
provider_id
string
required
Fulfillment provider ID (e.g., “manual”, “shippo”)
shipping_option_type_id
string
required
ID of the shipping option type
data
object
Provider-specific configuration data
rules
ShippingOptionRule[]
Rules for pricing and availability

ShippingOptionRule

Defines conditions and pricing for shipping options.
id
string
required
Unique rule identifier
shipping_option_id
string
required
ID of the shipping option
attribute
string
required
Rule attribute (e.g., “total”, “weight”, “quantity”)
operator
string
required
Comparison operator: eq, ne, gt, gte, lt, lte, in
value
string | number
Rule value to compare against

Fulfillment

Tracks order fulfillment.
id
string
required
Unique fulfillment identifier
location_id
string
required
Stock location fulfilling the items
provider_id
string
required
Fulfillment provider ID
shipping_option_id
string
ID of the shipping option used
data
object
Provider-specific fulfillment data
shipped_at
DateTime
When fulfillment was shipped
delivered_at
DateTime
When fulfillment was delivered
canceled_at
DateTime
When fulfillment was canceled
items
FulfillmentItem[]
Items in this fulfillment
labels
FulfillmentLabel[]
Shipping labels

FulfillmentSet

Organizes fulfillment configuration.
id
string
required
Unique fulfillment set identifier
name
string
required
Fulfillment set name
type
string
required
Set type: pickup, shipping
service_zones
ServiceZone[]
Service zones in this set

Service Interface

The Fulfillment Module service is available at @medusajs/medusa/fulfillment.

Create Shipping Profile

Create a shipping profile for products.
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { IFulfillmentModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"

export async function POST(
  req: MedusaRequest,
  res: MedusaResponse
) {
  const fulfillmentModuleService: IFulfillmentModuleService = req.scope.resolve(
    Modules.FULFILLMENT
  )

  const shippingProfile = await fulfillmentModuleService.createShippingProfiles({
    name: "Heavy Items",
    type: "custom",
  })

  res.json({ shipping_profile: shippingProfile })
}
data
CreateShippingProfileDTO
required
Shipping profile data
name
string
required
Profile name
type
string
required
Profile type: default, gift_card, custom

Create Fulfillment Set

Create a fulfillment set with service zones.
const fulfillmentSet = await fulfillmentModuleService.createFulfillmentSets({
  name: "US Shipping",
  type: "shipping",
  service_zones: [
    {
      name: "US East Coast",
      geo_zones: [
        {
          type: "country",
          country_code: "us",
        },
      ],
    },
  ],
})
data
CreateFulfillmentSetDTO
required
Fulfillment set data
name
string
required
Fulfillment set name
type
string
required
Set type: pickup, shipping
service_zones
CreateServiceZoneDTO[]
Service zones to create

Create Service Zone

Create a service zone with geographic coverage.
const serviceZone = await fulfillmentModuleService.createServiceZones({
  name: "California",
  fulfillment_set_id: "fset_123",
  geo_zones: [
    {
      type: "province",
      country_code: "us",
      province_code: "CA",
    },
  ],
})

Create Geo Zone

Define a geographic area.
const geoZone = await fulfillmentModuleService.createGeoZones({
  type: "country",
  country_code: "us",
  service_zone_id: "sz_123",
})

Create Shipping Option

Create a shipping method with rules.
const shippingOption = await fulfillmentModuleService.createShippingOptions({
  name: "Express Shipping",
  service_zone_id: "sz_123",
  shipping_profile_id: "sp_standard",
  provider_id: "manual",
  shipping_option_type_id: "sot_express",
  data: {
    // Provider-specific data
  },
  rules: [
    {
      attribute: "total",
      operator: "gte",
      value: "5000", // Free shipping over $50
    },
  ],
})
data
CreateShippingOptionDTO
required
Shipping option data
name
string
required
Shipping option name
service_zone_id
string
required
ID of the service zone
shipping_profile_id
string
required
ID of the shipping profile
provider_id
string
required
Fulfillment provider ID
rules
CreateShippingOptionRuleDTO[]
Pricing and availability rules

List Shipping Options for Context

Find available shipping options for an address.
const shippingOptions = await fulfillmentModuleService.listShippingOptionsForContext(
  {
    address: {
      country_code: "us",
      province_code: "CA",
      postal_code: "94102",
    },
    context: {
      total: 7500,
      weight: 2000,
    },
  },
  {
    relations: ["rules"],
  }
)
filters
FilterableShippingOptionForContextProps
required
Context filters
address
object
Shipping address to match against geo zones
context
object
Values for rule evaluation (total, weight, quantity, etc.)

Create Fulfillment

Create a fulfillment for order items.
const fulfillment = await fulfillmentModuleService.createFulfillment({
  location_id: "sloc_warehouse",
  provider_id: "manual",
  shipping_option_id: "so_express",
  items: [
    {
      line_item_id: "item_123",
      quantity: 2,
    },
  ],
  data: {
    // Provider-specific data
  },
})
data
CreateFulfillmentDTO
required
Fulfillment data
location_id
string
required
Stock location ID
provider_id
string
required
Fulfillment provider ID
items
CreateFulfillmentItemDTO[]
required
Items to fulfill
shipping_option_id
string
ID of the shipping option
data
object
Provider-specific data

Create Shipping Labels

Generate shipping labels for fulfillment.
const labels = await fulfillmentModuleService.createFulfillmentLabels(
  "ful_123",
  {
    // Provider-specific label data
  }
)

Update Fulfillment

Update fulfillment status.
const fulfillment = await fulfillmentModuleService.updateFulfillments(
  "ful_123",
  {
    shipped_at: new Date(),
  }
)

Cancel Fulfillment

Cancel an active fulfillment.
const fulfillment = await fulfillmentModuleService.cancelFulfillment("ful_123")

Integration Examples

With Cart Module

Add shipping method to cart.
import { Modules } from "@medusajs/framework/utils"

const fulfillmentModule = container.resolve(Modules.FULFILLMENT)
const cartModule = container.resolve(Modules.CART)

// Get cart
const cart = await cartModule.retrieveCart("cart_123", {
  relations: ["shipping_address"],
})

// Find available shipping options
const shippingOptions = await fulfillmentModule.listShippingOptionsForContext(
  {
    address: cart.shipping_address,
    context: {
      total: cart.total,
    },
  }
)

// Add shipping method to cart
await cartModule.createShippingMethods({
  cart_id: cart.id,
  name: shippingOptions[0].name,
  amount: 500,
  shipping_option_id: shippingOptions[0].id,
})

With Stock Location Module

Multi-location fulfillment.
import { Modules } from "@medusajs/framework/utils"

const stockLocationModule = container.resolve(Modules.STOCK_LOCATION)
const fulfillmentModule = container.resolve(Modules.FULFILLMENT)

// Get stock locations
const locations = await stockLocationModule.listStockLocations()

// Create fulfillments from different locations
for (const location of locations) {
  const itemsAtLocation = orderItems.filter(
    item => item.location_id === location.id
  )
  
  if (itemsAtLocation.length) {
    await fulfillmentModule.createFulfillment({
      location_id: location.id,
      provider_id: "manual",
      items: itemsAtLocation,
    })
  }
}

With Order Module

Create fulfillments for orders.
import { Modules } from "@medusajs/framework/utils"

const orderModule = container.resolve(Modules.ORDER)
const fulfillmentModule = container.resolve(Modules.FULFILLMENT)

// Get order
const order = await orderModule.retrieveOrder("order_123", {
  relations: ["items"],
})

// Create fulfillment
const fulfillment = await fulfillmentModule.createFulfillment({
  location_id: "sloc_warehouse",
  provider_id: "manual",
  items: order.items.map(item => ({
    line_item_id: item.id,
    quantity: item.quantity,
  })),
})

Fulfillment Providers

Medusa supports multiple fulfillment providers:

Manual Provider

Built-in provider for manual fulfillment processes.
const shippingOption = await fulfillmentModuleService.createShippingOptions({
  name: "Standard Shipping",
  provider_id: "manual",
  // ... other fields
})

Shippo

npm install @medusajs/medusa-fulfillment-shippo

Best Practices

  1. Shipping Profiles: Group products with similar shipping requirements (fragile, oversized, standard) into profiles.
  2. Service Zones: Structure zones hierarchically - start with broad zones (country), then narrow (province, city, ZIP).
  3. Rule-Based Pricing: Use rules to implement complex pricing:
    • Free shipping over certain total
    • Weight-based pricing
    • Quantity discounts
  4. Geo Zone Expressions: Use postal_expression with regex for flexible postal code matching (e.g., ^94 for San Francisco area).
  5. Multi-Location: Configure fulfillment sets per location for complex inventory scenarios.
  6. Provider Data: Store provider-specific configuration in the data field for flexibility.

Build docs developers (and LLMs) love