---
title: "Get a sync run"
method: GET
path: "/v1/sync-runs/{syncRunId}"
tags: ["ERP sync"]
---

# Get a sync run

`GET /v1/sync-runs/{syncRunId}`

## Request

- Base URL: `https://api.getfinero.com/functions/v1/api`
- URL: `https://api.getfinero.com/functions/v1/api/v1/sync-runs/{syncRunId}`
- Auth: HTTP bearer

Returns one ERP sync run (read-only operational visibility). Poll it after starting a pull, to follow that pull to completion. A run removed from the retained history answers `not_found`, like an unknown id.

Available to **admin and readonly** API keys (no side effects).

## Path parameters

- `syncRunId` string, uuid, required

## Response `200`

Success

- object
  - `id` string, uuid, required: Sync run id — poll this run until status is terminal.
  - `connection_id` string, uuid, required: The ERP connection that ran.
  - `direction` 'pull' | 'push', required: Sync direction. Every new run is `pull` — Finero no longer writes invoices back to an ERP. `push` remains in the enum because historical runs carry it.
  - `trigger` 'manual' | 'scheduled' | 'api', required: How the run started: `manual` (a person, in the Finero app), `scheduled` (the connection's own cadence), or `api` (POST /v1/erp-connections/{connectionId}/sync). Until 2026-08-11 API-started runs were recorded as `manual`; they are `api` now, because reporting a machine-started run as a human one misattributes it.
  - `status` 'running' | 'success' | 'partial' | 'failed', required: running is non-terminal; success/partial/failed are terminal. `partial` means the run ended with some invoices processed and some not: what WAS processed is applied and trustworthy. `error_summary` says why the rest was not — a failure on some items, or a pause at a per-run limit that the next sync resumes from; null means it only skipped invoices (`items_skipped`).
  - `started_at` string, date-time, required: Run start time (ISO 8601 UTC).
  - `finished_at` string, date-time, nullable, required: Run finish time (null while running) (ISO 8601 UTC).
  - `items_processed` integer, required: Invoices durably processed by this run, including correctness-preserving boundary rechecks. This is operational work, not the number of ERP changes; use `items_changed` for that. Judge completion by `status` and freshness by the connection's `last_successful_sync_at`.
  - `items_changed` integer, nullable, required: New invoices or invoices whose persisted ERP `source_updated_at` changed in this run. Zero is valid when positive `items_processed` only rechecks an inclusive cursor boundary. Null means the historical count is unknown.
  - `items_failed` integer, required: Invoices this run read but could not process.
  - `items_skipped` integer, required: Invoices NOT imported because the ERP sent them without a required value (named in `skipped_invoices`). Not a failure: the rest was imported, and the run is `partial` (`success` before 2026-10-02).
  - `skipped_invoices` object[], required: The first 20 skipped invoices, so they can be found and fixed in the ERP.
    - `external_invoice_id` string, required: The ERP's own id for the invoice.
    - `invoice_number` string, nullable, required: Null when the number is itself what is missing.
    - `missing` string[], required: Which values were missing. `invoice_status` counts only while the connection collects invoice status.
  - `error_summary` string, nullable, required: Categorical failure summary (never raw provider payloads).

## Other responses

- `400`: `validation_failed` — The request failed schema validation. See error.details for field messages.
- `401`: `invalid_credentials` — The credential is malformed or does not match an active key. The response never reveals whether a key identifier exists. `missing_credentials` — No Authorization: Bearer header was sent. `revoked_credentials` — The presented key was revoked. Create a new key in Settings → API.
- `403`: `feature_unavailable` — The tenant's tier does not currently include API access. Feature rollout flags cannot grant this entitlement. `permission_denied` — The key's permission does not allow this operation (readonly keys cannot call admin-only operations).
- `404`: `not_found` — No such resource in YOUR tenant. Ids belonging to another tenant are indistinguishable from missing ones.
- `429`: `rate_limit_exceeded` — Too many requests. Honor the Retry-After header (seconds) before retrying — waiting that long is enough. The RateLimit-* fields on every response say how much headroom is left before this happens; pace against them instead of retrying into a refusal.
- `500`: `internal_error` — Unexpected server error. Safe to retry with the same Idempotency-Key.

---

[API](https://skmtc.dev/getfinero/apis/finero-public-api.md) · [All operations](https://skmtc.dev/getfinero/apis/finero-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/getfinero/apis/finero-public-api/revisions/3d456e222775?raw)
