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

> ## Agent Instructions
> Trackstar is a unified REST API for WMS, cart, and carrier systems. Base URL: https://production.trackstarhq.com. There is no SDK; call the API with plain HTTP.
> Send x-trackstar-api-key on every request. Endpoints scoped to one connection also need x-trackstar-access-token. Read both from environment variables and never print them.
> Reads return data Trackstar has already synced from the connected system. Writes (POST, PUT, PATCH, DELETE) are forwarded to the connected system immediately.
> A new connection has no data until its initial sync finishes. Wait for the connection.historical-sync-completed webhook, or poll GET /connections/{connection_id} and check historical_sync_completed.
> List endpoints page with page_token and next_token (limit is capped at 1000). Repeat every filter on every page. Filters use field[operator]=value, for example created_date[gte]=2026-01-01T00:00:00Z.
> Write bodies must not contain null or empty strings; omit the field instead. Call GET /integrations/{integration_type}/{integration_name}/write-info first to learn the exact fields an integration accepts.
> To test without real credentials, POST /sandbox/generate-sandbox/{wms|cart|carrier} with the API key returns a sandbox access token. Start at https://docs.trackstarhq.com/how-to-guides/build-with-ai.md and install the skills with: npx skills add https://docs.trackstarhq.com

# Syncing Data

> How Trackstar syncs data: scheduled syncs, force syncs, and on-demand syncs

Trackstar keeps your data fresh by periodically pulling from each connected integration, normalizing the results, and making them available through the Trackstar API and webhooks.

There are three ways a sync can happen:

* **Scheduled syncs** run automatically at predefined intervals. Most of your data arrives this way.
* **Force syncs** are manually triggered syncs of recent data, when you don't want to wait for the next scheduled sync.
* **On-demand syncs** backfill a specific data type over a custom time window, for example to pull historical data from before the initial sync.

## Sync Types at a Glance

