ZITADEL Docs
Integrate & AuthenticateActionsV2

Migrate from Actions V1 to V2

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.

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.

Why Actions Changed from V1 to V2

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:

  • Better Scalability: Distributed, serverless execution
  • Greater Flexibility: Support for any technology stack (not just JavaScript)
  • Improved Resilience: Isolating custom logic from core ZITADEL services
  • Cost Optimization: Pay-per-execution models with serverless providers
  • Enhanced Monitoring: Better debugging and observability of custom extensions

The transition represents a move from "embedded extensions" to "true webhooks," aligning ZITADEL with industry patterns (GitHub Actions, Zapier, etc.).

Architecture Deep Dive: V1 vs V2

Actions V1: The Embedded Model

Custom JavaScript code executed directly inside ZITADEL's process. For a complete list of V1 flow types, see Actions V1 Flow Types.

  • Context: Embedded goja JavaScript engine
  • Risks: Shared memory space; errors could affect core functionality
  • Constraints: Bound to ZITADEL process resources; limited timeout configuration
  • V1 Triggers: Pre-event hooks (fire before operation) and Post-event hooks (fire after success)

Actions V2: The Webhook Model

Custom logic lives in external HTTP endpoints called via webhooks.

  • Context: Runs on your infrastructure (Cloudflare Workers, AWS Lambda, etc.)
  • Isolation: Completely isolated memory; failures do not crash ZITADEL
  • Scaling: Endpoints scale independently of ZITADEL

V2 Execution Types:

TypeDescription
RequestTriggers when a specific API request occurs
ResponseTriggers when a specific API response occurs
FunctionTriggers when specific functionality is used (useful for adding custom claims to tokens or executing external code during OIDC/SAML flows)
EventTriggers reactively when ZITADEL events occur

Key Architectural Differences

AspectActions V1Actions V2
Execution EnvironmentEmbedded in ZITADEL (sandboxed JavaScript)External webhooks (Cloudflare Workers, AWS Lambda, etc.)
Code LocationInline in ZITADEL ConsoleHosted on your infrastructure
LanguageJavaScript (limited runtime)Any language
API Accessctx and api objects provided by ZITADELZITADEL REST/gRPC APIs via HTTP calls
TriggersFlow + Trigger (e.g., "Pre Access Token Creation")Specific API methods or webhook events
DependenciesLimited (zitadel/http, zitadel/log)Any framework
SecurityManaged by ZITADELHMAC signature verification required (to validate incoming webhook requests from ZITADEL)
ScalabilityLimited by ZITADEL instanceIndependent scaling

Business Benefits

  • Technology Flexibility: Use your preferred language instead of being locked into JavaScript
  • Operational Resilience: Isolates failures to prevent cascading outages
  • Cost Optimization: Leverage serverless "scale to zero" pricing for custom logic
  • Observability: Integrate with tools such as Datadog and Sentry

When to Use Each V2 Execution Type

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 TypeWhen It FiresExample
Add custom token claimsFunction (preaccesstoken)Before access token generatedcustom-claims
Map roles to permissionsFunction (preaccesstoken)Before access token generatedauthorization
Add "groups" claim from rolesFunction (preaccesstoken/preuserinfo)Before token/userinfo generatedgroups-claim
Block loginFunction (preuserinfo) + interruptOnError: trueBefore userinfo generatedblock-login
Track last login timeFunction (preuserinfo)Before userinfo generatedset-user-metadata
Add custom SAML attributesFunction (presamlresponse)Before SAML response sentsaml-attributes
Migrate users on first loginRequest + Response (API methods)Before/after user lookup & sessionjit-users-migration
Map IDP attributesResponse (/RetrieveIdentityProviderIntent)After IDP authenticationidp-mapping
Auto-assign roles to new usersEvent (user.human.added)When user createdset-role
Forward events to monitoringEvent (any event)When event occursdatadog-forwarder

Detailed Flow Explanations

Flow 1: Internal Authentication

Maps user registration and login triggers to Request (Pre-operation) and Response (Post-operation) execution types.

Example Scripts:

Flow 2: External Authentication

Handles IDP logins and JIT (Just-in-Time) provisioning via Response (Intent retrieval) and standard User Creation hooks.

Example Scripts:

Flow 3: Complement Token

Moves from implicit hooks to specific V2 functions, primarily Function (preaccesstoken).

Example Scripts:

Flow 4: Customize SAML Response

Moves to the Function (presamlresponse).

Example Scripts:

Additional Resources

Was this page helpful?

On this page