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

# Data Sync Events

> Get notified at a webhook when a synced record is created, updated, or deleted, including for providers that have no webhooks of their own.

[Data Sync](/optimize/data-sync/overview) can send an [event](/gateway/concepts/events) to a webhook for every record a run creates, updates, or deletes. StackOne works out the changes itself by comparing each run's records with the ones it already stored.

Events are configured per action on a [Connector Profile](/gateway/concepts/connector-profiles), and every Linked Account with sync enabled for the action sends them.

## Turn on events for an action

Events are delivered to a webhook in your project. If you don't have one yet, add it on the [Webhooks](/connect/webhooks#quickstart) page first, or create it from the connector page in step 4.

<Steps>
  <Step title="Open the connector">
    Go to **Connectors**, open the connector, and select a saved Connector Profile. The action has to be switched on in that profile.
  </Step>

  <Step title="Open the action's Data Sync panel">
    Click the Data Sync icon on the action's row (**Set up Data Sync**).
  </Step>

  <Step title="Choose which changes to send">
    1. Turn on **Enable Data Sync**, if it isn't on already. The event toggles stay disabled until it is.
    2. Under **Events**, turn on **Created Events**, **Updated Events**, **Deleted Events**, or any combination.
  </Step>

  <Step title="Pick the webhook">
    Select the webhook under **Deliver to**, or choose **+ Add Webhook** to create one.
  </Step>

  <Step title="Save">
    Click **Save Changes**. Events start with the next run of each Linked Account's sync.
  </Step>
</Steps>

Subscribed actions show on the webhook's **Events** tab under **Connector**, tagged **Data Sync**, with a row for each change type. Each change type shows **Active**, or **Paused** when it's turned off or sync for the action isn't running.

## When events are sent

Events go out once a run finishes, not the moment a record changes at the provider. How soon you hear about a change depends on **Sync every**.

| Situation | What is sent |
| - | - |
| A Linked Account's first run | Nothing. The first run sets the baseline that later runs are compared with, so it sends no `created` event for the records that already existed |
| The first run after sync was switched off for more than 30 days | Nothing. The stored records [expire after 30 days](/optimize/data-sync/overview#limits) without a run, so this run sets a new baseline, the same as a Linked Account's first run |
| An incremental run | `created` and `updated` events for the records it fetched |
| A full run | `created` and `updated` events, plus `deleted` for every previously stored record that is no longer at the provider |
| A run that fails, or [stops early](/optimize/data-sync/overview#runs-that-stop-early) | Nothing for that run |
| A record that didn't change | Nothing |

<Warning>
  `deleted` events only come from a full run, for the same reason [deletions only surface on one](/optimize/data-sync/overview#full-and-incremental-runs). Set **Full re-sync** to match how quickly you need to hear about deletions.
</Warning>

## Event payload

The event name is the action ID followed by the change:

* `{action_id}.created`: a record that wasn't in the stored set when the run started.
* `{action_id}.updated`: a stored record whose fields changed since the last run.
* `{action_id}.deleted`: a stored record a full run no longer found at the provider.

For example, `bamboohr_list_employees.updated`. Each change is its own request to your webhook.

| Field | Type | Description |
| - | - | - |
| `event` | string | The event name, as above |
| `project_id` | string | The project the Connector Profile belongs to |
| `account_id` | string | The Linked Account the record was synced from |
| `record_type` | string | The action ID |
| `record_id` | string | The record's ID, taken from the field the action syncs on |
| `event_date` | string (ISO 8601) | When StackOne prepared the event, after the run finished |
| `sent_at` | string (ISO 8601) | When this delivery attempt was sent. Each retry gets a new value |
| `event_data` | object | The full record as Data Sync stored it, the same shape Deep Query returns. Left out of `deleted` events, since the record is gone |

```json theme={null}
{
  "project_id": "proj_7f3a9c",
  "account_id": "acc_42d1e8",
  "event": "bamboohr_list_employees.updated",
  "event_date": "2026-09-29T09:15:02.114Z",
  "record_type": "bamboohr_list_employees",
  "record_id": "4127",
  "sent_at": "2026-09-29T09:15:02.530Z",
  "event_data": {
    "id": "4127",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "work_email": "ada@example.com",
    "department": "Engineering"
  }
}
```

`event_data` is read from the stored record when the event is prepared, after the run finishes. On a large run, preparing every event can take long enough for the next run to change the stored record first:

* If the next run updates the record, the event carries the newer version.
* If the next run removes the record, the event isn't sent, since there's no record left to send.

## Delivery

Data Sync events are signed like every other webhook event, so the same [signature verification](/connect/webhooks#verifying-webhook-signatures) applies. Their delivery works as follows:

* A delivery that doesn't get a `2xx` response is retried, starting after 5 seconds and backing off to every 10 minutes, for up to 20 attempts.
* StackOne sends each change from a run once per webhook, and its own retries don't create duplicates. Your endpoint can still receive the same event twice if it returned `200` but the response was lost, so treat a repeat of the same `event`, `record_id`, and `event_date` as a duplicate.
* Events arrive in batches and several are sent at once, so they aren't guaranteed to arrive in the order the records changed.

Every delivery attempt is logged. **View logs** at the top of the webhook's page lists them. **View logs** on a Data Sync row in the webhook's **Events** tab opens that action's sync runs instead, with **Background Logs** turned on.

## Next steps

<CardGroup cols={2}>
  <Card title="Data Sync" icon="arrows-rotate" href="/optimize/data-sync/overview">
    Turn on sync for an action and set how often it runs.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/connect/webhooks">
    Create the webhook Data Sync events are delivered to, and verify their signatures.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.