| | Scheduled | Force | On-Demand |
| - | - | - | - |
| **How it starts** | Automatically, on a recurring schedule | Dashboard sync button, or [`POST /connections/sync`](/api-reference/mgmt/sync-connection) | Dashboard, or [`POST /connections/on-demand-syncs`](#creating-a-sync-job) |
| **Time window** | From the last sync to now | From the last sync to now | Custom `start_time` to `end_time` |
| **Scope** | Every data type, each on its own schedule | All data types, or specific ones via `functions_to_sync` | One function per sync job |
| **Completion signal** | Resource webhooks (e.g. [`order.updated`](/how-to-guides/webhooks/wms/order-updated)) | [`connection.force-sync-completed`](/how-to-guides/webhooks/admin/connection-force-sync-completed) | [`connection.sync-job-completed`](/how-to-guides/webhooks/admin/connection-sync-job-completed) |
| **Best for** | Staying up to date | Getting fresh data right now | Backfilling historical data |

## Scheduled Syncs

### Default Sync Frequencies

Different data types are synchronized at varying intervals to balance data freshness and system performance. Below is a breakdown of the default synchronization frequencies:

| **API** | **Data Type** | **Sync Frequency** |
| - | - | - |
| WMS | Inventory | Hourly |
| WMS | Inbound Shipments | Hourly |
| WMS | Orders | Hourly |
| WMS | Products | Hourly |
| WMS | Returns | Hourly |
| WMS | Bills | Hourly |
| WMS | Inventory Ledger | Hourly |
| WMS | Shipping Methods | Every 12 hours |
| WMS | Warehouses | Every 12 hours |
| WMS | Warehouse Customers | Every 12 hours |
| WMS | Warehouse Locations | Every 12 hours |
| Cart | Orders | Hourly |
| Cart | Products | Hourly |
| Cart | Warehouses | Every 12 hours |
| Carrier | Invoice Line Items | Daily |

> **Note:** These frequencies are default settings and can be customized per connection. If you need to modify the synchronization interval for a particular data type or connection, please contact us for assistance.

### Initial Sync Behavior

Upon establishing a new connection, Trackstar performs an initial synchronization that retrieves data from the past **30 days** by default. This historical sync ensures that your system starts with a comprehensive dataset.

To adjust the historical lookback window, go to your dashboard's [Connections Settings](https://dashboard.trackstarhq.com/settings/connection-settings). New connections can sync up to three years of historical data.

When each data type (e.g. inventory, orders) has finished syncing for the first time, we will send a `connection.historical-sync-completed` event. This indicates data is now available for that data type from our API.

Example:

```json theme={null}
{
  "connection_id": "connection_id",
  "data": {
    "newest_data_date": "2025-05-01T00:00:00Z",
    "oldest_data_date": "2025-01-01T00:00:00Z",
    "resource": "orders"
  },
  "event_type": "connection.historical-sync-completed",
  "integration_name": "integration_name",
  "integration_type": "wms"
}
```

You can also check the sync status of a connection programmatically by calling [`GET /connections/{id}`](/api-reference/mgmt/get-connection).

## Force Syncs

A force sync is a manually triggered sync. It runs the same sync a schedule would, just immediately, without waiting for the next scheduled run.

<Note>
  A force sync does **not** sync historical data. To backfill a custom time window, use an [on-demand sync](#on-demand-syncs).
</Note>

You can trigger a force sync two ways:

* **Via the Dashboard:** Go to the [Connections Page](https://dashboard.trackstarhq.com/connections), click on the connection you want to sync, and press the resync button for the desired data type.
* **Via the API:** Call [`POST /connections/sync`](/api-reference/mgmt/sync-connection). By default it syncs every data type on the connection; pass `functions_to_sync` (e.g. `["get_orders", "get_inventory"]`) to sync specific ones.

```bash cURL theme={null}
curl --request POST \
  --url https://production.trackstarhq.com/connections/sync \
  --header 'x-trackstar-api-key: your_api_key' \
  --header 'x-trackstar-access-token: your_access_token' \
  --header 'Content-Type: application/json' \
  --data '{
    "functions_to_sync": ["get_orders", "get_inventory"]
  }'
```

A few things to know:

* The sync starts right away, but it may take a few minutes for new data to appear as it completes in the background.
* If a data type is already mid-sync, the force sync leaves it alone rather than starting a duplicate.
* When the sync finishes for a data type, Trackstar sends a [`connection.force-sync-completed`](/how-to-guides/webhooks/admin/connection-force-sync-completed) event for it.

## On-Demand Syncs

On-demand syncs let you trigger a backfill of a specific data type over a custom time window, outside of Trackstar's normal sync schedule. They're useful for re-syncing historical data or pulling a longer window of data than the default [30-day initial sync](#initial-sync-behavior).

### Supported Functions

Support is rolled out per integration + function. If you'd like support added for an integration or function, [reach out to us](mailto:support@trackstarhq.com) and we'll look into enabling it.

#### WMS

**Available function names:**

* `get_orders`
* `get_inbound_shipments`
* `get_returns`
* `get_bills`
* `get_inventory_ledger`

<Note>
  `get_inventory` and `get_products` are intentionally **not** supported for on-demand syncs. Inventory always syncs as a full snapshot, and the full product catalog is retrieved on a connection's first sync, so an on-demand sync over a custom range would not change what gets pulled. To refresh either, use a [force sync](#force-syncs) or wait for the next scheduled sync.
</Note>

#### Carrier

**Available function names:**

* `get_invoice_line_items`

#### Cart

**Available function names:**

* `get_orders`

<Note>
  `get_products` is intentionally **not** supported for on-demand syncs. The full product catalog is retrieved on a connection's first sync, so an on-demand sync over a custom range would not change what gets pulled. To refresh products, use a [force sync](#force-syncs) or wait for the next scheduled sync.
</Note>

### Usage

There are three endpoints for managing on-demand syncs:

| Operation | Method | Path |
| - | - | - |
| Create a sync job | `POST` | `/connections/on-demand-syncs` |
| Get sync job status | `GET` | `/connections/on-demand-syncs/{sync_job_id}` |
| Cancel a sync job | `POST` | `/connections/on-demand-syncs/{sync_job_id}/cancel` |

Like all Trackstar API calls, you'll need to authenticate [using your API key and the access token](/how-to-guides/getting-started#5-make-api-calls-be) for the specific connection.

You can manage on-demand syncs either through the API directly or through the [Trackstar dashboard](https://dashboard.trackstarhq.com/connections). Each section below shows both options — pick whichever fits your workflow.

### Creating a Sync Job

The following parameters are required when creating a sync job via the API:

<ParamField path="start_time" type="string" required>
  ISO 8601 timestamp marking the start of the time window to sync (e.g., `2025-12-01T00:00:00Z`).
</ParamField>

<ParamField path="end_time" type="string" required>
  ISO 8601 timestamp marking the end of the time window to sync (e.g., `2026-01-01T00:00:00Z`).
</ParamField>

<ParamField path="function_name" type="string" required>
  The data-fetching function to run. Must be one of the values listed in [Supported Functions](#supported-functions).
</ParamField>

If you attempt to start an on-demand sync for an integration + function combination that isn't currently enabled, you will receive a `400` response with the message:

```text theme={null}
On-demand sync is not enabled for {integration_name} {function_name}
```

<Tabs>
  <Tab title="Create via API">
    <CodeGroup>
      ```python Python theme={null}
      import requests

      TRACKSTAR_API_KEY = "your_api_key"
      ACCESS_TOKEN = "your_access_token"

      url = "https://production.trackstarhq.com/connections/on-demand-syncs"
      headers = {
          "x-trackstar-api-key": TRACKSTAR_API_KEY,
          "x-trackstar-access-token": ACCESS_TOKEN,
          "Content-Type": "application/json"
      }

      payload = {
          "start_time": "2025-12-01T00:00:00Z",
          "end_time": "2026-01-01T00:00:00Z",
          "function_name": "get_orders"
      }

      response = requests.post(url, headers=headers, json=payload)
      response.raise_for_status()
      sync_job = response.json()

      print(sync_job)
      ```

      ```javascript Node.js theme={null}
      const axios = require('axios');

      const TRACKSTAR_API_KEY = 'your_api_key';
      const ACCESS_TOKEN = 'your_access_token';

      const url = 'https://production.trackstarhq.com/connections/on-demand-syncs';
      const headers = {
        'x-trackstar-api-key': TRACKSTAR_API_KEY,
        'x-trackstar-access-token': ACCESS_TOKEN,
        'Content-Type': 'application/json'
      };

      const payload = {
        start_time: '2025-12-01T00:00:00Z',
        end_time: '2026-01-01T00:00:00Z',
        function_name: 'get_orders'
      };

      const response = await axios.post(url, payload, { headers });

      console.log(response.data);
      ```

      ```bash cURL theme={null}
      curl --request POST \
        --url https://production.trackstarhq.com/connections/on-demand-syncs \
        --header 'x-trackstar-api-key: your_api_key' \
        --header 'x-trackstar-access-token: your_access_token' \
        --header 'Content-Type: application/json' \
        --data '{
          "start_time": "2025-12-01T00:00:00Z",
          "end_time": "2026-01-01T00:00:00Z",
          "function_name": "get_orders"
        }'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Create via Dashboard">
    1. Open the [Connections page](https://dashboard.trackstarhq.com/connections) and click into the connection you want to sync.

    2. In the connection details drawer, switch to the **On-Demand Syncs** tab.

    3. Click **Create**.

           <img src="https://mintcdn.com/trackstar/KiQUv3Ca9NnkESlJ/images/on-demand-syncs/create-button.png?fit=max&auto=format&n=KiQUv3Ca9NnkESlJ&q=85&s=00cd60c68580cdcd448ec7c348408995" alt="On-Demand Syncs tab with Create button" width="700" height="585" data-path="images/on-demand-syncs/create-button.png" />

    4. In the modal, pick a function, choose a start and end time (interpreted as your local timezone and converted to UTC on submit), and click **Create Sync Job**.

           <img src="https://mintcdn.com/trackstar/KiQUv3Ca9NnkESlJ/images/on-demand-syncs/create-modal.png?fit=max&auto=format&n=KiQUv3Ca9NnkESlJ&q=85&s=f0014df89d2360a8955adfd5e2c491de" alt="Create On-Demand Sync modal" width="461" height="408" data-path="images/on-demand-syncs/create-modal.png" />

    The new job will appear at the top of the list with status `open`.
  </Tab>
</Tabs>

### Checking Sync Job Status

Use the `sync_job_id` returned from the create call to check progress. The response includes a `status` field with one of the following values:

| Status | Meaning |
| - | - |
| `open` | The job has been created and is either queued or actively running. |
| `completed` | The job finished successfully. Synced data is now available via the standard Trackstar API. |
| `cancelled` | The job was cancelled before it could finish (see [Cancelling a Sync Job](#cancelling-a-sync-job)). |
| `stuck` | The job stopped making progress for an extended period (see [Stuck Syncs](#stuck-syncs)). |

A typical successful lifecycle is `open → completed`. A cancelled job follows `open → cancelled`, and a job that stops progressing moves `open → stuck`.

The full response also includes `id`, `connection_id`, `function_name`, `requested_start_time`, `requested_end_time`, and `created_at`.

<Tabs>
  <Tab title="Check via API">
    Use the `sync_job_id` returned from the create call:

    <CodeGroup>
      ```python Python theme={null}
      import requests

      TRACKSTAR_API_KEY = "your_api_key"
      ACCESS_TOKEN = "your_access_token"
      SYNC_JOB_ID = "your_sync_job_id"

      url = f"https://production.trackstarhq.com/connections/on-demand-syncs/{SYNC_JOB_ID}"
      headers = {
          "x-trackstar-api-key": TRACKSTAR_API_KEY,
          "x-trackstar-access-token": ACCESS_TOKEN
      }

      response = requests.get(url, headers=headers)
      response.raise_for_status()
      status = response.json()

      print(status)
      ```

      ```javascript Node.js theme={null}
      const axios = require('axios');

      const TRACKSTAR_API_KEY = 'your_api_key';
      const ACCESS_TOKEN = 'your_access_token';
      const SYNC_JOB_ID = 'your_sync_job_id';

      const url = `https://production.trackstarhq.com/connections/on-demand-syncs/${SYNC_JOB_ID}`;
      const headers = {
        'x-trackstar-api-key': TRACKSTAR_API_KEY,
        'x-trackstar-access-token': ACCESS_TOKEN
      };

      const response = await axios.get(url, { headers });

      console.log(response.data);
      ```

      ```bash cURL theme={null}
      curl --request GET \
        --url https://production.trackstarhq.com/connections/on-demand-syncs/your_sync_job_id \
        --header 'x-trackstar-api-key: your_api_key' \
        --header 'x-trackstar-access-token: your_access_token'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Check via Dashboard">
    The **On-Demand Syncs** tab in the connection details drawer lists all sync jobs for that connection, with their function name, status, and requested window. The list is sorted by most recently created first.

    <img src="https://mintcdn.com/trackstar/KiQUv3Ca9NnkESlJ/images/on-demand-syncs/list-view.png?fit=max&auto=format&n=KiQUv3Ca9NnkESlJ&q=85&s=3596266e259c98ca2e72264f581c2239" alt="On-Demand Syncs list with status badges" width="777" height="388" data-path="images/on-demand-syncs/list-view.png" />

    Click the refresh icon to re-fetch the list — the dashboard does not auto-poll.
  </Tab>
</Tabs>

### Cancelling a Sync Job

If a sync job is no longer needed, you can cancel it before it completes. Only jobs in the `open` state can be cancelled.

<Tabs>
  <Tab title="Cancel via API">
    <CodeGroup>
      ```python Python theme={null}
      import requests

      TRACKSTAR_API_KEY = "your_api_key"
      ACCESS_TOKEN = "your_access_token"
      SYNC_JOB_ID = "your_sync_job_id"

      url = f"https://production.trackstarhq.com/connections/on-demand-syncs/{SYNC_JOB_ID}/cancel"
      headers = {
          "x-trackstar-api-key": TRACKSTAR_API_KEY,
          "x-trackstar-access-token": ACCESS_TOKEN,
          "Content-Type": "application/json"
      }

      response = requests.post(url, headers=headers)
      response.raise_for_status()

      print(response.json())
      ```

      ```javascript Node.js theme={null}
      const axios = require('axios');

      const TRACKSTAR_API_KEY = 'your_api_key';
      const ACCESS_TOKEN = 'your_access_token';
      const SYNC_JOB_ID = 'your_sync_job_id';

      const url = `https://production.trackstarhq.com/connections/on-demand-syncs/${SYNC_JOB_ID}/cancel`;
      const headers = {
        'x-trackstar-api-key': TRACKSTAR_API_KEY,
        'x-trackstar-access-token': ACCESS_TOKEN,
        'Content-Type': 'application/json'
      };

      const response = await axios.post(url, null, { headers });

      console.log(response.data);
      ```

      ```bash cURL theme={null}
      curl --request POST \
        --url https://production.trackstarhq.com/connections/on-demand-syncs/your_sync_job_id/cancel \
        --header 'x-trackstar-api-key: your_api_key' \
        --header 'x-trackstar-access-token: your_access_token' \
        --header 'Content-Type: application/json'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Cancel via Dashboard">
    In the **On-Demand Syncs** tab, click the cancel icon at the end of any row whose status is `open`. The icon only appears for cancellable rows.

    <img src="https://mintcdn.com/trackstar/KiQUv3Ca9NnkESlJ/images/on-demand-syncs/cancel-action.png?fit=max&auto=format&n=KiQUv3Ca9NnkESlJ&q=85&s=238cfaabf0cfe7855f2c05958cf33ea0" alt="Cancel icon on an open sync job row" width="786" height="408" data-path="images/on-demand-syncs/cancel-action.png" />

    Once cancelled, the job stays in the list with status `cancelled` and the icon disappears.
  </Tab>
</Tabs>

### Interaction with Other Syncs

* **Asynchronous execution:** On-demand sync jobs run in the background. Poll the status endpoint or rely on Trackstar's existing webhooks (e.g. [`order.created`](/how-to-guides/webhooks/wms/order-created), [`order.updated`](/how-to-guides/webhooks/wms/order-updated)) to know when new data has landed.
* **Precedence over scheduled syncs:** While a sync job is in the `open` state, the regularly scheduled syncs for that same data type will not run, which can cause its recent data to fall behind. Other data types on the connection keep syncing on their normal schedules. Once no sync jobs remain in the `open` state for a data type (they complete, are cancelled, or are marked stuck), its scheduled syncs automatically resume from where they left off — so no data is missed, only delayed.

## Knowing When Your Data Is Ready

Each kind of sync has its own completion signal:

| After you... | Listen for... |
| - | - |
| Connect a new integration | [`connection.historical-sync-completed`](/how-to-guides/webhooks/admin/connection-historical-sync) per data type |
| Trigger a force sync | [`connection.force-sync-completed`](/how-to-guides/webhooks/admin/connection-force-sync-completed) per data type |
| Create an on-demand sync job | [`connection.sync-job-completed`](/how-to-guides/webhooks/admin/connection-sync-job-completed) (or [`connection.sync-job-stuck`](/how-to-guides/webhooks/admin/connection-sync-job-stuck)) |
| Anything — data changed at the source | Webhook events like [`order.created`](/how-to-guides/webhooks/wms/order-created) and [`order.updated`](/how-to-guides/webhooks/wms/order-updated) |

More information on our webhooks can be found in the [webhooks documentation](/how-to-guides/webhooks/webhooks).

## Stuck Syncs

Occasionally a sync stops making progress — for example when the underlying integration's API is degraded. Trackstar detects this in two places:

* **Scheduled syncs:** if a data type's regular sync stops making progress, Trackstar sends a [`connection.schedule-stuck`](/how-to-guides/webhooks/admin/connection-schedule-stuck) event. Its `latest_data` field tells you how fresh that data type's data is, so you know how far behind it may be. Our team is alerted internally and investigates; scheduled syncs resume automatically once the underlying issue is resolved.
* **On-demand sync jobs:** a job that stops making progress for an extended period moves to status `stuck`, and Trackstar sends a [`connection.sync-job-stuck`](/how-to-guides/webhooks/admin/connection-sync-job-stuck) event. Stuck jobs do not resume on their own — if a job becomes stuck, [reach out to us](mailto:support@trackstarhq.com) and we'll investigate.

## Disabled Endpoints

If there are data types your business doesn't use — say you never handle returns — you can disable those endpoints so they stay out of the way entirely. A disabled endpoint:

* **Doesn't sync.** Scheduled syncs stop, force syncs skip it, and creating an on-demand sync job for it returns a `400`.
* **Isn't validated at connect time.** End users connecting through [Trackstar Link](/how-to-guides/trackstar-link) won't see an attempt to validate permissions for it.
* **Is omitted from `available_actions`.** It no longer appears in the connection's [available actions](/how-to-guides/getting-started#22-store-token).
* **Rejects writes.** Write calls return a `403` (e.g. `create_return is disabled for this connection`) without reaching the integration. See [Writing Data](/how-to-guides/programmatic-writes).

Disabled endpoints resolve in two layers:

* **Org policy:** set per integration type (WMS, Cart, Carrier) in the dashboard. Applies to every connection of that type, existing and future.
* **Per-connection adjustments:** on top of org policy, the Magic Link that installs a connection can disable extra endpoints for it, or re-enable org-disabled ones.

<Tabs>
  <Tab title="Org policy via Dashboard">
    Go to [Connection Settings](https://dashboard.trackstarhq.com/settings/connection-settings) and open the **Disabled Endpoints** tab. Toggles are grouped by integration type, and each type's list is independent — turning off Products for Cart doesn't affect Products for WMS.

    <img src="https://mintcdn.com/trackstar/xhpoOpgsGt8DIxVn/images/disabled-endpoints/org-policy-tab.png?fit=max&auto=format&n=xhpoOpgsGt8DIxVn&q=85&s=fd07a0b1b71a63db7ce859bec5109be5" alt="Disabled Endpoints tab in Connection Settings, grouped by integration type" width="2366" height="1466" data-path="images/disabled-endpoints/org-policy-tab.png" />
  </Tab>

  <Tab title="At install via Magic Link">
    A [Magic Link](/how-to-guides/trackstar-link#sending-a-magic-link) can carry endpoint settings for the connection it installs, under **Advanced** in the Generate Magic Link modal:

    * **Disabled Endpoints** start turned off on the new connection, on top of your org policy.
    * **Enabled Endpoints** turn org-disabled endpoints back on for that connection — the only way to grant a single connection an endpoint your org policy disables.

          <img src="https://mintcdn.com/trackstar/xhpoOpgsGt8DIxVn/images/disabled-endpoints/magic-link-endpoints.png?fit=max&auto=format&n=xhpoOpgsGt8DIxVn&q=85&s=0c36f1daaf226417c07498eb5abdaddd" alt="Advanced section of the Generate Magic Link modal with the Disabled Endpoints picker" width="866" height="1396" data-path="images/disabled-endpoints/magic-link-endpoints.png" />
  </Tab>
</Tabs>

<Note>
  Some endpoints rely on data that another endpoint syncs. If a change would disable an endpoint that a still-enabled one depends on — for example disabling inventory while returns, which uses inventory data, stays on — the change is rejected with an error explaining the conflict.
</Note>

Re-enabling an endpoint is just removing it from the disabled list: its syncs resume automatically and Trackstar backfills the data it missed.

## What About Writes?

Writes don't wait for a sync. When you create or update a resource via `POST` or `PUT`, Trackstar forwards the request to the integration in real time and returns its response immediately. See [Writing Data](/how-to-guides/programmatic-writes) for details.


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