> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/medusajs/medusa/llms.txt
> Use this file to discover all available pages before exploring further.

# Fulfillment Module

> Learn about the Fulfillment Module and how to manage shipping options, fulfillments, and delivery logistics in Medusa.

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

<ResponseField name="id" type="string" required>
  Unique shipping profile identifier
</ResponseField>

<ResponseField name="name" type="string" required>
  Profile name (e.g., "Standard Products", "Fragile Items")
</ResponseField>

<ResponseField name="type" type="string" required>
  Profile type: `default`, `gift_card`, `custom`
</ResponseField>

### ServiceZone

Defines a shipping service area with associated shipping options.

<ResponseField name="id" type="string" required>
  Unique service zone identifier
</ResponseField>

<ResponseField name="name" type="string" required>
  Service zone name
</ResponseField>

<ResponseField name="fulfillment_set_id" type="string" required>
  ID of the parent fulfillment set
</ResponseField>

<ResponseField name="geo_zones" type="GeoZone[]">
  Geographic areas covered by this zone
</ResponseField>

<ResponseField name="shipping_options" type="ShippingOption[]">
  Available shipping options in this zone
</ResponseField>

### GeoZone

Defines a geographic area within a service zone.

<ResponseField name="id" type="string" required>
  Unique geo zone identifier
</ResponseField>

<ResponseField name="type" type="string" required>
  Zone type: `country`, `province`, `city`, `zip`
</ResponseField>

<ResponseField name="country_code" type="string" required>
  Two-letter ISO country code
</ResponseField>

<ResponseField name="province_code" type="string">
  Province or state code
</ResponseField>

<ResponseField name="city" type="string">
  City name
</ResponseField>

<ResponseField name="postal_expression" type="string">
  Regex pattern for postal codes
</ResponseField>

<ResponseField name="service_zone_id" type="string" required>
  ID of the parent service zone
</ResponseField>

### ShippingOption

Represents a shipping method available to customers.

<ResponseField name="id" type="string" required>
  Unique shipping option identifier
</ResponseField>

<ResponseField name="name" type="string" required>
  Shipping option name (e.g., "Express Shipping")
</ResponseField>

<ResponseField name="service_zone_id" type="string" required>
  ID of the service zone
</ResponseField>

<ResponseField name="shipping_profile_id" type="string" required>
  ID of the shipping profile
</ResponseField>

<ResponseField name="provider_id" type="string" required>
  Fulfillment provider ID (e.g., "manual", "shippo")
</ResponseField>

<ResponseField name="shipping_option_type_id" type="string" required>
  ID of the shipping option type
</ResponseField>

<ResponseField name="data" type="object">
  Provider-specific configuration data
</ResponseField>

<ResponseField name="rules" type="ShippingOptionRule[]">
  Rules for pricing and availability
</ResponseField>

### ShippingOptionRule

Defines conditions and pricing for shipping options.

<ResponseField name="id" type="string" required>
  Unique rule identifier
</ResponseField>

<ResponseField name="shipping_option_id" type="string" required>
  ID of the shipping option
</ResponseField>

<ResponseField name="attribute" type="string" required>
  Rule attribute (e.g., "total", "weight", "quantity")
</ResponseField>

