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

# Overview

Use the `serve()` function to define an endpoint that runs a workflow.
It accepts two arguments:

1. **Route Function**: an async function that receives the workflow context and defines the workflow steps.
2. **Options**: configuration options for the workflow.

<CodeGroup>
  ```typescript TypeScript theme={"system"}
  import { serve } from "@upstash/workflow/nextjs";

  export const { POST } = serve(async (context) => {
    // Route function
  }, {
    // Options
  });
  ```

  ```python Python theme={"system"}
  from fastapi import FastAPI
  from upstash_workflow.fastapi import Serve
  from upstash_workflow import AsyncWorkflowContext

  app = FastAPI()
  serve = Serve(app)


  @serve.post("/api/example")
  async def example(context: AsyncWorkflowContext[str]) -> None:
      async def _step1() -> str:
          # define a piece of business logic as step 1
          return "step 1 result"

      result = await context.run("step-1", _step1)

      async def _step2() -> None:
          # define another piece of business logic as step 2
          pass

      await context.run("step-2", _step2)
  ```
</CodeGroup>

## Route Function

The route function defines the execution logic of the workflow.
It is an async function that receives a context object, which is automatically created and passed by Upstash Workflow.

The context object provides:

* **Workflow APIs** – functions for defining workflow steps.
* **Workflow Run Properties** – request payload, request headers, and other metadata.

For a full list of available APIs and properties, see the [Workflow Context](/workflow/basics/context) documentation.

<CodeGroup>
  ```typescript TypeScript highlight={4-9} theme={"system"}
  import { serve } from "@upstash/workflow/nextjs";

  export const { POST } = serve(
    async (context) => {
      // 👇 Access context properties
      const { userId } = context.requestPayload;
      // 👇 Define a workflow step
      await context.run("step-1", async () => {})
    }
  );
  ```

  ```python Python theme={"system"}
  from fastapi import FastAPI
  from upstash_workflow.fastapi import Serve
  from upstash_workflow import AsyncWorkflowContext

  app = FastAPI()
  serve = Serve(app)


  @serve.post("/api/example")
  async def example(context: AsyncWorkflowContext[str]) -> None:
      async def _step1() -> str:
          # define a piece of business logic as step 1
          return "step 1 result"

      result = await context.run("step-1", _step1)

      async def _step2() -> None:
          # define another piece of business logic as step 2
          pass

      await context.run("step-2", _step2)

  ```
</CodeGroup>

## Options

Options provide additional configuration for workflow runs.
Most of them are advanced settings and are not required for typical use cases. See [Advanced Options](/workflow/basics/serve/advanced) for more details.

<CodeGroup>
  ```typescript TypeScript highlight={5-8} theme={"system"}
  import { serve } from "@upstash/workflow/nextjs";

  export const { POST } = serve(
      async (context) => { ... },
      // 👇 Workflow options
      {
          failureFunction: async ({ ... }) => {}
      }
  );
  ```

  ```python Python theme={"system"}
  from fastapi import FastAPI
  from upstash_workflow.fastapi import Serve
  from upstash_workflow import AsyncWorkflowContext

  app = FastAPI()
  serve = Serve(app)


  @serve.post("/api/example")
  async def example(context: AsyncWorkflowContext[str]) -> None:
      async def _step1() -> str:
          # define a piece of business logic as step 1
          return "step 1 result"

      result = await context.run("step-1", _step1)

      async def _step2() -> None:
          # define another piece of business logic as step 2
          pass

      await context.run("step-2", _step2)

  ```
</CodeGroup>
