> ## 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.

# Actions

> Field reference for the operations a connector exposes: inputs, steps, fieldConfigs, result, responses, cursor, dataSync, executionMode, compositeIdentifiers, validationRules, and examples.

## overview

<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>`actionId`</td>
      <td>Identifier for the action, prefixed with the connector key to form its MCP tool name.</td>
      <td>string</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`actionType`</td>
      <td>Operation kind the engine treats this action as.<br />Allowed: `list`, `get`, `create`, `update`, `delete`, `custom`, `refresh_token`, `event`, `unknown`</td>
      <td>enum</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>[`annotations`](#annotations)</td>
      <td>Explicit MCP tool-annotation overrides for the action.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`authRequirements`](#authrequirements)</td>
      <td>Per-authentication-method scopes required to run the action.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`categories`</td>
      <td>Business-domain classifications used for filtering the action.</td>
      <td>string\[]</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>[`compositeIdentifiers`](#compositeidentifiers)</td>
      <td>Configuration for building a record id from multiple provider fields.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`cursor`](#cursor)</td>
      <td>Engine-managed cursor pagination configuration.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`dataSync`](#datasync)</td>
      <td>Data Sync configuration for bulk syncing this action's records.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`description`</td>
      <td>Short description shown in the UI and MCP tool declarations.</td>
      <td>string</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`details`</td>
      <td>Extended context about the action for agents and developers.</td>
      <td>string</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`effects`](#effects)</td>
      <td>Semantic effects the action performs, used for MCP annotations and dashboard filtering.</td>
      <td>string\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`entrypointHttpMethod`</td>
      <td>HTTP method of the primary request.</td>
      <td>string</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`entrypointUrl`</td>
      <td>URL path of the action's primary request. Paired with `entrypointHttpMethod` to form the action key such as `GET /employees`, and used as the request log URL.</td>
      <td>string</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`examples`](#examples)</td>
      <td>Example input values for the action, each optionally labeled with `exampleDescription`.</td>
      <td>object\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`executionMode`</td>
      <td>Whether the action runs synchronously or is dispatched to an async workflow.<br />Allowed: `sync`, `async`</td>
      <td>enum</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`fieldConfigs`](#fieldconfigs)</td>
      <td>Field-level mapping and typing configuration for the result.</td>
      <td>array</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`inputs`](#inputs)</td>
      <td>Parameters the action accepts, forming its tool input schema.</td>
      <td>object\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`label`</td>
      <td>Human-readable display name for the action.</td>
      <td>string</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`prerequisiteActions`</td>
      <td>Action ids this action declares as dependencies.</td>
      <td>string\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`providerEvents`</td>
      <td>Provider event names this action handles.</td>
      <td>string\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`releaseStage`</td>
      <td>Maturity level of the action.<br />Allowed: `preview`, `beta`, `ga`, `deprecated`, `internal`</td>
      <td>enum</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`requiredScopes`</td>
      <td>Permission scopes required to run the action.</td>
      <td>string</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`resources`</td>
      <td>URL to provider documentation for this action.</td>
      <td>string</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`responses`](#responses)</td>
      <td>Documented HTTP responses the action can return.</td>
      <td>object\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`result`](#result)</td>
      <td>Data returned to the caller, given as an expression or a map of output keys to expressions.</td>
      <td>union</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`schema`</td>
      <td>Name of the output schema the action conforms to.</td>
      <td>string</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`schemaType`</td>
      <td>Whether the output follows the native provider shape or the unified StackOne schema.<br />Allowed: `native`, `unified`<br />Default: `native`</td>
      <td>enum</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>[`steps`](#steps)</td>
      <td>Ordered steps executed to carry out the action.</td>
      <td>array</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`tags`</td>
      <td>Free-form tags for grouping and filtering the action.</td>
      <td>string\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`validationRules`](#validationrules)</td>
      <td>Cross-field validation rules applied to the action inputs.</td>
      <td>array</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

<Accordion title="Action types">
  `actionType` tells the engine how to treat the operation.

  **Unified types (`list`, `get`, `create`, `update`, `delete`)** return normalized data:

  * Consistent response schemas across providers.
  * Cross-provider compatibility.
  * Automatic pagination handling.
  * Normalized error responses.

  A `list` action always returns `{ data: [...], next: <cursor or null> }`.

  **Custom** (`custom`) returns the raw provider response, with no schema normalization. Use it for provider-specific endpoints that need full flexibility.

  **Special-purpose types** are used in other blocks, not `actions[]`:

  * `event` — an event handler under [`events.actions`](/connector-yaml-reference/yaml-schema/events#actions) that runs when a matching provider event arrives (matched via `providerEvents`). Same shape as a regular action.
  * `refresh_token` — the credential-refresh action under [`refreshAuthentication`](/connector-yaml-reference/yaml-schema/authentication#refreshauthentication).
</Accordion>

**Examples**

```yaml theme={null}
actions:
  - actionId: list_tickets
    actionType: custom
    effects: [read]
    label: List tickets
    description: List tickets from the provider.
    inputs:
      - name: limit
        description: Maximum number of results to return.
        type: number
        in: query
        required: false
      - name: offset
        description: Number of results to skip.
        type: number
        in: query
        required: false
    steps:
      - stepId: list_tickets_request
        description: Fetch tickets from the provider.
        stepFunction:
          functionName: request
          parameters:
            url: /tickets
            method: get
            args:
              - name: limit
                value: $.inputs.limit
                in: query
                condition: '{{present(inputs.limit)}}'
              - name: offset
                value: $.inputs.offset
                in: query
                condition: '{{present(inputs.offset)}}'
    result:
      data: $.steps.list_tickets_request.output.data
```

## annotations

Explicit MCP tool-annotation overrides for the action.

<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>`destructiveHint`</td>
      <td>Whether the action may delete or overwrite data.</td>
      <td>boolean</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`idempotentHint`</td>
      <td>Whether repeating the action has no additional effect.</td>
      <td>boolean</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`openWorldHint`</td>
      <td>Whether the action interacts with an open, external world.</td>
      <td>boolean</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`readOnlyHint`</td>
      <td>Whether the action only reads data.</td>
      <td>boolean</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`title`</td>
      <td>Human-readable title exposed to MCP clients.</td>
      <td>string</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

**Examples**

```yaml theme={null}
annotations:
  title: List employees
  readOnlyHint: true
  destructiveHint: false
  idempotentHint: true
  openWorldHint: false
```

## authRequirements

Per-authentication-method scopes required to run the action.

**Examples**

```yaml theme={null}
authRequirements:
  oauth2:
    - employees:read
  api_key:
    - employees:read
```

## compositeIdentifiers

Configuration for building a record id from multiple provider fields.

<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>`enabled`</td>
      <td>Whether composite identifiers are built for records.</td>
      <td>boolean</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>[`fields`](#compositeidentifiers-fields)</td>
      <td>Field mappings that make up each composite identifier.</td>
      <td>object\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`version`</td>
      <td>Version of the composite identifier encoding.</td>
      <td>number</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

<AccordionGroup>
  <Accordion title="compositeIdentifiers.fields">
    Field mappings that make up each composite identifier.

    <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>`components`</td>
          <td>Ordered output field keys whose values combine into the identifier.</td>
          <td>string\[]</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`remote`</td>
          <td>Provider field the identifier component is read from.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`targetFieldKey`</td>
          <td>Key the composite identifier is written to.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>
  </Accordion>
</AccordionGroup>

**Examples**

```yaml theme={null}
compositeIdentifiers:
  enabled: true
  version: 1
  fields:
    - targetFieldKey: id
      remote: '$.record.identifier'
      components: [tenant_id, employee_id]
```

## cursor

Engine-managed cursor pagination 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>`enabled`</td>
      <td>Whether cursor pagination is enabled. Only applies to list actions and has no effect on others.</td>
      <td>boolean</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`pageSize`</td>
      <td>Number of records requested per page.</td>
      <td>number</td>
      <td>Yes</td>
    </tr>
  </tbody>
</table>

**Examples**

```yaml theme={null}
cursor:
  enabled: true
  pageSize: 100
```

## dataSync

Synced records are stored for reading with [Deep Query](/optimize/deep-query). See [Data Sync](/optimize/data-sync).

Data Sync configuration for bulk syncing this action's records.

<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>`allowed`</td>
      <td>Whether Data Sync is enabled for this action.</td>
      <td>boolean</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`dataKey`</td>
      <td>Path within the step output to the records array, used when the action returns them in a single call rather than paginating.</td>
      <td>string</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`incremental`](#datasync-incremental)</td>
      <td>Change-tracking configuration for incremental syncs.</td>
      <td>union</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`indexField`</td>
      <td>Field or fields forming each record's primary key during sync.</td>
      <td>union</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`maxDurationMinutes`</td>
      <td>Maximum time a single sync run may take.</td>
      <td>integer</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`maxPages`</td>
      <td>Maximum number of pages fetched in a single sync run.</td>
      <td>integer</td>
      <td>No</td>
    </tr>

    <tr>
      <td>[`pagination`](#datasync-pagination)</td>
      <td>Pagination strategy used while syncing.</td>
      <td>union</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

<AccordionGroup>
  <Accordion title="dataSync.incremental">
    Change-tracking configuration for incremental syncs.

    <Tabs>
      <Tab title="time_filter">
        <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>`format`</td>
              <td>Encoding of the timestamp value: `iso8601`, `unix_seconds`, or `unix_millis`.<br />Allowed: `iso8601`, `unix_seconds`, `unix_millis`</td>
              <td>enum</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>[`iterator`](#datasync-incremental-time-filter-iterator)</td>
              <td>Names the request parameter carrying the last-sync timestamp and where on the request to place it.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>[`response`](#datasync-incremental-time-filter-response)</td>
              <td>Configures reading the newest record timestamp from each page to advance the watermark.</td>
              <td>object</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`safetyBufferSeconds`</td>
              <td>Seconds subtracted from the run start time when falling back to the local clock so records near the boundary are not skipped.<br />Default: `60`</td>
              <td>integer</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`type`</td>
              <td>Selects the updated-since strategy where each sync requests only records changed after the last watermark.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>
          </tbody>
        </table>

        <AccordionGroup>
          <Accordion title="dataSync.incremental.time_filter.iterator">
            Names the request parameter carrying the last-sync timestamp and where on the request to place it.

            <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>`in`</td>
                  <td>Where to add the timestamp parameter: `query`, `body`, or `headers`.<br />Allowed: `query`, `body`, `headers`</td>
                  <td>enum</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`key`</td>
                  <td>Request parameter name the last-sync timestamp is sent under.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>

          <Accordion title="dataSync.incremental.time_filter.response">
            Configures reading the newest record timestamp from each page to advance the watermark.

            <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>`updatedAtPath`</td>
                  <td>Path within each returned record to its last-updated timestamp, read to advance the watermark.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>
        </AccordionGroup>
      </Tab>

      <Tab title="delta_token">
        <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>[`iterator`](#datasync-incremental-delta-token-iterator)</td>
              <td>Names the request parameter carrying the previous delta token and where on the request to place it.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>[`response`](#datasync-incremental-delta-token-response)</td>
              <td>Configures reading the next delta token from the response.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`type`</td>
              <td>Selects the delta-token strategy where each sync sends the token returned by the previous sync.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>
          </tbody>
        </table>

        <AccordionGroup>
          <Accordion title="dataSync.incremental.delta_token.iterator">
            Names the request parameter carrying the previous delta token and where on the request to place it.

            <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>`in`</td>
                  <td>Where to add the delta token: `query`, `body`, or `headers`.<br />Allowed: `query`, `body`, `headers`</td>
                  <td>enum</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`key`</td>
                  <td>Request parameter name the delta token is sent under.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>

          <Accordion title="dataSync.incremental.delta_token.response">
            Configures reading the next delta token from the response.

            <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>`onlyOnFinalPage`</td>
                  <td>When `true`, read the delta token only from the final page of results.</td>
                  <td>boolean</td>
                  <td>No</td>
                </tr>

                <tr>
                  <td>`path`</td>
                  <td>Path within the response to the delta token used for the next sync.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>
        </AccordionGroup>
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="dataSync.pagination">
    Pagination strategy used while syncing.

    <Tabs>
      <Tab title="cursor">
        <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>[`iterator`](#datasync-pagination-cursor-iterator)</td>
              <td>Request parameter that carries the next-page cursor.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>[`response`](#datasync-pagination-cursor-response)</td>
              <td>How records and the next-page cursor are located in the response.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`stopCondition`</td>
              <td>Expression evaluated against each response to stop paging. Defaults to stopping when the next-page cursor key is `null`.</td>
              <td>string</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`type`</td>
              <td>Selects the cursor-based pagination strategy.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>
          </tbody>
        </table>

        <AccordionGroup>
          <Accordion title="dataSync.pagination.cursor.iterator">
            Request parameter that carries the next-page cursor.

            <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>`in`</td>
                  <td>Where to add the pagination parameters: `query`, `body`, or `headers`.<br />Allowed: `query`, `body`, `headers`</td>
                  <td>enum</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`key`</td>
                  <td>Request parameter the next-page cursor is sent in.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>

          <Accordion title="dataSync.pagination.cursor.response">
            How records and the next-page cursor are located in the response.

            <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>`dataKey`</td>
                  <td>Response key holding the array of records for each page.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`nextKey`</td>
                  <td>Response key holding the cursor for the next page.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>
        </AccordionGroup>
      </Tab>

      <Tab title="offset">
        <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>[`iterator`](#datasync-pagination-offset-iterator)</td>
              <td>Request parameters that page through results by offset and limit.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>[`response`](#datasync-pagination-offset-response)</td>
              <td>How each page of records is located in the response.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`stopCondition`</td>
              <td>Expression evaluated against each response to stop paging. Defaults to stopping when the data key returns no records.</td>
              <td>string</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`type`</td>
              <td>Selects the offset-based pagination strategy.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>
          </tbody>
        </table>

        <AccordionGroup>
          <Accordion title="dataSync.pagination.offset.iterator">
            Request parameters that page through results by offset and limit.

            <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>`defaultLimit`</td>
                  <td>Number of records requested per page. Defaults to `100` when omitted.</td>
                  <td>number</td>
                  <td>No</td>
                </tr>

                <tr>
                  <td>`in`</td>
                  <td>Where to add the pagination parameters: `query`, `body`, or `headers`.<br />Allowed: `query`, `body`, `headers`</td>
                  <td>enum</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`limitKey`</td>
                  <td>Request parameter set to the number of records requested per page.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`offsetKey`</td>
                  <td>Request parameter set to the number of records to skip for each page.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>

          <Accordion title="dataSync.pagination.offset.response">
            How each page of records is located in the response.

            <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>`dataKey`</td>
                  <td>Response key holding the array of records for each page.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>
        </AccordionGroup>
      </Tab>

      <Tab title="page">
        <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>[`iterator`](#datasync-pagination-page-iterator)</td>
              <td>Request parameters that page through results by page number.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>[`response`](#datasync-pagination-page-response)</td>
              <td>How each page of records is located in the response.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`stopCondition`</td>
              <td>Expression evaluated against each response to stop paging. Defaults to stopping when the data key returns no records.</td>
              <td>string</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`type`</td>
              <td>Selects the page-number pagination strategy.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>
          </tbody>
        </table>

        <AccordionGroup>
          <Accordion title="dataSync.pagination.page.iterator">
            Request parameters that page through results by page number.

            <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>`defaultPageSize`</td>
                  <td>Number of records requested per page. Defaults to `100` when omitted.</td>
                  <td>number</td>
                  <td>No</td>
                </tr>

                <tr>
                  <td>`in`</td>
                  <td>Where to add the pagination parameters: `query`, `body`, or `headers`.<br />Allowed: `query`, `body`, `headers`</td>
                  <td>enum</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`pageKey`</td>
                  <td>Request parameter set to the page number for each request.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>

                <tr>
                  <td>`pageSizeKey`</td>
                  <td>Request parameter set to the number of records requested per page. Omit when the endpoint takes no page-size parameter.</td>
                  <td>string</td>
                  <td>No</td>
                </tr>

                <tr>
                  <td>`startPage`</td>
                  <td>Page number requested for the first page. Defaults to `1` when omitted.</td>
                  <td>number</td>
                  <td>No</td>
                </tr>
              </tbody>
            </table>
          </Accordion>

          <Accordion title="dataSync.pagination.page.response">
            How each page of records is located in the response.

            <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>`dataKey`</td>
                  <td>Response key holding the array of records for each page.</td>
                  <td>string</td>
                  <td>Yes</td>
                </tr>
              </tbody>
            </table>
          </Accordion>
        </AccordionGroup>
      </Tab>
    </Tabs>
  </Accordion>
</AccordionGroup>

**Examples**

<Tabs>
  <Tab title="cursor">
    ```yaml theme={null}
    dataSync:
      allowed: true
      indexField: id
      pagination:
        type: cursor
        response:
          dataKey: data
          nextKey: next
        iterator:
          key: next
          in: query
      incremental: { ... }
    ```
  </Tab>

  <Tab title="offset">
    ```yaml theme={null}
    dataSync:
      allowed: true
      indexField: id
      pagination:
        type: offset
        response:
          dataKey: data.data
        iterator:
          offsetKey: offset
          limitKey: limit
          in: query
      incremental: { ... }
    ```
  </Tab>

  <Tab title="page">
    ```yaml theme={null}
    dataSync:
      allowed: true
      indexField: id
      pagination:
        type: page
        response:
          dataKey: data.records
        iterator:
          pageKey: page
          pageSizeKey: per_page
          startPage: 1
          in: query
      incremental: { ... }
    ```
  </Tab>
</Tabs>

<Tabs>
  <Tab title="time_filter">
    ```yaml theme={null}
    dataSync:
      allowed: true
      indexField: id
      pagination: { ... }
      incremental:
        type: time_filter
        iterator:
          key: updated_since
          in: query
        format: iso8601
    ```
  </Tab>

  <Tab title="delta_token">
    ```yaml theme={null}
    dataSync:
      allowed: true
      indexField: id
      pagination: { ... }
      incremental:
        type: delta_token
        iterator:
          key: after
          in: query
        response:
          path: data.cursor
    ```
  </Tab>
</Tabs>

## effects

Semantic effects the action performs, used for MCP annotations and dashboard filtering. Optional, but worth setting on every action so an MCP client can auto-approve reads and prompt before writes.

| Effect    | Use for                                                          |
| --------- | ---------------------------------------------------------------- |
| `read`    | Fetching a record or a list. Changes nothing.                    |
| `search`  | Querying with filters. Changes nothing.                          |
| `write`   | Creating or updating records.                                    |
| `delete`  | Removing records.                                                |
| `execute` | Operations that aren't CRUD: send, sync, deploy, approve, merge. |

An action can carry more than one effect. A find-or-create gets `[read, write]`.

<Accordion title="How effects become MCP annotations">
  | Annotation        | Derived from                                              |
  | ----------------- | --------------------------------------------------------- |
  | `readOnlyHint`    | `true` when every effect is `read` or `search`.           |
  | `destructiveHint` | `true` when effects include `delete`.                     |
  | `openWorldHint`   | Always `true`, since actions call external provider APIs. |
  | `title`           | The action's `label`.                                     |
  | `idempotentHint`  | Never derived. Set it with `annotations`.                 |

  With no `effects` and no `annotations` override, no hints are emitted, so a read looks no safer than a delete.
</Accordion>

<Warning>
  Annotations are hints, not enforcement. Clients use them for grouping and approval defaults, not as a security boundary. To actually restrict what a linked account can call, disable the actions on its Connector Profile. See [Scoping connectors](/secure/scoping-connectors).
</Warning>

**Examples**

```yaml theme={null}
effects:
  - read
```

## examples

Example input values for the action, each optionally labeled with `exampleDescription`.

<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>`exampleDescription`</td>
      <td>Explains what this usage example demonstrates.</td>
      <td>string</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

**Examples**

```yaml theme={null}
examples:
  - exampleDescription: Fetch a single active employee.
    input:
      employee_id: emp_123
    output:
      id: emp_123
      name: Ada Lovelace
      status: active

  - exampleDescription: Employee not found.
    input:
      employee_id: emp_does_not_exist
    output:
      error: not_found
      statusCode: 404
```

## fieldConfigs

Field-level mapping and typing configuration for the result.

**Examples**

```yaml theme={null}
fieldConfigs:
  - targetFieldKey: id
    alias: employee_id
    type: string
  - targetFieldKey: name
    expression: '${item.first_name} ${item.last_name}'
    type: string
  - targetFieldKey: country
    alias: country_code
    type: string
    enumMapper:
      matcher: country_alpha2code_by_country_name
  - targetFieldKey: address
    type: object
    properties:
      - { targetFieldKey: street, alias: street_address, type: string }
      - { targetFieldKey: city, alias: city, type: string }
  - targetFieldKey: salary
    type: number
    requiredScopes: read:compensation   # hidden if scope not granted
```

## inputs

Parameters the action accepts, forming its tool input schema.

<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>`array`</td>
      <td>Whether the input accepts a list of values.<br />Default: `false`</td>
      <td>boolean</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`arrayFormat`</td>
      <td>How a list input's values are formatted in the request, such as repeated, comma-separated, or bracketed. Currently not in use.<br />Allowed: `repeat`, `brackets`, `comma`, `stringify`</td>
      <td>enum</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`description`</td>
      <td>Explains the input for callers and generated tool schemas.</td>
      <td>string</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`in`</td>
      <td>Part of the HTTP request this input is placed in.<br />Allowed: `body`, `query`, `path`, `headers`</td>
      <td>enum</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`name`</td>
      <td>Parameter name exposed to callers and mapped into the request.</td>
      <td>string</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>[`oneOf`](#inputs-oneof)</td>
      <td>Allowed values when the input is an enum.</td>
      <td>union</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`properties`</td>
      <td>Nested inputs when the input is an object.</td>
      <td>object\[]</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`required`</td>
      <td>Whether the caller must supply this input.</td>
      <td>boolean</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>[`rules`](#inputs-rules)</td>
      <td>Validation rules applied to the input value.</td>
      <td>object</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`type`</td>
      <td>Data type of the input value.<br />Allowed: `string`, `number`, `boolean`, `datetime_string`, `object`, `enum`</td>
      <td>enum</td>
      <td>No</td>
    </tr>

    <tr>
      <td>`variants`</td>
      <td>Alternative typed shapes the input may take.</td>
      <td>object\[]</td>
      <td>No</td>
    </tr>
  </tbody>
</table>

<AccordionGroup>
  <Accordion title="inputs.oneOf">
    Allowed values when the input is an enum.

    <Tabs>
      <Tab title="Option 1">
        <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>`values`</td>
              <td>Explicit list of allowed enum values.</td>
              <td>string\[]</td>
              <td>Yes</td>
            </tr>
          </tbody>
        </table>
      </Tab>

      <Tab title="Option 2">
        <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>`ref`</td>
              <td>Name of a shared enum definition supplying the allowed values. One of: `employment_status`, `employment_type`, `gender`, `marital_status`.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>
          </tbody>
        </table>
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="inputs.rules">
    Validation rules applied to the input value.

    <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>`errorMessage`</td>
          <td>Message shown when the value violates a rule.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`format`</td>
          <td>Named format the value must conform to.<br />Allowed: `email`, `url`, `uri`, `uuid`, `date`, `datetime`</td>
          <td>enum</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`max`</td>
          <td>Maximum numeric value allowed.</td>
          <td>number</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`maxLength`</td>
          <td>Maximum number of characters the value may have.</td>
          <td>number</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`min`</td>
          <td>Minimum numeric value allowed.</td>
          <td>number</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`minLength`</td>
          <td>Minimum number of characters the value must have.</td>
          <td>number</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`pattern`</td>
          <td>Regular expression the value must match.</td>
          <td>string</td>
          <td>No</td>
        </tr>
      </tbody>
    </table>
  </Accordion>
</AccordionGroup>

**Examples**

```yaml theme={null}
inputs:
  - name: employee_id
    type: string
    required: true
    in: path
    description: Provider's employee identifier.

  - name: status
    type: enum
    required: false
    in: query
    description: Filter by employment status.
    oneOf:
      values: [active, inactive, terminated]

  - name: hire_date
    type: datetime_string
    required: false
    in: body
    description: ISO 8601 hire date.
    rules:
      format: date

  - name: skills
    type: string
    array: true
    arrayFormat: comma
    in: query
    description: Comma-separated skill filter.

  - name: destination
    in: body
    required: true
    description: Where to send the payload. The type field selects the variant.
    variants:
      - type: object
        description: Post to a webhook URL.
        properties:
          - name: type
            type: enum
            required: true
            oneOf:
              values: [webhook]
          - name: url
            type: string
            required: true
      - type: object
        description: Send to an email address.
        properties:
          - name: type
            type: enum
            required: true
            oneOf:
              values: [email]
          - name: address
            type: string
            required: true
```

## responses

Documented HTTP responses the action can return.

<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>`description`</td>
      <td>What this response status means.</td>
      <td>string</td>
      <td>Yes</td>
    </tr>

    <tr>
      <td>`statusCode`</td>
      <td>HTTP status code being documented.</td>
      <td>number</td>
      <td>Yes</td>
    </tr>
  </tbody>
</table>

**Examples**

```yaml theme={null}
responses:
  - statusCode: 200
    description: Employee record returned.
  - statusCode: 404
    description: No employee found with the provided ID.
  - statusCode: 409
    description: Conflicts with an existing record; check inputs.
```

## result

Data returned to the caller, given as an expression or a map of output keys to expressions.

**Examples**

<Tabs>
  <Tab title="Expression">
    ```yaml theme={null}
    result: '${steps.cast.output.data}'
    ```
  </Tab>

  <Tab title="Object map">
    ```yaml theme={null}
    result:
      user: '${steps.fetch_user.output.data}'
      team: '${steps.fetch_team.output.data}'
      last_synced_at: '{{now()}}'
    ```
  </Tab>
</Tabs>

## steps

See [Step Functions](/connector-yaml-reference/step-functions/overview) for the full catalog and their parameters.

Ordered steps executed to carry out the action.

<Tabs>
  <Tab title="Single 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>`condition`</td>
          <td>Expression gating whether this step runs.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`description`</td>
          <td>Explains what this step does.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`ignoreError`</td>
          <td>Whether a failure in this step is ignored so execution continues.</td>
          <td>boolean</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`onConditionError`</td>
          <td>How to behave when the condition expression errors.<br />Allowed: `true`, `false`, `break`</td>
          <td>enum</td>
          <td>No</td>
        </tr>

        <tr>
          <td>[`stepFunction`](#steps-single-step-stepfunction)</td>
          <td>Step function executed by this step.</td>
          <td>object</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`stepId`</td>
          <td>Identifier for this step, used to reference its output.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>

    <AccordionGroup>
      <Accordion title="steps.Single step.stepFunction">
        Step function executed by this 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>`functionName`</td>
              <td>Name of the step function to execute.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`parameters`</td>
              <td>Arguments passed to the step function.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`version`</td>
              <td>Version of the step function to use.</td>
              <td>string</td>
              <td>No</td>
            </tr>
          </tbody>
        </table>
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Iterator 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>`condition`</td>
          <td>Expression gating whether this step runs.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`description`</td>
          <td>Explains what this step does.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`ignoreError`</td>
          <td>Whether a failure in this step is ignored so execution continues.</td>
          <td>boolean</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`iterator`</td>
          <td>Expression that produces the array this step loops over. The step function(s) run once per item until the array is exhausted, halting early if an item fails and `ignoreError` is not set.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`onConditionError`</td>
          <td>How to behave when the condition expression errors.<br />Allowed: `true`, `false`, `break`</td>
          <td>enum</td>
          <td>No</td>
        </tr>

        <tr>
          <td>[`stepFunction`](#steps-iterator-step-stepfunction)</td>
          <td>Step function run for each iterated item. Provide this or `stepFunctions`, not both.</td>
          <td>object</td>
          <td>No</td>
        </tr>

        <tr>
          <td>[`stepFunctions`](#steps-iterator-step-stepfunctions)</td>
          <td>Step functions run in sequence for each iterated item. Provide this or `stepFunction`, not both.</td>
          <td>object\[]</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`stepId`</td>
          <td>Identifier for this step, used to reference its output.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>

    <AccordionGroup>
      <Accordion title="steps.Iterator step.stepFunction">
        Step function run for each iterated item. Provide this or `stepFunctions`, not both.

        <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>`functionName`</td>
              <td>Name of the step function to execute.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`parameters`</td>
              <td>Arguments passed to the step function.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`version`</td>
              <td>Version of the step function to use.</td>
              <td>string</td>
              <td>No</td>
            </tr>
          </tbody>
        </table>
      </Accordion>

      <Accordion title="steps.Iterator step.stepFunctions">
        Step functions run in sequence for each iterated item. Provide this or `stepFunction`, not both.

        <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>`functionName`</td>
              <td>Name of the step function to execute.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`parameters`</td>
              <td>Arguments passed to the step function.</td>
              <td>object</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`version`</td>
              <td>Version of the step function to use.</td>
              <td>string</td>
              <td>No</td>
            </tr>
          </tbody>
        </table>
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

## validationRules

Cross-field validation rules applied to the action inputs.

<Tabs>
  <Tab title="atLeastOneOf">
    <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>`errorMessage`</td>
          <td>Message shown when the rule is violated.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`fields`</td>
          <td>Input names of which at least one must be provided.</td>
          <td>string\[]</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`rule`</td>
          <td>Requires at least one of the listed inputs to be provided.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>
  </Tab>

  <Tab title="requiredIf">
    <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>[`condition`](#validationrules-requiredif-condition)</td>
          <td>Condition under which the field is required.</td>
          <td>object</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`errorMessage`</td>
          <td>Message shown when the rule is violated.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`field`</td>
          <td>Input that becomes required when the condition holds.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`rule`</td>
          <td>Requires an input when another field satisfies a condition.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>

    <AccordionGroup>
      <Accordion title="validationRules.requiredIf.condition">
        Condition under which the field is required.

        <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>`equals`</td>
              <td>Condition holds when the referenced field equals this value.</td>
              <td>string</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`field`</td>
              <td>Name of the other input this condition inspects.</td>
              <td>string</td>
              <td>Yes</td>
            </tr>

            <tr>
              <td>`notEquals`</td>
              <td>Condition holds when the referenced field does not equal this value.</td>
              <td>string</td>
              <td>No</td>
            </tr>

            <tr>
              <td>`present`</td>
              <td>When true, the condition holds if the referenced field is present. When false, it holds if the field is absent.</td>
              <td>boolean</td>
              <td>No</td>
            </tr>
          </tbody>
        </table>
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="mutuallyExclusive">
    <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>`errorMessage`</td>
          <td>Message shown when the rule is violated.</td>
          <td>string</td>
          <td>No</td>
        </tr>

        <tr>
          <td>`fields`</td>
          <td>Input names of which at most one may be provided.</td>
          <td>string\[]</td>
          <td>Yes</td>
        </tr>

        <tr>
          <td>`rule`</td>
          <td>Allows at most one of the listed inputs to be provided.</td>
          <td>string</td>
          <td>Yes</td>
        </tr>
      </tbody>
    </table>
  </Tab>
</Tabs>

**Examples**

<Tabs>
  <Tab title="atLeastOneOf">
    ```yaml theme={null}
    validationRules:
      - rule: atLeastOneOf
        fields: [email, employee_id]
        errorMessage: Provide either email or employee_id.
    ```
  </Tab>

  <Tab title="requiredIf">
    ```yaml theme={null}
    validationRules:
      - rule: requiredIf
        field: termination_date
        condition: { field: status, equals: terminated }
        errorMessage: termination_date is required when status is "terminated".
    ```
  </Tab>

  <Tab title="mutuallyExclusive">
    ```yaml theme={null}
    validationRules:
      - rule: mutuallyExclusive
        fields: [start_date, anchor_date]
        errorMessage: Use one of start_date or anchor_date, not both.
    ```
  </Tab>
</Tabs>

## Related

<CardGroup cols={2}>
  <Card title="Step functions" icon="book" href="/connector-yaml-reference/step-functions/overview">
    Full catalog of stepFunction implementations.
  </Card>

  <Card title="Expression language" icon="book" href="/guides/connector-engine/expression-language">
    JEXL syntax for condition, iterator, result, and step inputs.
  </Card>
</CardGroup>
