Documentation menu

Zitadel setup walkthrough

How to wire Targets and Executions so ZITADEL reaches the right Atrium Action endpoints.

This page is about the webhook plumbing, not script authoring.

Use it when you need to:

  • create Targets
  • rotate signing keys
  • wire Executions
  • understand which endpoint serves which condition

The mental model

ZITADEL Actions v2 has three moving parts:

  1. Endpoint — the HTTP URL you host
  2. Target — ZITADEL's saved definition of that endpoint
  3. Execution — the condition that calls one or more Targets

Atrium owns:

  • the script source
  • the runtime endpoints
  • the admin APIs that help create Targets/Executions

ZITADEL owns:

  • the Targets
  • the Executions
  • the decision of when to call them

The canonical Atrium endpoints

Atrium exposes one endpoint per transport family:

Target nameEndpointPurpose
atrium-actions-eventshttps://atrium.ommax-intelligence.de/actions/eventsall Event deliveries
atrium-actions-functions-preuserinfohttps://atrium.ommax-intelligence.de/actions/functions/preuserinfoFUNCTION:preuserinfo
atrium-actions-functions-preaccesstokenhttps://atrium.ommax-intelligence.de/actions/functions/preaccesstokenFUNCTION:preaccesstoken
atrium-actions-functions-presamlresponsehttps://atrium.ommax-intelligence.de/actions/functions/presamlresponseFUNCTION:presamlresponse
atrium-actions-requestshttps://atrium.ommax-intelligence.de/actions/requestsRequest executions
atrium-actions-responseshttps://atrium.ommax-intelligence.de/actions/responsesResponse executions

For each Target:

  • type: REST webhook
  • payload: JSON
  • timeout: 5s
  • interrupt on error: usually unchecked unless you intentionally want synchronous blocking behaviour

Event-side vs script-side routing

Two different routing layers matter:

ZITADEL Execution routing

Event Executions can be scoped to:

  • all
  • group
  • event

Atrium script routing

Once the request reaches Atrium, the runtime matches by exact slot:

  • EVENT:user.human.added
  • EVENT:oidc_session.added
  • FUNCTION:preuserinfo

So an all events Execution can still be valid, but the script itself still needs the exact trigger name.

Path A: Atrium admin API

Use this when you already have Atrium admin auth.

Create a Target:

curl -X POST \
  -H "Authorization: Bearer atr_live_..." \
  -H "Content-Type: application/json" \
  https://atrium.ommax-intelligence.de/api/admin/zitadel/targets \
  -d '{
    "name": "atrium-actions-events",
    "endpoint": "https://atrium.ommax-intelligence.de/actions/events",
    "payloadType": "PAYLOAD_TYPE_JSON",
    "timeout": "5s",
    "interruptOnError": false
  }'

Wire an Execution:

curl -X POST \
  -H "Authorization: Bearer atr_live_..." \
  -H "Content-Type: application/json" \
  https://atrium.ommax-intelligence.de/api/admin/zitadel/executions \
  -d '{
    "condition": { "event": { "all": true } },
    "targetIds": ["<events-target-id>"]
  }'

Path B: Zitadel Console

Use this if you must work directly in ZITADEL.

The tricky parts:

  • the Console is worse than the API for signing-key recovery
  • the important routing concept is the Execution condition, not just the Target

Signing keys

Each Target has its own signing key.

The runtime accepts:

  • ZITADEL_WEBHOOK_SIGNING_KEY
  • or the preferred CSV form ZITADEL_WEBHOOK_SIGNING_KEYS

Operational rule:

  • keep all active Target keys present on the runtime
  • during rotation, keep old + new until traffic is clean

The two OMMAX Function slots that matter most

For the current migrations, the important Function slots are:

preuserinfo

Use for:

  • userinfo / ID-token-adjacent claim mutation
  • flatRoles parity when consumers read these claims there

preaccesstoken

Use for:

  • access-token claim mutation
  • the same flatRoles logic when downstream apps read the access token

Often the correct OMMAX setup is both slots, not just one.

Current trigger advice

Choose these on purpose:

  • EVENT:user.human.added for first-time onboarding
  • EVENT:oidc_session.added for login-time catch-up
  • FUNCTION:preuserinfo / FUNCTION:preaccesstoken for claims

Avoid guessing from names like session.added. Prefer recorded observed traffic.

Disable temporarily

If you want to stop a ZITADEL routing path without deleting the Target, remove its Execution by replacing the target list with an empty array.