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

# Create Warehouse Sync

> Import contacts or events from a warehouse query on a schedule

Creates a sync. Each run executes the query and sends only rows that changed since they were last sent:

* **subscribers** syncs create and update contacts through the same pipeline as [imports](/api-reference/subscribers/import-create), with duplicate strategy `overwrite`: mapped values replace stored ones, empty values never clear data, tags are only added, and unsubscribed contacts are never resubscribed.
* **events** syncs record events on contacts that already exist. Events older than an hour are stored as history and never start automations.

The mapping and cursor column are checked against the query's real columns, and the first run starts right away.

Requires `warehouse:write` and `subscribers:write`. Event syncs also need `events:write`. `triggerAutomations: true` or `optInMode: "double_opt_in"` need `automations:trigger`.

## Request

<ParamField body="connectionId" type="string" required />

<ParamField body="name" type="string" required />

<ParamField body="kind" type="string" required>
  `subscribers` or `events`.
</ParamField>

<ParamField body="query" type="string" required>
  A single `SELECT` or `WITH` statement.
</ParamField>

<ParamField body="mapping" type="object" required>
  Column names as the query returns them (Snowflake returns unquoted names in upper case).

  **subscribers**: `emailColumn` (or `phoneColumn` for SMS-only contacts), `externalIdColumn`, `firstNameColumn`, `lastNameColumn`, `tagsColumn` (array or comma-separated string) and `attributes`, a list of `{ "column", "attribute" }` pairs.

  **events**: `emailColumn` or `externalIdColumn` to find the contact, `eventNameColumn` or a fixed `eventName`, `eventIdColumn` (stable ID; derived from the row when omitted), `occurredAtColumn` (defaults to the sync time) and `properties`, a list of `{ "column", "property" }` pairs.
</ParamField>

<ParamField body="cursorColumn" type="string | null">
  A column that grows when a row changes, such as `updated_at`. Each run reads
  only rows at or after the last value it saw. Without a cursor, every run reads
  the whole result (up to 2,000,000 rows) and skips unchanged rows.
</ParamField>

<ParamField body="frequency" type="string" default="daily">
  `every_15_minutes`, `hourly`, `daily`, `weekly` or `manual`.
</ParamField>

<ParamField body="listIds" type="string[]">
  Subscriber syncs: lists that contacts the sync creates join. Existing contacts
  keep their list memberships.
</ParamField>

<ParamField body="optInMode" type="string" default="confirmed">
  Subscriber syncs: `confirmed` for contacts whose consent is already verified,
  or `double_opt_in` to email new contacts a confirmation first.
</ParamField>

<ParamField body="triggerAutomations" type="boolean" default="false">
  Let new contacts, or events from the last hour, start automations.
</ParamField>

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/warehouse-syncs" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "connectionId": "wconn_abc123",
    "name": "Customers",
    "kind": "subscribers",
    "query": "select email, first_name, plan, updated_at from analytics.customers",
    "mapping": {
      "emailColumn": "EMAIL",
      "firstNameColumn": "FIRST_NAME",
      "attributes": [{ "column": "PLAN", "attribute": "plan" }]
    },
    "cursorColumn": "UPDATED_AT",
    "frequency": "hourly"
  }'
```

<ResponseExample>
  ```json 201 theme={null}
  {
    "success": true,
    "sync": {
      "id": "wsync_abc123",
      "connectionId": "wconn_abc123",
      "name": "Customers",
      "kind": "subscribers",
      "query": "select email, first_name, plan, updated_at from analytics.customers",
      "mapping": {
        "emailColumn": "EMAIL",
        "firstNameColumn": "FIRST_NAME",
        "attributes": [
          {
            "column": "PLAN",
            "attribute": "plan"
          }
        ]
      },
      "cursorColumn": "UPDATED_AT",
      "cursorValue": null,
      "listIds": [],
      "optInMode": "confirmed",
      "triggerAutomations": false,
      "frequency": "hourly",
      "isEnabled": true,
      "fullResyncRequested": false,
      "status": "queued",
      "nextRunAt": "2026-09-30T13:00:00.000Z",
      "lastRunAt": "2026-09-30T12:00:00.000Z",
      "lastSuccessAt": "2026-09-30T12:00:41.000Z",
      "lastError": null,
      "lastErrorAt": null,
      "consecutiveFailures": 0,
      "latestRun": null,
      "createdAt": "2026-09-30T10:00:00.000Z",
      "updatedAt": "2026-09-30T12:00:41.000Z"
    }
  }
  ```

  ```json 400 theme={null}
  {
    "success": false,
    "code": "invalid_mapping",
    "error": "emailColumn \"MAIL\" is not a column of the query. Available columns: EMAIL, FIRST_NAME, PLAN, UPDATED_AT."
  }
  ```

  ```json 403 theme={null}
  {
    "success": false,
    "code": "missing_scope",
    "error": "Starting automations or sending double opt-in emails from a sync requires the automations:trigger permission."
  }
  ```
</ResponseExample>


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