# Where to Find Medusa Workflow and API Route Implementations: A Complete Guide

> Discover production-ready Medusa workflow and API route implementations in the official medusajs/medusa repository. Learn practical patterns for creating workflows and API routes.

- Repository: [Medusa/medusa](https://github.com/medusajs/medusa)
- Tags: how-to-guide
- Published: 2026-05-19

---

**You can find production-ready Medusa workflow and API route implementations in the official `medusajs/medusa` repository under `packages/plugins/loyalty`, `packages/core/core-flows`, and `packages/medusa/src/api`, which demonstrate patterns using `createWorkflow`, `createStep`, and thin HTTP route wrappers.**

Medusa is an open-source ecommerce framework that uses a sophisticated **workflow engine** to handle complex business logic. Understanding where to locate real-world examples of Medusa workflow and API route implementations within the source code helps developers build custom commerce features correctly. This guide maps the essential file locations in the repository and breaks down the architectural patterns you will encounter.

## Understanding Medusa's Workflow Architecture

The **workflow engine** lives in `@medusajs/framework/workflows-sdk`. All concrete workflows are built using the `createWorkflow` helper (and its companion `createStep`), while API routes follow a thin-wrapper pattern in `packages/medusa/src/api`.

### Core Workflow Engine Location

The foundation of every workflow starts in [`packages/core/workflows-sdk/src/utils/composer/create-workflow.ts`](https://github.com/medusajs/medusa/blob/main/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts). This file exports `createWorkflow`, which accepts a unique identifier string and a function containing your business logic. Workflows return a `WorkflowResponse` instance that can register hooks and pass data between steps.

## Real-World Workflow Implementation Examples

The repository ships dozens of production-ready examples in the **plugins** and **core-flows** packages. These demonstrate how to structure multi-step operations with compensation logic.

### Store Credit Workflow Definition

The loyalty plugin provides a clear example of workflow composition. In [`packages/plugins/loyalty/src/workflows/store-credit/workflows/credit-store-credit-account.ts`](https://github.com/medusajs/medusa/blob/main/packages/plugins/loyalty/src/workflows/store-credit/workflows/credit-store-credit-account.ts), the workflow wraps business logic with hooks for extensibility:

```typescript
import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk"

export const creditStoreCreditAccountWorkflow = createWorkflow(
  "credit-store-credit-account",
  (input: { accountId: string; amount: number }) => {
    // Example step: load the store‑credit service & apply credit
    const credit = creditStoreCreditAccountStep(input.accountId, input.amount)

    // Hook emitted after successful credit
    const hook = createHook("storeCreditCredited", { accountId: input.accountId })

    // The workflow returns a typed response and registers the hook
    return new WorkflowResponse(credit, { hooks: [hook] })
  }
)

```

This demonstrates the **core pattern**: `createWorkflow(id, fn) → WorkflowResponse`. The workflow is later invoked from an API route or another workflow.

### Step Implementation with Compensation

Individual steps are defined using `createStep` in [`packages/plugins/loyalty/src/workflows/store-credit/steps/credit-store-credit-account.ts`](https://github.com/medusajs/medusa/blob/main/packages/plugins/loyalty/src/workflows/store-credit/steps/credit-store-credit-account.ts). This file shows how to implement **idempotent steps** with optional rollback logic:

```typescript
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"

export const creditStoreCreditAccountStep = createStep(
  "credit-store-credit-account",
  async (accountId: string, amount: number, { container }) => {
    const storeCreditService = container.resolve(Modules.STORE_CREDIT)
    await storeCreditService.credit(accountId, amount)
    return new StepResponse(void 0, { accountId })
  },
  // Compensation (rollback) – optional
  async (compensationData, { container }) => {
    const { accountId } = compensationData ?? {}
    if (!accountId) return
    const storeCreditService = container.resolve(Modules.STORE_CREDIT)
    await storeCreditService.debit(accountId, amount) // reverse the credit
  }
)

```

The **compensation function** (second argument to `createStep`) automatically runs if the workflow fails, ensuring data consistency.

### Conditional and Nested Workflows

For complex business rules, you can implement conditional branching using the `when` utility. The integration test fixtures in [`packages/modules/workflow-engine-redis/integration-tests/__fixtures__/workflow_when.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/workflow-engine-redis/integration-tests/__fixtures__/workflow_when.ts) demonstrate nested workflows:

```typescript
import { createWorkflow, when } from "@medusajs/framework/workflows-sdk"

export const parentWorkflow = createWorkflow("parent", (input) => {
  const sub = when(input.runSub, (i) => {
    return createWorkflow("sub", () => {
      // sub‑workflow logic
    })
  })

  return { subResult: sub }
})

```

This pattern allows you to conditionally execute sub-workflows based on runtime input, keeping your logic modular and readable.

## API Route Implementation Patterns

Medusa **API routes** are thin wrappers that extract HTTP parameters, invoke workflows through the dependency injection container (`req.scope`), and return JSON responses.

### Admin API Routes Invoking Workflows

Admin routes typically use `AuthenticatedMedusaRequest` and trigger workflows to perform write operations. The store credit endpoint in `packages/medusa/src/api/admin/store-credit-accounts/[id]/credit/route.ts` shows the standard pattern:

```typescript
import {
  AuthenticatedMedusaRequest,
  MedusaResponse,
} from "@medusajs/framework/http"
import { creditStoreCreditAccountWorkflow } from "@medusajs/loyalty"

export const POST = async (
  req: AuthenticatedMedusaRequest<{ amount: number }>,
  res: MedusaResponse
) => {
  const { id } = req.params
  const { amount } = req.body

  // Run the workflow via the DI container (req.scope)
  await creditStoreCreditAccountWorkflow(req.scope).run({
    input: { accountId: id, amount },
  })

  res.status(200).json({ id, credited: true, amount })
}

```

The key interaction occurs via `creditStoreCreditAccountWorkflow(req.scope).run()`, which accesses the Medusa container to resolve services and execute steps.

### Storefront API Routes

Storefront routes follow the same structure but use `MedusaRequest` instead of the authenticated variant. The products listing in [`packages/medusa/src/api/store/products/route.ts`](https://github.com/medusajs/medusa/blob/main/packages/medusa/src/api/store/products/route.ts) illustrates a simple read operation:

```typescript
import {
  MedusaRequest,
  MedusaResponse,
} from "@medusajs/framework/http"
import { listProducts } from "@medusajs/medusa"

export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
  const products = await listProducts(req.scope, {
    limit: req.query.limit,
    offset: req.query.offset,
  })

  res.json({ products, count: products.length })
}

```

This demonstrates the **basic route skeleton** used across the entire `api/store` namespace, where `req.scope` provides access to Medusa's service layer.

### Workflow Execution Endpoints

Medusa also provides generic administrative endpoints for manual workflow execution. The route at `packages/medusa/src/api/admin/workflows-executions/[workflow_id]/run/route.ts` allows you to trigger any registered workflow via HTTP, which is useful for debugging or administrative operations.

## Key Source Files to Explore

To deepen your understanding of Medusa workflow and API route implementations, explore these specific files in the `develop` branch:

- **Core workflow utilities**: [`packages/core/workflows-sdk/src/utils/composer/create-workflow.ts`](https://github.com/medusajs/medusa/blob/main/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts) – Implementation of `createWorkflow` and step composition.
- **Workflow examples (plugins)**: [`packages/plugins/loyalty/src/workflows/gift-cards/workflows/create-gift-cards.ts`](https://github.com/medusajs/medusa/blob/main/packages/plugins/loyalty/src/workflows/gift-cards/workflows/create-gift-cards.ts) – Full-featured workflow with steps, hooks, and compensation.
- **Workflow tests (reference)**: [`packages/modules/workflow-engine-redis/integration-tests/__tests__/index.spec.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/workflow-engine-redis/integration-tests/__tests__/index.spec.ts) – End-to-end tests that run real workflows against the Redis engine.
- **API-route pattern (admin)**: `packages/medusa/src/api/admin/orders/[id]/route.ts` – CRUD route that triggers an order-related workflow.
- **API-route pattern (store)**: `packages/medusa/src/api/store/carts/[id]/complete/route.ts` – Store-side route that finalizes a cart via a workflow.
- **Step with compensation**: [`packages/plugins/loyalty/src/workflows/store-credit/steps/credit-store-credit-account.ts`](https://github.com/medusajs/medusa/blob/main/packages/plugins/loyalty/src/workflows/store-credit/steps/credit-store-credit-account.ts) – Production example of rollback logic.

## Summary

- **Workflows** are defined with `createWorkflow` in files under `packages/*/workflows/**`, returning a `WorkflowResponse` that can include hooks.
- **Steps** are atomic units created via `createStep`, optionally accepting a compensation function for rollback scenarios.
- **API routes** are thin HTTP wrappers that import request/response types, extract parameters, invoke workflows through `req.scope`, and return JSON.
- The **admin "workflow-executions"** endpoints let you manually trigger or inspect any workflow, providing an excellent testing interface.
- Production examples in the **loyalty plugin** demonstrate real-world patterns for store credit, gift cards, and points systems.

## Frequently Asked Questions

### Where is the main workflow engine code located in the Medusa repository?

The main workflow engine code resides in `packages/core/workflows-sdk`, specifically in [`src/utils/composer/create-workflow.ts`](https://github.com/medusajs/medusa/blob/main/src/utils/composer/create-workflow.ts). This package exports `createWorkflow`, `createStep`, `WorkflowResponse`, and `StepResponse`, which form the foundation of Medusa's business logic orchestration.

### How do I invoke a Medusa workflow from an API route?

You invoke a workflow by calling the workflow function with `req.scope` as the first argument, then chaining `.run()` with your input data. For example: `await myWorkflow(req.scope).run({ input: { id: "example" } })`. The `req.scope` object is Medusa's dependency injection container that resolves services required by the workflow steps.

### What is the purpose of the compensation function in `createStep`?

The compensation function (the second argument to `createStep`) acts as a rollback mechanism. If any step in a workflow fails after this step has completed, Medusa automatically executes the compensation function to undo the step's changes. This pattern ensures data consistency during distributed transactions, such as reversing a store credit if a subsequent inventory check fails.

### Can I find examples of conditional workflow execution?

Yes, the integration test fixtures in [`packages/modules/workflow-engine-redis/integration-tests/__fixtures__/workflow_when.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/workflow-engine-redis/integration-tests/__fixtures__/workflow_when.ts) demonstrate the `when` utility for conditional branching. This allows you to execute sub-workflows or specific steps only when certain input conditions are met, which is essential for implementing complex business rules without cluttering your main workflow logic.