<ResponseField name="operator" type="string" required>
  Comparison operator: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`
</ResponseField>

<ResponseField name="value" type="string | number">
  Rule value to compare against
</ResponseField>

### Fulfillment

Tracks order fulfillment.

<ResponseField name="id" type="string" required>
  Unique fulfillment identifier
</ResponseField>

<ResponseField name="location_id" type="string" required>
  Stock location fulfilling the items
</ResponseField>

<ResponseField name="provider_id" type="string" required>
  Fulfillment provider ID
</ResponseField>

<ResponseField name="shipping_option_id" type="string">
  ID of the shipping option used
</ResponseField>

<ResponseField name="data" type="object">
  Provider-specific fulfillment data
</ResponseField>

<ResponseField name="shipped_at" type="DateTime">
  When fulfillment was shipped
</ResponseField>

<ResponseField name="delivered_at" type="DateTime">
  When fulfillment was delivered
</ResponseField>

<ResponseField name="canceled_at" type="DateTime">
  When fulfillment was canceled
</ResponseField>

<ResponseField name="items" type="FulfillmentItem[]">
  Items in this fulfillment
</ResponseField>

<ResponseField name="labels" type="FulfillmentLabel[]">
  Shipping labels
</ResponseField>

### FulfillmentSet

Organizes fulfillment configuration.

<ResponseField name="id" type="string" required>
  Unique fulfillment set identifier
</ResponseField>

<ResponseField name="name" type="string" required>
  Fulfillment set name
</ResponseField>

<ResponseField name="type" type="string" required>
  Set type: `pickup`, `shipping`
</ResponseField>

<ResponseField name="service_zones" type="ServiceZone[]">
  Service zones in this set
</ResponseField>

## Service Interface

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

### Create Shipping Profile

Create a shipping profile for products.

<CodeGroup>
  ```typescript Example theme={null}
  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 })
  }
  ```
</CodeGroup>

<ParamField path="data" type="CreateShippingProfileDTO" required>
  Shipping profile data

  <ParamField path="name" type="string" required>
    Profile name
  </ParamField>

  <ParamField path="type" type="string" required>
    Profile type: `default`, `gift_card`, `custom`
  </ParamField>
</ParamField>

### Create Fulfillment Set

Create a fulfillment set with service zones.

<CodeGroup>
  ```typescript Example theme={null}
  const fulfillmentSet = await fulfillmentModuleService.createFulfillmentSets({
    name: "US Shipping",
    type: "shipping",
    service_zones: [
      {
        name: "US East Coast",
        geo_zones: [
          {
            type: "country",
            country_code: "us",
          },
        ],
      },
    ],
  })
  ```
</CodeGroup>

<ParamField path="data" type="CreateFulfillmentSetDTO" required>
  Fulfillment set data

  <ParamField path="name" type="string" required>
    Fulfillment set name
  </ParamField>

  <ParamField path="type" type="string" required>
    Set type: `pickup`, `shipping`
  </ParamField>

  <ParamField path="service_zones" type="CreateServiceZoneDTO[]">
    Service zones to create
  </ParamField>
</ParamField>

### Create Service Zone

Create a service zone with geographic coverage.

<CodeGroup>
  ```typescript Example theme={null}
  const serviceZone = await fulfillmentModuleService.createServiceZones({
    name: "California",
    fulfillment_set_id: "fset_123",
    geo_zones: [
      {
        type: "province",
        country_code: "us",
        province_code: "CA",
      },
    ],
  })
  ```
</CodeGroup>

### Create Geo Zone

Define a geographic area.

<CodeGroup>
  ```typescript Country Level theme={null}
  const geoZone = await fulfillmentModuleService.createGeoZones({
    type: "country",
    country_code: "us",
    service_zone_id: "sz_123",
  })
  ```

  ```typescript Province Level theme={null}
  const geoZone = await fulfillmentModuleService.createGeoZones({
    type: "province",
    country_code: "us",
    province_code: "CA",
    service_zone_id: "sz_123",
  })
  ```

  ```typescript Postal Code Pattern theme={null}
  const geoZone = await fulfillmentModuleService.createGeoZones({
    type: "zip",
    country_code: "us",
    postal_expression: "^94", // ZIP codes starting with 94
    service_zone_id: "sz_123",
  })
  ```
</CodeGroup>

### Create Shipping Option

Create a shipping method with rules.

<CodeGroup>
  ```typescript Example theme={null}
  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
      },
    ],
  })
  ```
</CodeGroup>

<ParamField path="data" type="CreateShippingOptionDTO" required>
  Shipping option data

  <ParamField path="name" type="string" required>
    Shipping option name
  </ParamField>

  <ParamField path="service_zone_id" type="string" required>
    ID of the service zone
  </ParamField>

  <ParamField path="shipping_profile_id" type="string" required>
    ID of the shipping profile
  </ParamField>

  <ParamField path="provider_id" type="string" required>
    Fulfillment provider ID
  </ParamField>

  <ParamField path="rules" type="CreateShippingOptionRuleDTO[]">
    Pricing and availability rules
  </ParamField>
</ParamField>

### List Shipping Options for Context

Find available shipping options for an address.

<CodeGroup>
  ```typescript Example theme={null}
  const shippingOptions = await fulfillmentModuleService.listShippingOptionsForContext(
    {
      address: {
        country_code: "us",
        province_code: "CA",
        postal_code: "94102",
      },
      context: {
        total: 7500,
        weight: 2000,
      },
    },
    {
      relations: ["rules"],
    }
  )
  ```
</CodeGroup>

<ParamField path="filters" type="FilterableShippingOptionForContextProps" required>
  Context filters

  <ParamField path="address" type="object">
    Shipping address to match against geo zones
  </ParamField>

  <ParamField path="context" type="object">
    Values for rule evaluation (total, weight, quantity, etc.)
  </ParamField>
</ParamField>

### Create Fulfillment

Create a fulfillment for order items.

<CodeGroup>
  ```typescript Example theme={null}
  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
    },
  })
  ```
</CodeGroup>

<ParamField path="data" type="CreateFulfillmentDTO" required>
  Fulfillment data

  <ParamField path="location_id" type="string" required>
    Stock location ID
  </ParamField>

  <ParamField path="provider_id" type="string" required>
    Fulfillment provider ID
  </ParamField>

  <ParamField path="items" type="CreateFulfillmentItemDTO[]" required>
    Items to fulfill
  </ParamField>

  <ParamField path="shipping_option_id" type="string">
    ID of the shipping option
  </ParamField>

  <ParamField path="data" type="object">
    Provider-specific data
  </ParamField>
</ParamField>

### Create Shipping Labels

Generate shipping labels for fulfillment.

<CodeGroup>
  ```typescript Example theme={null}
  const labels = await fulfillmentModuleService.createFulfillmentLabels(
    "ful_123",
    {
      // Provider-specific label data
    }
  )
  ```
</CodeGroup>

### Update Fulfillment

Update fulfillment status.

<CodeGroup>
  ```typescript Mark as Shipped theme={null}
  const fulfillment = await fulfillmentModuleService.updateFulfillments(
    "ful_123",
    {
      shipped_at: new Date(),
    }
  )
  ```

  ```typescript Mark as Delivered theme={null}
  const fulfillment = await fulfillmentModuleService.updateFulfillments(
    "ful_123",
    {
      delivered_at: new Date(),
    }
  )
  ```
</CodeGroup>

### Cancel Fulfillment

Cancel an active fulfillment.

<CodeGroup>
  ```typescript Example theme={null}
  const fulfillment = await fulfillmentModuleService.cancelFulfillment("ful_123")
  ```
</CodeGroup>

## Integration Examples

### With Cart Module

Add shipping method to cart.

<CodeGroup>
  ```typescript Example theme={null}
  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,
  })
  ```
</CodeGroup>

### With Stock Location Module

Multi-location fulfillment.

<CodeGroup>
  ```typescript Example theme={null}
  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,
      })
    }
  }
  ```
</CodeGroup>

### With Order Module

Create fulfillments for orders.

<CodeGroup>
  ```typescript Example theme={null}
  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,
    })),
  })
  ```
</CodeGroup>

## Fulfillment Providers

Medusa supports multiple fulfillment providers:

### Manual Provider

Built-in provider for manual fulfillment processes.

<CodeGroup>
  ```typescript Example theme={null}
  const shippingOption = await fulfillmentModuleService.createShippingOptions({
    name: "Standard Shipping",
    provider_id: "manual",
    // ... other fields
  })
  ```
</CodeGroup>

### Shippo

<CodeGroup>
  ```typescript Install theme={null}
  npm install @medusajs/medusa-fulfillment-shippo
  ```

  ```typescript Configure theme={null}
  // medusa-config.js
  module.exports = {
    modules: [
      {
        resolve: "@medusajs/medusa-fulfillment-shippo",
        options: {
          api_key: process.env.SHIPPO_API_KEY,
        },
      },
    ],
  }
  ```
</CodeGroup>

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

## Related Modules

* [Cart Module](/modules/cart) - Add shipping methods to carts
* [Order Module](/modules/order) - Create order fulfillments
* [Stock Location Module](/modules/stock-location) - Multi-location fulfillment
* [Inventory Module](/modules/inventory) - Reserve inventory for fulfillments
* [Region Module](/modules/region) - Configure region fulfillment providers
