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.
Unique shipping profile identifier
Profile name (e.g., “Standard Products”, “Fragile Items”)
Profile type: default, gift_card, custom
ServiceZone
Defines a shipping service area with associated shipping options.
Unique service zone identifier
ID of the parent fulfillment set
Geographic areas covered by this zone
Available shipping options in this zone
GeoZone
Defines a geographic area within a service zone.
Unique geo zone identifier
Zone type: country, province, city, zip
Two-letter ISO country code
Regex pattern for postal codes
ID of the parent service zone
ShippingOption
Represents a shipping method available to customers.
Unique shipping option identifier
Shipping option name (e.g., “Express Shipping”)
ID of the shipping profile
Fulfillment provider ID (e.g., “manual”, “shippo”)
ID of the shipping option type
Provider-specific configuration data
Rules for pricing and availability
ShippingOptionRule
Defines conditions and pricing for shipping options.
ID of the shipping option
Rule attribute (e.g., “total”, “weight”, “quantity”)
Comparison operator: eq, ne, gt, gte, lt, lte, in
Rule value to compare against
Fulfillment
Tracks order fulfillment.
Unique fulfillment identifier
Stock location fulfilling the items
ID of the shipping option used
Provider-specific fulfillment data
When fulfillment was shipped
When fulfillment was delivered
When fulfillment was canceled
Items in this fulfillment
FulfillmentSet
Organizes fulfillment configuration.
Unique fulfillment set identifier
Set type: pickup, shipping
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 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 Set type: pickup, shipping
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.
Country Level
Province Level
Postal Code Pattern
const geoZone = await fulfillmentModuleService . createGeoZones ({
type: "country" ,
country_code: "us" ,
service_zone_id: "sz_123" ,
})
const geoZone = await fulfillmentModuleService . createGeoZones ({
type: "province" ,
country_code: "us" ,
province_code: "CA" ,
service_zone_id: "sz_123" ,
})
const geoZone = await fulfillmentModuleService . createGeoZones ({
type: "zip" ,
country_code: "us" ,
postal_expression: "^94" , // ZIP codes starting with 94
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 ID of the shipping profile
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 Shipping address to match against geo zones
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 items
CreateFulfillmentItemDTO[]
required
Items to fulfill
ID of the shipping option
Create Shipping Labels
Generate shipping labels for fulfillment.
const labels = await fulfillmentModuleService . createFulfillmentLabels (
"ful_123" ,
{
// Provider-specific label data
}
)
Update Fulfillment
Update fulfillment status.
Mark as Shipped
Mark as Delivered
const fulfillment = await fulfillmentModuleService . updateFulfillments (
"ful_123" ,
{
shipped_at: new Date (),
}
)
const fulfillment = await fulfillmentModuleService . updateFulfillments (
"ful_123" ,
{
delivered_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
// medusa-config.js
module . exports = {
modules: [
{
resolve: "@medusajs/medusa-fulfillment-shippo" ,
options: {
api_key: process . env . SHIPPO_API_KEY ,
},
},
],
}
Best Practices
Shipping Profiles : Group products with similar shipping requirements (fragile, oversized, standard) into profiles.
Service Zones : Structure zones hierarchically - start with broad zones (country), then narrow (province, city, ZIP).
Rule-Based Pricing : Use rules to implement complex pricing:
Free shipping over certain total
Weight-based pricing
Quantity discounts
Geo Zone Expressions : Use postal_expression with regex for flexible postal code matching (e.g., ^94 for San Francisco area).
Multi-Location : Configure fulfillment sets per location for complex inventory scenarios.
Provider Data : Store provider-specific configuration in the data field for flexibility.