diff --git a/docs/docs/guides/integrate/actions/testing-event.md b/docs/docs/guides/integrate/actions/testing-event.md index bddaf9197..fe1e872dd 100644 --- a/docs/docs/guides/integrate/actions/testing-event.md +++ b/docs/docs/guides/integrate/actions/testing-event.md @@ -60,6 +60,12 @@ func main() { } ``` +:::info +The example above runs only on your local machine (`localhost`). +To test it with Zitadel, you must make your listener reachable from the internet. +You can do this by using **Webhook.site** (see [Creating a Listener with Webhook.site](./webhook-site-setup)). +::: + ## Create target As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as webhook, the diff --git a/docs/docs/guides/integrate/actions/testing-function-manipulation.md b/docs/docs/guides/integrate/actions/testing-function-manipulation.md index e82f0b8c1..d95169be3 100644 --- a/docs/docs/guides/integrate/actions/testing-function-manipulation.md +++ b/docs/docs/guides/integrate/actions/testing-function-manipulation.md @@ -87,6 +87,12 @@ func main() { ``` +:::info +The example above runs only on your local machine (`localhost`). +To test it with Zitadel, you must make your listener reachable from the internet. +You can do this by using **Webhook.site** (see [Creating a Listener with Webhook.site](./webhook-site-setup)). +::: + ## Create target As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as call, the target can be created as follows: diff --git a/docs/docs/guides/integrate/actions/testing-function.md b/docs/docs/guides/integrate/actions/testing-function.md index a2faa5e70..c75963247 100644 --- a/docs/docs/guides/integrate/actions/testing-function.md +++ b/docs/docs/guides/integrate/actions/testing-function.md @@ -65,6 +65,12 @@ func main() { ``` +:::info +The example above runs only on your local machine (`localhost`). +To test it with Zitadel, you must make your listener reachable from the internet. +You can do this by using **Webhook.site** (see [Creating a Listener with Webhook.site](./webhook-site-setup)). +::: + ## Create target As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as webhook, the target can be created as follows: diff --git a/docs/docs/guides/integrate/actions/testing-request-manipulation.md b/docs/docs/guides/integrate/actions/testing-request-manipulation.md index 49bc4d937..1ae9cc40d 100644 --- a/docs/docs/guides/integrate/actions/testing-request-manipulation.md +++ b/docs/docs/guides/integrate/actions/testing-request-manipulation.md @@ -113,6 +113,12 @@ func main() { ``` +:::info +The example above runs only on your local machine (`localhost`). +To test it with Zitadel, you must make your listener reachable from the internet. +You can do this by using **Webhook.site** (see [Creating a Listener with Webhook.site](./webhook-site-setup)). +::: + ## Create target As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as call, the target can be created as follows: diff --git a/docs/docs/guides/integrate/actions/testing-request-signature.md b/docs/docs/guides/integrate/actions/testing-request-signature.md index b39b75d7a..91028bcb8 100644 --- a/docs/docs/guides/integrate/actions/testing-request-signature.md +++ b/docs/docs/guides/integrate/actions/testing-request-signature.md @@ -72,6 +72,12 @@ func main() { } ``` +:::info +The example above runs only on your local machine (`localhost`). +To test it with Zitadel, you must make your listener reachable from the internet. +You can do this by using **Webhook.site** (see [Creating a Listener with Webhook.site](./webhook-site-setup)). +::: + ## Create target As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as webhook, the target can be created as follows: diff --git a/docs/docs/guides/integrate/actions/testing-request.md b/docs/docs/guides/integrate/actions/testing-request.md index 6a3f780f0..e2c9719ec 100644 --- a/docs/docs/guides/integrate/actions/testing-request.md +++ b/docs/docs/guides/integrate/actions/testing-request.md @@ -65,6 +65,12 @@ func main() { } ``` +:::info +The example above runs only on your local machine (`localhost`). +To test it with Zitadel, you must make your listener reachable from the internet. +You can do this by using **Webhook.site** (see [Creating a Listener with Webhook.site](./webhook-site-setup)). +::: + ## Create target As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as webhook, the target can be created as follows: diff --git a/docs/docs/guides/integrate/actions/testing-response-manipulation.md b/docs/docs/guides/integrate/actions/testing-response-manipulation.md index 2bec3e0ac..843dedce7 100644 --- a/docs/docs/guides/integrate/actions/testing-response-manipulation.md +++ b/docs/docs/guides/integrate/actions/testing-response-manipulation.md @@ -130,6 +130,12 @@ func main() { } ``` +:::info +The example above runs only on your local machine (`localhost`). +To test it with Zitadel, you must make your listener reachable from the internet. +You can do this by using **Webhook.site** (see [Creating a Listener with Webhook.site](./webhook-site-setup)). +::: + ## Create target As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as call, the diff --git a/docs/docs/guides/integrate/actions/testing-response.md b/docs/docs/guides/integrate/actions/testing-response.md index 4114f9a3a..dc53a3ca6 100644 --- a/docs/docs/guides/integrate/actions/testing-response.md +++ b/docs/docs/guides/integrate/actions/testing-response.md @@ -65,6 +65,12 @@ func main() { } ``` +:::info +The example above runs only on your local machine (`localhost`). +To test it with Zitadel, you must make your listener reachable from the internet. +You can do this by using **Webhook.site** (see [Creating a Listener with Webhook.site](./webhook-site-setup)). +::: + ## Create target As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as webhook, the target can be created as follows: diff --git a/docs/docs/guides/integrate/actions/webhook-site-setup.md b/docs/docs/guides/integrate/actions/webhook-site-setup.md new file mode 100644 index 000000000..434d944d7 --- /dev/null +++ b/docs/docs/guides/integrate/actions/webhook-site-setup.md @@ -0,0 +1,172 @@ +--- +title: Testing Actions V2 with Webhook.site +sidebar_label: Testing Actions V2 with Webhook.site +--- + +## 1. Introduction + +This guide explains how to test **ZITADEL Actions V2** locally using [Webhook.site](https://webhook.site). +We will use Webhook.site’s **XHR Redirect** feature to forward requests from ZITADEL to your local machine. + +**What you will learn in this guide:** + +- How to add the required CORS headers to your local listener +- How to configure Webhook.site with XHR Redirect +- How to create a target in ZITADEL and link it to your Action +- How to verify forwarded requests in your terminal + +--- + +## 2. Prerequisites + +### 2.1. Local Listener + +You should already have a local HTTP server (for example, the Go example listener from [Testing a Request](./testing-request)) running at `http://localhost:8090/webhook`. + +### 2.2. CORS Headers + +Because Webhook.site’s XHR redirect runs in your browser, your listener must allow CORS. +Add the following headers in your handler: + +```go +w.Header().Set("Access-Control-Allow-Origin", "*") +w.Header().Set("Access-Control-Allow-Methods", "*") +w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") + +if req.Method == http.MethodOptions { + w.WriteHeader(http.StatusOK) + return +} +``` + +--- + +## 3. Configure Webhook.site XHR Redirect + +1. Open your unique Webhook.site URL. +2. Click **Configure XHR Redirect**. +3. Enable **XHR Redirect**. +4. Enter your local endpoint in **Target**, e.g.: + + ``` + http://localhost:8090/webhook + ``` + +5. Leave other fields empty unless you need custom headers. +6. Keep the Webhook.site browser tab open while testing. + +Screenshot: Webhook.site XHR Redirect configuration interface + +--- + +## 4. Run Your Listener + +Start your local listener: + +```sh +go run actionsRequest.go +``` + +You should see output in your console whenever the listener is called. + +Screenshot: Console output showing listener receiving webhook requests + +--- + +## 5. Create Target in ZITADEL + +As shown in the example above, the target is created with HTTP and port '8090'. If you want to use it as a webhook, the target can be created as follows: + +See [Create a target](/apis/resources/action_service_v2/action-service-create-target) for more detailed information. Notice that the `endpoint` is your Webhook.site URL. + +```shell +curl -L -X POST 'https://$CUSTOM-DOMAIN/v2beta/actions/targets' \ +-H 'Content-Type: application/json' \ +-H 'Accept: application/json' \ +-H 'Authorization: Bearer ' \ +--data-raw '{ + "name": "local webhook", + "restWebhook": { + "interruptOnError": true + }, + "endpoint": "https://webhook.site/29fa2769-e2f6-44ff-8eb0-2434b83507d8/webhook", + "timeout": "10s" +}' +``` + +Screenshot: Webhook.site target creation interface + +--- + +Save the returned ID to use in the execution step. A sample response looks like this: + +```json +{ + "id": "337246363446151234", + "creationDate": "2025-09-10T13:21:36.959699Z", + "signingKey": "OpUHaCtEqh8swdJ5xUYbQ2bhej1abcXYZ" +} +``` + +## 6. Set execution + +To configure ZITADEL to call the target when an API endpoint is called, set an execution and define the request condition. + +See [Set an execution](/apis/resources/action_service_v2/action-service-set-execution) for more detailed information. + +Here, `` is the `id` from the previous step. + +```shell +curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \ +-H 'Content-Type: application/json' \ +-H 'Accept: application/json' \ +-H 'Authorization: Bearer ' \ +--data-raw '{ + "condition": { + "request": { + "method": "/zitadel.user.v2.UserService/AddHumanUser" + } + }, + "targets": [ + "" + ] +}' +``` + +--- + +## 7. Example Call + +Now that you have set up the target and execution, you can test it by creating a user through the Console UI or by calling the ZITADEL API to create a human user. + +Here, we are creating a user via the API: + +```shell +curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \ +-H 'Content-Type: application/json' \ +-H 'Accept: application/json' \ +-H 'Authorization: Bearer ' \ +--data-raw '{ + "profile": { + "givenName": "Example_given", + "familyName": "Example_family" + }, + "email": { + "email": "example@example.com" + } +}' +``` + +Both your Webhook.site and your local listener should now print out something like the following. See the [Sent information Request](./usage#sent-information-request) payload description for details. + +Your local listener should look like this: +Screenshot: Local listener output + +Your Webhook.site should look like this: +Screenshot: Webhook.site request log + +--- + +## 8. Done + +You now have a fully working setup for testing ZITADEL Actions V2 with Webhook.site. This allows you to forward requests securely from ZITADEL to your local environment without needing a public IP address or domain. diff --git a/docs/sidebars.js b/docs/sidebars.js index d15c6ab46..8003056c6 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -528,6 +528,10 @@ module.exports = { type: "doc", id: "guides/integrate/actions/migrate-from-v1", }, + { + type: "doc", + id: "guides/integrate/actions/webhook-site-setup", + }, ], }, { diff --git a/docs/static/img/actions-v2/console.png b/docs/static/img/actions-v2/console.png new file mode 100644 index 000000000..7749b9874 Binary files /dev/null and b/docs/static/img/actions-v2/console.png differ diff --git a/docs/static/img/actions-v2/local-listener.png b/docs/static/img/actions-v2/local-listener.png new file mode 100644 index 000000000..bf408a748 Binary files /dev/null and b/docs/static/img/actions-v2/local-listener.png differ diff --git a/docs/static/img/actions-v2/webhook-listener.png b/docs/static/img/actions-v2/webhook-listener.png new file mode 100644 index 000000000..5cf6bc00d Binary files /dev/null and b/docs/static/img/actions-v2/webhook-listener.png differ diff --git a/docs/static/img/actions-v2/webhook-url.png b/docs/static/img/actions-v2/webhook-url.png new file mode 100644 index 000000000..485d163fd Binary files /dev/null and b/docs/static/img/actions-v2/webhook-url.png differ diff --git a/docs/static/img/actions-v2/webhook-xhr.png b/docs/static/img/actions-v2/webhook-xhr.png new file mode 100644 index 000000000..8034668e9 Binary files /dev/null and b/docs/static/img/actions-v2/webhook-xhr.png differ