> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> Field reference for a connector's events block: event actions, router, setup lifecycle, and the external account id extractor.

Configures a connector's inbound webhooks. For how event handling works end to end, see [Implementing events](/connector-building/implementing-events).

## overview

Event and webhook configuration for the connector.

<table>
  <colgroup>
    <col width="210" />

    <col width="400" />

    <col width="90" />

    <col width="90" />
  </colgroup>

  <thead>
    <tr>
      <th>Field</th>
      <th>Description</th>
      <th>Type</th>
      <th>Required</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>[`actions`](#actions)</td>
      <td>Event actions that process incoming provider events.</td>
      <td>object\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`externalAccountIdExtractor`](#externalaccountidextractor)</td>
      <td>Action that reads the provider's external account identifier from an incoming payload so the event can be matched to a linked account.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`guides`](#guides)</td>
      <td>Manual webhook setup guides.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`router`](#router)</td>
      <td>Rules mapping incoming payloads to event actions.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`setup`](#setup)</td>
      <td>Programmatic webhook lifecycle configuration.</td>
      <td>object</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

**Examples**

```yaml theme={null}
events:
  setup:
    creation:
      steps:
        - stepId: create_webhook
          description: Register a webhook receiver.
          stepFunction:
            functionName: request
            version: v1
            parameters:
              url: /webhooks
              method: post
              args:
                - name: url
                  value: '${inputs.callbackUrl}'
                  in: body
      result: '$.id'
    deletion:
      steps:
        - stepId: delete_webhook
          description: Remove the webhook receiver.
          stepFunction:
            functionName: request
            version: v1
            parameters:
              url: '/webhooks/${inputs.remoteId}'
              method: delete
  router:
    rules:
      - when: '${event.type == "user.created"}'
        then: { action: user_created_event }
```

## actions

Event actions that process incoming provider events.

Same fields as [actions](/connector-yaml-reference/yaml-schema/actions), plus:

<table>
  <colgroup>
    <col width="210" />

    <col width="400" />

    <col width="90" />

    <col width="90" />
  </colgroup>

  <thead>
    <tr>
      <th>Field</th>
      <th>Description</th>
      <th>Type</th>
      <th>Required</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>`requiresManualSetup`</td>
      <td>Whether the webhook must be configured manually in the provider UI.</td>
      <td>boolean</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

**Examples**

```yaml theme={null}
events:
  actions:
    - actionId: handle_ticket_created
      actionType: event
      label: Ticket created webhook
      description: Processes ticket.created events from the provider.
      providerEvents: [ticket.created]
      inputs:
        - name: event
          description: The provider event object from the delivery.
          type: object
          in: body
          required: false
      steps:
        - stepId: emit
          description: Emit the ticket.created event to StackOne's dispatcher.
          stepFunction:
            functionName: emit_event
            parameters:
              event:
                eventType: ticket.created
                eventId: $.inputs.event.id
                data: $.inputs.event
      result:
        statusCode: 200
        body:
          status: OK
```

## externalAccountIdExtractor

Action that reads the provider's external account identifier from an incoming payload so the event can be matched to a linked account.

Same fields as [actions](/connector-yaml-reference/yaml-schema/actions).

**Examples**

```yaml theme={null}
events:
  externalAccountIdExtractor:
    actionId: extract_account_id
    actionType: custom
    label: Extract account ID from event
    description: Map provider tenant ID to StackOne linked account.
    steps:
      - stepId: lookup
        stepFunction:
          functionName: request
          version: v1
          parameters:
            url: 'https://internal/accounts/by-tenant/${inputs.tenant_id}'
            method: get
    result: '${steps.lookup.output.data.linked_account_id}'
```

## guides

Manual webhook setup guides.

<table>
  <colgroup>
    <col width="210" />

    <col width="400" />

    <col width="90" />

    <col width="90" />
  </colgroup>

  <thead>
    <tr>
      <th>Field</th>
      <th>Description</th>
      <th>Type</th>
      <th>Required</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>[`setup`](#guides-setup)</td>
      <td>Guide for configuring webhooks in the provider UI.</td>
      <td>object</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

<AccordionGroup>
  <Accordion title="guides.setup">
    Guide for configuring webhooks in the provider UI.

    <table>
      <colgroup>
        <col width="210" />

        <col width="400" />

        <col width="90" />

        <col width="90" />
      </colgroup>

      <thead>
        <tr>
          <th>Field</th>
          <th>Description</th>
          <th>Type</th>
          <th>Required</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>[`sections`](#guides-setup-sections)</td>
          <td>Ordered sections making up the guide.</td>
          <td>object\[]</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`warning`</td>
          <td>Cautionary note shown at the top of the guide.</td>
          <td>string</td>
          <td>No</td>
        </tr>
      </tbody>
    </table>

    <AccordionGroup>
      <Accordion title="guides.setup.sections">
        Ordered sections making up the guide.

        <table>
          <colgroup>
            <col width="210" />

            <col width="400" />

            <col width="90" />

            <col width="90" />
          </colgroup>

          <thead>
            <tr>
              <th>Field</th>
              <th>Description</th>
              <th>Type</th>
              <th>Required</th>
            </tr>
          </thead>

          <tbody>
            <tr>
              <td>`applicableScopes`</td>
              <td>Scope names for which this section is shown. Space-separated, with any name that contains spaces wrapped in double quotes.</td>
              <td>string</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`content`</td>
              <td>Introductory text for the section.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>[`image`](#guides-setup-sections-image)</td>
              <td>Illustrative image for the section.</td>
              <td>object</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`list`</td>
              <td>Ordered items elaborating the section.</td>
              <td>string\[]</td>
              <td>No</td>
            </tr>

            <tr>
              <td>[`steps`](#guides-setup-sections-steps)</td>
              <td>Ordered steps making up the section.</td>
              <td>object\[]</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`title`</td>
              <td>Heading for this guide section.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>
          </tbody>
        </table>

        <AccordionGroup>
          <Accordion title="guides.setup.sections.image">
            Illustrative image for the section.

            <table>
              <colgroup>
                <col width="210" />

                <col width="400" />

                <col width="90" />

                <col width="90" />
              </colgroup>

              <thead>
                <tr>
                  <th>Field</th>
                  <th>Description</th>
                  <th>Type</th>
                  <th>Required</th>
                </tr>
              </thead>

              <tbody>
                <tr>
                  <td>`alt`</td>
                  <td>Alternative text describing the image.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`src`</td>
                  <td>Image URL or a path relative to the connector.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>

          <Accordion title="guides.setup.sections.steps">
            Ordered steps making up the section.

            <table>
              <colgroup>
                <col width="210" />

                <col width="400" />

                <col width="90" />

                <col width="90" />
              </colgroup>

              <thead>
                <tr>
                  <th>Field</th>
                  <th>Description</th>
                  <th>Type</th>
                  <th>Required</th>
                </tr>
              </thead>

              <tbody>
                <tr>
                  <td>`applicableScopes`</td>
                  <td>Scope names for which this step is shown. Space-separated, with any name that contains spaces wrapped in double quotes.</td>
                  <td>string</td>
                  <td>No</td>
                </tr>

                <tr>
                  <td>`content`</td>
                  <td>Body text describing what the user should do.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`displayScopes`</td>
                  <td>Whether the step shows badges for the actions its scopes unlock.</td>
                  <td>boolean</td>
                  <td>No</td>
                </tr>

                <tr>
                  <td>[`image`](#guides-setup-sections-steps-image)</td>
                  <td>Illustrative image for the step.</td>
                  <td>object</td>
                  <td>No</td>
                </tr>

                <tr>
                  <td>`list`</td>
                  <td>Ordered items elaborating the step.</td>
                  <td>string\[]</td>
                  <td>No</td>
                </tr>

                <tr>
                  <td>`title`</td>
                  <td>Heading for this guide step.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>

            <AccordionGroup>
              <Accordion title="guides.setup.sections.steps.image">
                Illustrative image for the step.

                <table>
                  <colgroup>
                    <col width="210" />

                    <col width="400" />

                    <col width="90" />

                    <col width="90" />
                  </colgroup>

                  <thead>
                    <tr>
                      <th>Field</th>
                      <th>Description</th>
                      <th>Type</th>
                      <th>Required</th>
                    </tr>
                  </thead>

                  <tbody>
                    <tr>
                      <td>`alt`</td>
                      <td>Alternative text describing the image.</td>
                      <td>string</td>
                      <td>Yes</td>
                    </tr>

                    <tr>
                      <td>`src`</td>
                      <td>Image URL or a path relative to the connector.</td>
                      <td>string</td>
                      <td>Yes</td>
                    </tr>
                  </tbody>
                </table>
              </Accordion>
            </AccordionGroup>
          </Accordion>
        </AccordionGroup>
      </Accordion>
    </AccordionGroup>
  </Accordion>
</AccordionGroup>

**Examples**

```yaml theme={null}
guides:
  setup:
    sections:
      - title: Enable webhooks
        content: Turn on event delivery in the provider dashboard.
        steps:
          - title: Open webhook settings
            content: Go to Settings, then Webhooks.
```

## router

Rules mapping incoming payloads to event actions.

<table>
  <colgroup>
    <col width="210" />

    <col width="400" />

    <col width="90" />

    <col width="90" />
  </colgroup>

  <thead>
    <tr>
      <th>Field</th>
      <th>Description</th>
      <th>Type</th>
      <th>Required</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>[`delivery`](#router-delivery)</td>
      <td>Rules matched against the whole delivery payload, rather than the individual events `itemsPath` splits it into. The first match short-circuits, so the per-event `rules` are skipped.</td>
      <td>object\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`itemsPath`</td>
      <td>Expression that splits a batched delivery payload into individual events, so each is routed on its own through `rules`. When omitted, the whole payload is treated as a single event.</td>
      <td>string</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`rules`](#router-rules)</td>
      <td>Rules matched in order against each individual event, where the first match maps it to an event action. Skipped when a `delivery` rule matches.</td>
      <td>object\[]</td>
      <td>Yes</td>
    </tr>
  </tbody>
</table>

<AccordionGroup>
  <Accordion title="router.delivery">
    Rules matched against the whole delivery payload, rather than the individual events `itemsPath` splits it into. The first match short-circuits, so the per-event `rules` are skipped.

    <table>
      <colgroup>
        <col width="210" />

        <col width="400" />

        <col width="90" />

        <col width="90" />
      </colgroup>

      <thead>
        <tr>
          <th>Field</th>
          <th>Description</th>
          <th>Type</th>
          <th>Required</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>[`then`](#router-delivery-then)</td>
          <td>Action to invoke when the rule matches.</td>
          <td>object</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`when`</td>
          <td>Expression evaluated against the incoming request. This rule is selected when the expression returns anything other than null, false, or undefined.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>

    <AccordionGroup>
      <Accordion title="router.delivery.then">
        Action to invoke when the rule matches.

        <table>
          <colgroup>
            <col width="210" />

            <col width="400" />

            <col width="90" />

            <col width="90" />
          </colgroup>

          <thead>
            <tr>
              <th>Field</th>
              <th>Description</th>
              <th>Type</th>
              <th>Required</th>
            </tr>
          </thead>

          <tbody>
            <tr>
              <td>`action`</td>
              <td>Event action id invoked when the rule matches.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`input`</td>
              <td>Expressions evaluated against the incoming request whose results become the invoked action's input.</td>
              <td>object</td>
              <td>No</td>
            </tr>
          </tbody>
        </table>
      </Accordion>
    </AccordionGroup>
  </Accordion>

  <Accordion title="router.rules">
    Rules matched in order against each individual event, where the first match maps it to an event action. Skipped when a `delivery` rule matches.

    <table>
      <colgroup>
        <col width="210" />

        <col width="400" />

        <col width="90" />

        <col width="90" />
      </colgroup>

      <thead>
        <tr>
          <th>Field</th>
          <th>Description</th>
          <th>Type</th>
          <th>Required</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>[`then`](#router-rules-then)</td>
          <td>Action to invoke when the rule matches.</td>
          <td>object</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`when`</td>
          <td>Expression evaluated against the incoming request. This rule is selected when the expression returns anything other than null, false, or undefined.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>

    <AccordionGroup>
      <Accordion title="router.rules.then">
        Action to invoke when the rule matches.

        <table>
          <colgroup>
            <col width="210" />

            <col width="400" />

            <col width="90" />

            <col width="90" />
          </colgroup>

          <thead>
            <tr>
              <th>Field</th>
              <th>Description</th>
              <th>Type</th>
              <th>Required</th>
            </tr>
          </thead>

          <tbody>
            <tr>
              <td>`action`</td>
              <td>Event action id invoked when the rule matches.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`input`</td>
              <td>Expressions evaluated against the incoming request whose results become the invoked action's input.</td>
              <td>object</td>
              <td>No</td>
            </tr>
          </tbody>
        </table>
      </Accordion>
    </AccordionGroup>
  </Accordion>
</AccordionGroup>

**Examples**

```yaml theme={null}
events:
  router:
    rules:
      - when: '${event.type == "user.created"}'
        then: { action: handle_user_created }

      - when: '${event.type == "user.updated" && event.changes.contains("email")}'
        then:
          action: handle_email_change
          input:
            user_id: '${event.data.id}'
            new_email: '${event.data.email}'
```

## setup

Programmatic webhook lifecycle configuration.

<table>
  <colgroup>
    <col width="210" />

    <col width="400" />

    <col width="90" />

    <col width="90" />
  </colgroup>

  <thead>
    <tr>
      <th>Field</th>
      <th>Description</th>
      <th>Type</th>
      <th>Required</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>[`activation`](#setup-activation)</td>
      <td>Optional phase that activates the receiver after creation.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`creation`](#setup-creation)</td>
      <td>Phase that registers the webhook receiver.</td>
      <td>object</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>[`deletion`](#setup-deletion)</td>
      <td>Phase that removes the webhook receiver.</td>
      <td>object</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`isConsolidated`</td>
      <td>Whether one receiver handles all events rather than one per event.<br />Default: `false`</td>
      <td>boolean</td>
      <td>Yes</td>
    </tr>
  </tbody>
</table>

<AccordionGroup>
  <Accordion title="setup.activation">
    Optional phase that activates the receiver after creation.

    <table>
      <colgroup>
        <col width="210" />

        <col width="400" />

        <col width="90" />

        <col width="90" />
      </colgroup>

      <thead>
        <tr>
          <th>Field</th>
          <th>Description</th>
          <th>Type</th>
          <th>Required</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>`result`</td>
          <td>Value produced by the phase, such as the created webhook id.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`steps`</td>
          <td>Ordered steps performed in this webhook phase.</td>
          <td>array</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>
  </Accordion>

  <Accordion title="setup.creation">
    Phase that registers the webhook receiver.

    <table>
      <colgroup>
        <col width="210" />

        <col width="400" />

        <col width="90" />

        <col width="90" />
      </colgroup>

      <thead>
        <tr>
          <th>Field</th>
          <th>Description</th>
          <th>Type</th>
          <th>Required</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>`result`</td>
          <td>Expression selecting the value this phase produces, such as the created receiver's remote id (e.g. `$.steps.create.output.data.id`), which later phases reference as `${inputs.remoteId}`.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`steps`</td>
          <td>Ordered steps performed in this webhook phase.</td>
          <td>array</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>
  </Accordion>

  <Accordion title="setup.deletion">
    Phase that removes the webhook receiver.

    <table>
      <colgroup>
        <col width="210" />

        <col width="400" />

        <col width="90" />

        <col width="90" />
      </colgroup>

      <thead>
        <tr>
          <th>Field</th>
          <th>Description</th>
          <th>Type</th>
          <th>Required</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>`result`</td>
          <td>Value produced by the phase, such as the created webhook id.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`steps`</td>
          <td>Ordered steps performed in this webhook phase.</td>
          <td>array</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>
  </Accordion>
</AccordionGroup>

**Examples**

```yaml theme={null}
events:
  setup:
    creation:
      steps:
        - stepId: create_webhook
          description: Register a webhook receiver.
          stepFunction:
            functionName: request
            version: v1
            parameters:
              url: /webhooks
              method: post
              args:
                - { name: url, value: '${inputs.callbackUrl}', in: body }
                - { name: events, value: '${inputs.eventTypes}', in: body }
      result: '$.id'

    activation:
      steps:
        - stepId: activate
          description: Mark webhook active.
          stepFunction:
            functionName: request
            version: v1
            parameters:
              url: '/webhooks/${inputs.remoteId}/activate'
              method: post

    deletion:
      steps:
        - stepId: delete_webhook
          description: Remove the receiver.
          stepFunction:
            functionName: request
            version: v1
            parameters:
              url: '/webhooks/${inputs.remoteId}'
              method: delete

    isConsolidated: false
```

## Related

<CardGroup cols={2}>
  <Card title="Actions overview" icon="book" href="/connector-yaml-reference/yaml-schema/actions#overview">
    The full action shape event actions and the extractor are built from.
  </Card>

  <Card title="Step functions: emit_event" icon="cube" href="/connector-yaml-reference/step-functions/emit-event">
    Fan out events to downstream subscribers.
  </Card>

  <Card title="Expression language" icon="book" href="/connector-yaml-reference/expression-language">
    JEXL syntax for the router's when rules.
  </Card>

  <Card title="Action steps" icon="cube" href="/connector-yaml-reference/yaml-schema/actions#steps">
    The step shape each setup phase reuses.
  </Card>
</CardGroup>
