---
title: "Trigger a sync for a feed"
method: POST
path: "/v1/feeds/{fid}/sync"
tags: ["Syncs"]
---

# Trigger a sync for a feed

`POST /v1/feeds/{fid}/sync`

## Request

- Base URL: `https://api.banksync.io`
- URL: `https://api.banksync.io/v1/feeds/{fid}/sync`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Creates a sync job and queues it for execution. By default, transaction feeds use incremental (cursor-based) syncing. Pass startDate and endDate (YYYY-MM-DD) in the JSON body for a specific date range. Trade feeds always require a date range. Poll GET /feeds/:fid/jobs/:jid to monitor progress.

If a previous sync is already running (or its lock is stuck), this endpoint returns 409. Two recovery options: set `forceCancelActive: true` to cancel the active sync and start a fresh one, or DELETE /feeds/:fid/jobs/:jid to cancel the specific in-flight job. Pass `resetCursors: true` to clear cursors before fetching (full re-sync); pass `skipDedup: true` to bypass per-record dedup for backfills.

A feed that is not fully configured returns 400 with the missing piece named, and no job is created — `forceCancelActive` does not override this.

## Path parameters

- `fid` string, required: Feed ID

## Request body

- TriggerSyncBody
  - `startDate` string: Start date (YYYY-MM-DD) for date-range syncs (transactions, trades).
  - `endDate` string: End date (YYYY-MM-DD) for date-range syncs (transactions, trades).
  - `forceCancelActive` boolean: When true, cancel any currently-running sync on this feed before starting the new one. Use this for user-initiated retries when the previous sync is stuck. Defaults to false.
  - `resetCursors` boolean: When true, clear all per-bank cursors, tier-1/tier-2 dedup state, and the date-based watermark before fetching. Use for backfills or recovery when the incremental cursor has gone stale. Defaults to false (normal incremental sync).
  - `skipDedup` boolean: When true, bypass the per-record dedup guard for this run. Use for backfills where upstream IDs are known-stable but downstream dedup has drifted. Defaults to false.

## Response `201`

Sync job created

- object
  - `success` true, required
  - `data` object, required
    - `id` string, required
    - `userId` string, required
    - `feedId` string, required: The feed this job belongs to
    - `workspaceId` string
    - `status` 'created' | 'in_progress' | 'paused' | 'completed' | 'failed' | 'cancelled', required
    - `type` 'manual' | 'scheduled' | 'webhook', required
    - `startDate` string
    - `endDate` string
    - `transactionsProcessed` number, required
    - `transactionsWritten` number, required
    - `errors` object[], required
      - `timestamp` string, required
      - `message` string, required
      - `category` string
      - `severity` string
    - `messages` string[]
    - `deliverySummary` object
      - `created` integer, required
      - `duplicate` integer, required
      - `baseline` integer, required
      - `held` integer, required
      - `skippedCurrency` integer, required
      - `skippedUnmapped` integer, required
      - `skippedZero` integer, required
      - `skippedInvalid` integer, required
      - `requests` integer, required
      - `startingBalancesPosted` integer
      - `startingBalancesUnknown` integer
      - `rateLimited` boolean, required
    - `errorCategory` string
    - `workflowInstanceId` string
    - `initiator` object
      - `kind` 'user' | 'staff' | 'system', required
      - `id` string, required
      - `label` string
    - `createdAt` string, required
    - `updatedAt` string, required
    - `startedAt` string
    - `completedAt` string

## Other responses

- `400`: The feed is not ready to sync — the message names the missing piece (e.g. no destination configured, no bank accounts selected, no Notion database chosen). Finish configuring the feed and retry; retrying as-is will fail identically.
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Feed not found
- `409`: A sync job is already running for this feed (set forceCancelActive=true to override), or the feed is paused because something it uses (its connection, mailbox or destination table) is in trash

---

[API](https://skmtc.dev/banksync/apis/banksync-api.md) · [All operations](https://skmtc.dev/banksync/apis/banksync-api/llms.txt) · [OpenAPI document](https://skmtc.dev/banksync/apis/banksync-api/revisions/94465f5ee922?raw)
