# 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
    import { serve } from "@upstash/workflow/nextjs";

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

    ```python Python
    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}
    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
    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}
    import { serve } from "@upstash/workflow/nextjs";

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

    ```python Python
    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>
