<!-- llms.txt: https://workos.com/llms.txt -->

# Webhooks

Webhook endpoints let WorkOS deliver event notifications directly to your application. Use these endpoints to create, list, and delete the webhook endpoints configured for your environment.

For implementation guidance, including payload verification and local testing, see the [webhooks guide](https://workos.com/docs/events/data-syncing/webhooks).

## Create a Webhook Endpoint

Create a new webhook endpoint to receive event notifications.

:::code-group

```bash language="curl" title="Request" tab="1"
curl --request POST \
  --url "https://api.workos.com/webhook_endpoints" \
  --header "Authorization: Bearer sk_example_123456789" \
  --header "Content-Type: application/json" \
  -d @- <<'BODY'
    {
        "endpoint_url": "https://example.com/webhooks",
        "events": [
            "user.created",
            "dsync.user.created"
        ]
    }
BODY
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.webhooks.create_webhook_endpoint(
  endpoint_url: "https://example.com/webhooks",
  events: ["user.created", "dsync.user.created"]
)
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.webhooks.create_webhook_endpoint(
    endpoint_url="https://example.com/webhooks",
    events=["user.created", "dsync.user.created"],
)
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Webhooks().CreateEndpoint(context.Background(), &workos.WebhooksCreateEndpointParams{
		EndpointURL: "https://example.com/webhooks",
		Events:      []any{"user.created", "dsync.user.created"},
	})
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos
    ->webhooks()
    ->createWebhookEndpoint(
        endpointUrl: "https://example.com/webhooks",
        events: ["user.created", "dsync.user.created"],
    );
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;
import com.workos.webhooks.WebhooksApi.CreateWebhookEndpointOptions;

WorkOS workos = new WorkOS("sk_example_123456789");

CreateWebhookEndpointOptions options =
    CreateWebhookEndpointOptions.builder()
        .endpointUrl("https://example.com/webhooks")
        .events(List.of("user.created", "dsync.user.created"))
        .build();

workos.webhooks.createWebhookEndpoint(options);
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Webhooks.CreateEndpointAsync(new WebhooksCreateEndpointOptions {
    EndpointUrl = "https://example.com/webhooks",
    Events = new[] { "user.created", "dsync.user.created" },
});
```

```rust language="rust" title="Request" tab="1"
use workos::Client;
use workos::webhooks::CreateWebhookEndpointParams;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .webhooks()
        .create_webhook_endpoint(
            CreateWebhookEndpointParams {
                endpoint_url: "https://example.com/webhooks".into(),
                events: vec!["user.created".into(), "dsync.user.created".into()],
                ..Default::default()
            }
        )
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "object": "webhook_endpoint",
  "id": "we_0123456789",
  "endpoint_url": "https://example.com/webhooks",
  "secret": "whsec_0FWAiVGkEfGBqqsJH4aNAGBJ4",
  "status": "enabled",
  "events": [
    "user.created",
    "dsync.user.created"
  ],
  "created_at": "2026-01-15T12:00:00.000Z",
  "updated_at": "2026-01-15T12:00:00.000Z"
}
```

:::

## Delete a Webhook Endpoint

Delete an existing webhook endpoint.

:::code-group

```bash language="curl" title="Request" tab="1"
curl --request DELETE \
  --url "https://api.workos.com/webhook_endpoints/we_0123456789" \
  --header "Authorization: Bearer sk_example_123456789"
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.webhooks.delete_webhook_endpoint(id: "we_0123456789")
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.webhooks.delete_webhook_endpoint(id_="we_0123456789")
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Webhooks().DeleteEndpoint(context.Background(), "we_0123456789")
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->webhooks()->deleteWebhookEndpoint(id: "we_0123456789");
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.webhooks.deleteWebhookEndpoint("we_0123456789");
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Webhooks.DeleteEndpointAsync("we_0123456789");
```

```rust language="rust" title="Request" tab="1"
use workos::Client;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .webhooks()
        .delete_webhook_endpoint("we_0123456789")
        .await?;

    Ok(())
}
```

:::

## List Webhook Endpoints

Get a list of all of your existing webhook endpoints.

:::code-group

```bash language="curl" title="Request" tab="1"
curl "https://api.workos.com/webhook_endpoints" \
  --header "Authorization: Bearer sk_example_123456789"
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.webhooks.list_webhook_endpoints
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.webhooks.list_webhook_endpoints()
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Webhooks().ListEndpoints(context.Background())
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->webhooks()->listWebhookEndpoints();
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.webhooks.listWebhookEndpoints();
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Webhooks.ListEndpointsAsync();
```

```rust language="rust" title="Request" tab="1"
use workos::Client;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .webhooks()
        .list_webhook_endpoints()
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "object": "list",
  "data": [
    {
      "object": "webhook_endpoint",
      "id": "we_0123456789",
      "endpoint_url": "https://example.com/webhooks",
      "secret": "whsec_0FWAiVGkEfGBqqsJH4aNAGBJ4",
      "status": "enabled",
      "events": [
        "user.created",
        "dsync.user.created"
      ],
      "created_at": "2026-01-15T12:00:00.000Z",
      "updated_at": "2026-01-15T12:00:00.000Z"
    }
  ],
  "list_metadata": {
    "before": "we_01HXYZ123456789ABCDEFGHIJ",
    "after": "we_01HXYZ987654321KJIHGFEDCBA"
  }
}
```

:::

## Update a Webhook Endpoint

Update the properties of an existing webhook endpoint.

:::code-group

```bash language="curl" title="Request" tab="1"
curl --request PATCH \
  --url "https://api.workos.com/webhook_endpoints/we_0123456789" \
  --header "Authorization: Bearer sk_example_123456789" \
  --header "Content-Type: application/json" \
  -d @- <<'BODY'
    {
        "endpoint_url": "https://example.com/webhooks",
        "status": "enabled",
        "events": [
            "user.created",
            "dsync.user.created"
        ]
    }
BODY
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.webhooks.update_webhook_endpoint(id: "we_0123456789")
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.webhooks.update_webhook_endpoint(id_="we_0123456789")
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Webhooks().UpdateEndpoint(context.Background(), "we_0123456789")
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->webhooks()->updateWebhookEndpoint(id: "we_0123456789");
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.webhooks.updateWebhookEndpoint("we_0123456789");
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Webhooks.UpdateEndpointAsync("we_0123456789");
```

```rust language="rust" title="Request" tab="1"
use workos::Client;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .webhooks()
        .update_webhook_endpoint("we_0123456789")
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "object": "webhook_endpoint",
  "id": "we_0123456789",
  "endpoint_url": "https://example.com/webhooks",
  "secret": "whsec_0FWAiVGkEfGBqqsJH4aNAGBJ4",
  "status": "enabled",
  "events": [
    "user.created",
    "dsync.user.created"
  ],
  "created_at": "2026-01-15T12:00:00.000Z",
  "updated_at": "2026-01-15T12:00:00.000Z"
}
```

:::

### webhook_endpoint

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `object` | "webhook_endpoint" | Yes | Distinguishes the Webhook Endpoint object. |
| `id` | string | Yes | Unique identifier of the Webhook Endpoint. |
| `endpoint_url` | string | Yes | The URL to which webhooks are sent. |
| `secret` | string | Yes | The secret used to sign webhook payloads. |
| `status` | "enabled" \| "disabled" | Yes | Whether the Webhook Endpoint is enabled or disabled. |
| `events` | string[] | Yes | The events that the Webhook Endpoint is subscribed to. |
| `created_at` | string | Yes | An ISO 8601 timestamp. |
| `updated_at` | string | Yes | An ISO 8601 timestamp. |

### POST /webhook_endpoints

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `endpoint_url` | string | Yes | The HTTPS URL where webhooks will be sent. |
| `events` | ("agent.blueprint.created" \| "agent.blueprint.deleted" \| "agent.blueprint.updated" \| ...)[] | Yes | The events that the Webhook Endpoint is subscribed to. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `webhook_endpoint` | object | Distinguishes the Webhook Endpoint object. |

### DELETE /webhook_endpoints/{id}

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Unique identifier of the Webhook Endpoint. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `empty` | empty | Returns an empty response on success. |

### GET /webhook_endpoints

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `before` | string | No | An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. |
| `after` | string | No | An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. |
| `limit` | integer | No | Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. |
| `order` | "normal" \| "desc" \| "asc" | No | Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `normal`. |

### PATCH /webhook_endpoints/{id}

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `endpoint_url` | string | No | The HTTPS URL where webhooks will be sent. |
| `status` | "enabled" \| "disabled" | No | Whether the Webhook Endpoint is enabled or disabled. |
| `events` | ("agent.blueprint.created" \| "agent.blueprint.deleted" \| "agent.blueprint.updated" \| ...)[] | No | The events that the Webhook Endpoint is subscribed to. |

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Unique identifier of the Webhook Endpoint. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `webhook_endpoint` | object | Distinguishes the Webhook Endpoint object. |