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

# Using Serve Many

Normally, workflows are created with `serve()`, which exposes each workflow as its own HTTP endpoint.
If workflows were invoked only by their full URL, it would mean:

* You'd have to provide the URL explicitly like a trigger request
* You'd lose type safety for request and response payloads

To avoid these issues, Upstash Workflow lets you define workflows as objects and expose them under the same parent path.
This way, you can invoke a workflow simply by passing the object to `context.invoke`, with full type safety and no URLs required.

<Steps>
  <Step title="Create workflow objects">
    Use `createWorkflow()` to define workflows as objects.

    It works just like `serve()`—accepting the same arguments—but does **not** expose the workflow directly as an HTTP endpoint.
    Instead, it simply initializes a workflow object.

    ```typescript theme={"system"}
    const workflowOne = createWorkflow(
      // 👇 Request Payload Type
      async (context: WorkflowContext<string>) => {

        await context.sleep("wait 1 second", 1)

        // 👇 Workflow Response Type
        return { message: "This is the data returned by the workflow" };
      }
    );

    const workflowTwo = createWorkflow(async (context) => {
      // 👇 Invoke the workflow with type-safe call
      const { body } = await context.invoke(
        "invoke workflowOne",
        {
          workflow: workflowOne,
          body: "user-1"
        }
      ),
    });
    ```
  </Step>

  <Step title="Expose multiple workflows under same endpoint">
    Use `serveMany()` instead of `serve()` to expose multiple workflows on a single catch‑all route.

    If one workflow is going to invoke another, both must be included in the same `serveMany` definition.
    First step of using `serveMany` is to define a catch-all route.

    ```typescript app/serve-many/[...any]/route.ts theme={"system"}
    export const { POST } = serveMany(
      {
        "workflow-one-route": workflowOne,
        "workflow-two-route": workflowTwo,
      }
    )
    ```

    <Info>
      In Next.js, a catch‑all route can be defined by creating a `route.ts` file inside a directory named with `[...]`, for example: `app/serve-many/[...any]/route.ts`.

      For implementations of `serveMany` in other frameworks, you can refer to the projects available in the [`examples` directory of the workflow-js repository](https://github.com/upstash/workflow-js/tree/main/examples).
    </Info>
  </Step>

  <Step title="Invoke by passing workflow object">
    When invoking, pass the workflow object created with `createWorkflow()` (from step 1) as the argument to `context.invoke()`.
    This removes the need to specify a URL explicitly and ensures the call is
    fully type‑safe.

    ```ts theme={"system"}
    const workflowTwo = createWorkflow(async (context) => {
      // 👇 Invoke the workflow with type-safe call
      const { body } = await context.invoke(
        "invoke workflowOne",
        {
          // 👇 Pass the workflow object as argument
          workflow: workflowOne,
          body: "user-1"
        }
      ),
    });
    ```
  </Step>

  <Step title="Trigger">
    In this example, both `workflowOne` and `workflowTwo` are exposed through `serveMany`, sharing the same parent path.

    You can start `workflowOne` by sending a trigger request to:
    `https://your-app/serve-many/workflow-one-route`.

    ```typescript theme={"system"}
    import { Client } from "@upstash/workflow";

    const client = new Client({ token: "<QSTASH_TOKEN>" })

    const { workflowRunId } = await client.trigger({
      // 👇 URL of workflow one
      url: "https://your-app/serve-many/workflow-one-route"
    })
    ```

    Route names are inferred from the keys you pass to `serveMany`.
    For example, you can start `workflowTwo` by sending trigger request to: `https://your-app/serve-many/workflow-two-route`.
  </Step>
</Steps>
