apps/docs/content/guides/integrate/actions/migrate-from-v1.mdx
This guide helps existing users understand the shift from Actions V1 (Embedded) to V2 (Webhook), and provides guidance for new users on how to work with Actions V2.
<Callout type="caution"> Deprecation Notice Actions V1 APIs are planned to be sunsetted in ZITADEL V5. While a definitive V5 release date is not yet available, this is the final timeline for V1 API removal. Actions V1 will receive no new features, and all new implementations must use V2. </Callout>ZITADEL Actions evolved from V1 to V2 to address fundamental architectural limitations. While Actions V1 executed JavaScript code directly within ZITADEL's runtime, Actions V2 uses external HTTP endpoints.
This shift enables:
The transition represents a move from "embedded extensions" to "true webhooks," aligning ZITADEL with industry patterns (GitHub Actions, Zapier, etc.).
Custom JavaScript code executed directly inside ZITADEL's process. For a complete list of V1 flow types, see Actions V1 Flow Types.
Custom logic lives in external HTTP endpoints called via webhooks.
V2 Execution Types:
| Type | Description |
|---|---|
| Request | Triggers when a specific API request occurs |
| Response | Triggers when a specific API response occurs |
| Function | Triggers when specific functionality is used (useful for adding custom claims to tokens or executing external code during OIDC/SAML flows) |
| Event | Triggers reactively when ZITADEL events occur |
| Aspect | Actions V1 | Actions V2 |
|---|---|---|
| Execution Environment | Embedded in ZITADEL (sandboxed JavaScript) | External webhooks (Cloudflare Workers, AWS Lambda, etc.) |
| Code Location | Inline in ZITADEL Console | Hosted on your infrastructure |
| Language | JavaScript (limited runtime) | Any language |
| API Access | ctx and api objects provided by ZITADEL | ZITADEL REST/gRPC APIs via HTTP calls |
| Triggers | Flow + Trigger (e.g., "Pre Access Token Creation") | Specific API methods or webhook events |
| Dependencies | Limited (zitadel/http, zitadel/log) | Any framework |
| Security | Managed by ZITADEL | HMAC signature verification required (to validate incoming webhook requests from ZITADEL) |
| Scalability | Limited by ZITADEL instance | Independent scaling |
We provide a collection of ready-to-deploy Cloudflare Worker examples that integrate with ZITADEL Actions V2. Each script demonstrates how to handle ZITADEL events, signatures, and responses directly from a serverless Cloudflare Worker environment. While the examples are designed for Cloudflare Workers, the code can be adapted to deploy on the platform of your choice (AWS Lambda, Azure Functions, etc.).
| If You Need To... | Use This V2 Type | When It Fires | Example |
|---|---|---|---|
| Add custom token claims | Function (preaccesstoken) | Before access token generated | custom-claims |
| Map roles to permissions | Function (preaccesstoken) | Before access token generated | authorization |
| Add "groups" claim from roles | Function (preaccesstoken/preuserinfo) | Before token/userinfo generated | groups-claim |
| Block login | Function (preuserinfo) + interruptOnError: true | Before userinfo generated | block-login |
| Track last login time | Function (preuserinfo) | Before userinfo generated | set-user-metadata |
| Add custom SAML attributes | Function (presamlresponse) | Before SAML response sent | saml-attributes |
| Migrate users on first login | Request + Response (API methods) | Before/after user lookup & session | jit-users-migration |
| Map IDP attributes | Response (/RetrieveIdentityProviderIntent) | After IDP authentication | idp-mapping |
| Auto-assign roles to new users | Event (user.human.added) | When user created | set-role |
| Forward events to monitoring | Event (any event) | When event occurs | datadog-forwarder |
Maps user registration and login triggers to Request (Pre-operation) and Response (Post-operation) execution types.
Example Scripts:
Handles IDP logins and JIT (Just-in-Time) provisioning via Response (Intent retrieval) and standard User Creation hooks.
Example Scripts:
Moves from implicit hooks to specific V2 functions, primarily Function (preaccesstoken).
Example Scripts:
Moves to the Function (presamlresponse).
Example Scripts: