dist/codex/medusa-commerce/skills/medusa-fulfillment/SKILL.md
Implement Medusa v2 fulfillment — fulfillment module, provider interface, shipping options, fulfillment sets, shipping profiles, and multi-warehouse support. Use when adding fulfillment providers.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins medusa-fulfillmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fetch live docs:
site:docs.medusajs.com fulfillment module for fulfillment data model and service methodssite:docs.medusajs.com fulfillment provider for the provider abstraction interfacesite:docs.medusajs.com shipping option for shipping option configurationhttps://docs.medusajs.com/resources/references/fulfillment and review the IFulfillmentModuleService interfacemedusajs v2 AbstractFulfillmentProviderService 2026 for latest provider interface| Entity | Contains | Key Fields |
|--------|----------|------------|
| FulfillmentSet | ServiceZones, Fulfillments | name, type (shipping, pick-up) |
| ServiceZone | GeoZones, ShippingOptions | Geographic area with shipping config |
| ShippingOption | Rules | name, price_type, provider_id, type |
| GeoZone | — | country, province, city, zip |
| Fulfillment | Items, Labels | tracking_numbers, packed/shipped/delivered_at |
| StockLocation | Link to FulfillmentSet | Warehouse connection |
Fulfillment Module ──link──> Stock Location Module (warehouse)
Fulfillment Module ──link──> Cart Module (shipping methods)
Fulfillment Module ──link──> Order Module (order fulfillments)
Fetch live docs for exact link definitions and how fulfillment sets connect to stock locations.
All providers extend AbstractFulfillmentProviderService:
// Skeleton: custom fulfillment provider
// Fetch live docs for AbstractFulfillmentProviderService
class MyShippingProvider extends AbstractFulfillmentProviderService {
// Implement: validateFulfillmentData, calculatePrice,
// createFulfillment, cancelFulfillment
// Fetch live docs for exact method signatures
}
| Method | Purpose | Returns |
|--------|---------|---------|
| validateFulfillmentData | Validate shipping data at checkout | Validated data |
| validateOption | Validate shipping option config | Boolean |
| canCalculate | Whether provider supports dynamic pricing | Boolean |
| calculatePrice | Calculate shipping cost dynamically | Price amount |
| createFulfillment | Create fulfillment (generate label) | Fulfillment data |
| cancelFulfillment | Cancel an existing fulfillment | void |
| getFulfillmentDocuments | Get shipping labels/documents | Document URLs |
| createReturnFulfillment | Create return shipment | Return data |
Fetch live docs for exact method signatures, input types, and expected return shapes.
Shipping options reference a ShippingOptionType entity with a label and code. Types are configurable — common patterns include "express", "standard", "economy". The is_return rule on a shipping option determines if it applies to returns.
Fetch live docs for how
ShippingOptionTypeentities are created and linked.
| Price Type | Description |
|------------|-------------|
| flat_rate | Fixed price defined in shipping option |
| calculated | Dynamic price calculated by provider at checkout |
| Rule Attribute | Example | Description |
|----------------|---------|-------------|
| enabled_in_store | true | Visible to customers |
| is_return | false | Available for returns |
| custom attributes | varies | Provider-specific criteria |
Fetch live docs for the full list of rule attributes and how to create custom rules.
| Concept | Description | |---------|-------------| | Fulfillment Set | Named group of service zones linked to a stock location | | Service Zone | Geographic area with associated shipping options | | Geo Zone | Specific geographic boundary | | Stock Location Link | Connects fulfillment set to a warehouse |
| Type | Scope | Example |
|------|-------|---------|
| country | Entire country | country_code: "US" |
| province | State/province | province_code: "CA" |
| city | City | city: "San Francisco" |
| zip | Postal code range | postal_expression: "941*" |
| Concept | Description | |---------|-------------| | Shipping Profile | Links product types to shipping options | | Default Profile | Applies to products without explicit assignment | | Custom Profiles | For oversized, fragile, or special-handling items |
| Entity | Key Fields | |--------|------------| | StockLocation | name, address, FulfillmentSet (link) | | InventoryItem | stocked_quantity, reserved_quantity, incoming_quantity |
Each InventoryItem tracks stock per variant per location.
| Strategy | Description | |----------|-------------| | Nearest warehouse | Ship from closest location to customer | | Inventory priority | Ship from location with highest stock | | Manual selection | Admin selects fulfillment location |
Fetch live docs for stock location module service methods and inventory allocation strategies.
Created ──> Packed ──> Shipped ──> Delivered
└─> Return (if needed)
| Workflow | Purpose |
|----------|---------|
| createFulfillmentWorkflow | Create fulfillment for order items |
| cancelFulfillmentWorkflow | Cancel a pending fulfillment |
| createShipmentWorkflow | Add tracking and mark shipped |
| markFulfillmentAsDeliveredWorkflow | Mark as delivered |
| Operation | Method |
|-----------|--------|
| Create fulfillment set | fulfillmentModuleService.createFulfillmentSets() |
| Create service zone | fulfillmentModuleService.createServiceZones() |
| Create shipping option | fulfillmentModuleService.createShippingOptions() |
| List shipping options | fulfillmentModuleService.listShippingOptions() |
| Create fulfillment | fulfillmentModuleService.createFulfillment() |
AbstractFulfillmentProviderService — do not implement from scratchcalculatePrice accurately — it directly affects checkout totalsflat_rate and calculated options — flat rate for simplicity, calculated for accuracydata fieldFetch the Medusa v2 fulfillment module documentation and provider interface references for exact method signatures, shipping option configuration, and multi-warehouse patterns before implementing.
development
Build with Spree's headless Next.js storefront — the official `spree/storefront` repo (Next.js 16 App Router with Server Actions and Turbopack, React 19 Server Components, Tailwind CSS 4, TypeScript 5, `@spree/sdk`, Sentry), server-only auth (httpOnly JWT cookies + publishable key), MeiliSearch faceted catalog, one-page checkout with Apple/Google Pay/Klarna/Affirm/SEPA, multi-region market routing, GA4 + JSON-LD SEO, and Vercel/Docker deployment. Use when forking or customizing the storefront, or evaluating headless adoption.
tools
Build Spree extensions as Rails engines — gem scaffolding, `bin/rails g spree:extension`, mounting routes/migrations/assets, the modern `prepend` decorator pattern (`*_decorator.rb` with `self.prepended(base)`), generators (`spree:model_decorator`, `spree:controller_decorator`), the four customization surfaces in preference order (Events > Webhooks > Dependencies > Decorators), Spree::Dependencies for swapping service objects, gem release/versioning, and the deprecated Deface engine. Use when building a reusable Spree extension or adding non-trivial customization to an app.
development
Build with Spree's event bus and Webhooks 2.0 — `Spree::Events` publication, `Spree::Subscriber` DSL with `subscribes_to` and `on`, wildcard matching, lifecycle events (`{model}.created/.updated/.deleted` via `publishes_lifecycle_events`), the canonical event catalog (order.*, payment.*, shipment.*, product.*), Webhooks 2.0 endpoints, HMAC-SHA256 signing (`X-Spree-Webhook-Signature`), exponential-backoff retries, and Sidekiq job orchestration. Use when wiring event-driven business logic, building webhook consumers, or replacing ActiveSupport callback chains.
tools
Cross-cutting Spree development patterns — the customization preference hierarchy (Events > Webhooks > Dependencies > Decorators), `Spree::Dependencies` service-object swapping, the `_decorator.rb` + `prepend` + `self.prepended` idiom, idempotent subscribers and webhook receivers, multi-store scoping discipline, prefixed IDs, calculator polymorphism (shipping/promotion/tax share the base), service-object composition with `dry-monads` or simple results, why to avoid `class_eval` reopening and Deface, and Spree-on-Rails idioms (Hotwire/Turbo Stimulus, ActiveStorage, Action Cable, Sidekiq). Use when designing the architecture of a Spree extension or solving cross-cutting concerns.