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

# createWebhook

> Create a webhook to receive HTTP requests in a workflow

Creates a webhook that can be used to suspend and resume a workflow run upon receiving HTTP requests to a generated URL.

Webhooks are specialized hooks that provide an HTTP endpoint. External systems can make HTTP requests to the webhook URL to send data into the workflow.

## Signature

```typescript theme={null}
function createWebhook(
  options: WebhookOptions & { respondWith: 'manual' }
): Webhook<RequestWithResponse>

function createWebhook(options?: WebhookOptions): Webhook<Request>
```

## Parameters

<ParamField path="options" type="WebhookOptions" optional>
  Configuration options for the webhook.

  <Expandable title="properties">
    <ParamField path="token" type="string" optional>
      Unique token to associate with the webhook. If not provided, a randomly generated token will be assigned.
    </ParamField>

    <ParamField path="metadata" type="Serializable" optional>
      Additional user-defined data to include with the webhook.
    </ParamField>

    <ParamField path="respondWith" type="Response | 'manual'" optional>
      Controls how the webhook responds to HTTP requests:

      * If set to a `Response` object, automatically respond with that response
      * If set to `"manual"`, each request must be responded to manually by calling `respondWith()` within a step
      * If not set, automatically respond with `202 Accepted`
    </ParamField>
  </Expandable>
</ParamField>

## Returns

<ResponseField name="Webhook" type="Webhook<Request> | Webhook<RequestWithResponse>">
  A webhook object that extends Hook with an HTTP URL.

  <Expandable title="properties">
    <ResponseField name="url" type="string">
      The URL that external systems can call to send HTTP requests to the workflow.
    </ResponseField>

    <ResponseField name="token" type="string">
      The unique token identifying this webhook.
    </ResponseField>

    <ResponseField name="dispose" type="() => void">
      Releases the webhook token for reuse.
    </ResponseField>
  </Expandable>
</ResponseField>

## Usage

### Basic Webhook

Create a webhook and receive HTTP requests:

```typescript theme={null}
export async function workflowWithWebhook() {
  "use workflow";

  const webhook = createWebhook();
  console.log('Webhook URL:', webhook.url);

  const request = await webhook;
  console.log('Received request:', request.method, request.url);
}
```

### Custom Response

Automatically respond with a custom response:

```typescript theme={null}
export async function workflowWithCustomResponse() {
  "use workflow";

  const webhook = createWebhook({
    respondWith: new Response('Thank you!', {
      status: 200,
      headers: { 'Content-Type': 'text/plain' },
    }),
  });

  const request = await webhook;
  // Automatically responds with "Thank you!"
}
```

### Manual Response

Respond manually from within a step:

```typescript theme={null}
import { step } from 'workflow';

export async function workflowWithManualResponse() {
  "use workflow";

  const webhook = createWebhook({ respondWith: 'manual' });
  console.log('Webhook URL:', webhook.url);

  const request = await webhook;

  await step(async () => {
    "use step";

    // Process the request
    const body = await request.json();
    const result = await processData(body);

    // Send response back to the caller
    await request.respondWith(
      new Response(JSON.stringify(result), {
        status: 200,
        headers: { 'Content-Type': 'application/json' },
      })
    );
  });
}
```

### Iterate Over Multiple Requests

Handle multiple HTTP requests:

```typescript theme={null}
export async function webhookListener() {
  "use workflow";

  const webhook = createWebhook();
  console.log('Listening at:', webhook.url);

  for await (const request of webhook) {
    console.log('Received:', request.method, request.url);
    
    const body = await request.text();
    if (body === 'stop') {
      break;
    }
  }
}
```

### Parse Request Body

Extract data from the HTTP request:

```typescript theme={null}
export async function workflowWithRequestBody() {
  "use workflow";

  const webhook = createWebhook();

  const request = await webhook;
  
  // Parse JSON body
  const data = await request.json();
  console.log('Data:', data);

  // Or parse form data
  const formData = await request.formData();
  
  // Or get raw text
  const text = await request.text();
}
```

### Webhook with Custom Token

Use a predictable token:

```typescript theme={null}
export async function githubWebhook(repoId: string) {
  "use workflow";

  const webhook = createWebhook({
    token: `github:${repoId}`,
  });

  for await (const request of webhook) {
    const event = request.headers.get('X-GitHub-Event');
    const payload = await request.json();
    console.log('GitHub event:', event, payload);
  }
}
```

## Notes

* Can only be called inside a workflow function (with `"use workflow"`)
* The webhook URL is automatically generated and includes the workflow deployment URL
* When `respondWith: 'manual'` is set, you must call `request.respondWith()` from within a step function
* Webhooks inherit all Hook functionality, including disposal and iteration
* The `Request` object follows the [Web API Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) standard

## Related

* [createHook](/api-reference/workflow/create-hook) - Create a generic hook
* [defineHook](/api-reference/workflow/define-hook) - Define a typed hook with validation


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.