Skip to main content
POST
`POST /orgs/{org_id}/connectors/{connector_id}/syncs`

Authorizations

Authorization
string
header
required

Timbal API key. Obtain your API key from the Timbal platform settings. See Authentication for more information.

Path Parameters

org_id
string
required
connector_id
string
required

Body

application/json
dest_table
string
required

Destination table inside the KB. Created by the first run when it doesn't exist yet; when it does, existing_dest decides whether the sync continues it or rebuilds it.

interval_secs
integer<int64>
required

Seconds between run starts. The scheduler ticks every 30s, so smaller values effectively mean "every tick".

kb_id
integer<int64>
required

Target KB (numeric id, same as the /k2 routes).

source
object
required

The source half of a dispatch, tagged by kind. Each variant maps to a SourceSpec and gates on the connector advertising the matching source:<kind> capability. Request shape: "source": { "kind": "sql_server", "connection_ref": "...", "table": "...", "cursor_column": "..." }.

existing_dest
null | enum<string>

How to treat a dest_table that already exists. Defaults to adopt. Only meaningful for an incremental sync — a full-refresh one replaces the destination on every run by definition.

Available options:
adopt,
replace
initial_cursor
object | null

Checkpoint to continue an existing dest_table from, overriding the one read off the table itself. Only valid when the table exists and existing_dest is adopt — for a table the sync still has to build, use start_cursor. Same shape as start_cursor.

key_columns
string[] | null

Ordered destination PRIMARY KEY columns. Omit for a keyless table. The first run declares the key; later runs then merge on it (upsert) so an upstream update — or a re-pulled boundary row from a non-unique cursor — overwrites in place instead of duplicating. Key columns are auto-added to a columns subset, so they only need to exist on the source table. Source these from the browse columns' pk_position.

name
string | null

Operator label.

start_cursor
object | null

Optional lower bound for the first run when it builds the table: only rows with cursor_column >= start_cursor are pulled (e.g. seed a timestamp to backfill "from last month on" instead of the whole table). Ignored on later runs — the advancing cursor takes over — and ignored when the sync adopts an existing table. Shape matches the job cursor (e.g. {"kind":"timestamp","value":"2026-06-01T00:00:00Z"}). Not valid on a full-refresh sync (no cursor_column to bound).

Response

Sync created

adopted_dest_table
boolean
required

true when the sync continues an existing destination table instead of building it on the first run.

key_columns
string[]
required

Primary-key columns the sync will merge on. Inherited from an adopted table's own key when the request didn't declare one.

sync_id
string
required
initial_cursor
object | null

The checkpoint the first run resumes from when the destination was adopted; null otherwise (including an adopted table that was empty).