sync-connector
Sync one connector, the same as Sync this connector on its card in the console. The connector's actions and
ontology are refreshed, and then ingestion starts when the connector has data to pull. Get the connector's id
from list-connectors first.
The call answers at once with a sync_id. A sync can run for minutes, so the call never waits for it. Pass the
sync_id to get-connector-sync to follow it, or let an SDK wait for you
(below).
Which connectors you can sync
You can sync a connector when both of these are true:
list-connectorsshows it to you. That is decided by the access scope chosen when the connector was provisioned, the same rule that decides which actions you can run.- It was provisioned in your project. These are the connectors whose card the console shows in your project. A connector provisioned in another project is refused, even when its access scope lets you use its actions.
| Access scope | Listed for you when |
|---|---|
organization | your project is in the connector's organization |
department | your project is in the connector's department |
project | your project is the project the connector was provisioned in |
individual | you are the person who provisioned it |
A connector in another organization is always refused. Every refusal is the same S8:connector-not-usable
error, so the answer does not tell you whether a connector you cannot use exists.
A sync that is already running is joined
When a sync of the connector is still running, the call does not start a second one. It answers with the id of
the running sync and joined: true, so the load on the connected system never doubles. A finished sync is not
joined: the next call starts a new one.
Two calls in the same instant can both start a sync, because neither sees the other yet.
The console's own Sync button always starts a new sync.
What it is called on each surface
The wire name is sync-connector everywhere: it is what the Wexa MCP server advertises, the REST path is
POST /v1/sync-connector, and each SDK exposes it under its own language's naming convention.
| Surface | Name |
|---|---|
| Wexa MCP server | sync-connector |
| REST API | POST /v1/sync-connector |
| TypeScript SDK | fabric.syncConnector() |
| Python SDK | fabric.sync_connector() |
Arguments
| Argument | Type | Required | Notes |
|---|---|---|---|
connector_id | string | Required | The connector, from list-connectors. |
Both SDKs also take three options that are not sent to the platform:
| Python | TypeScript | Default | What it does |
|---|---|---|---|
wait | wait | off | Poll get-connector-sync until the sync is no longer running. |
wait_timeout | waitTimeout | 600 | The most seconds to wait. |
poll | poll | 5 | Seconds between two polls. |
project_id, projectID, organization_id and executed_by are not arguments you pass: the
platform binds all four from the credential you authenticated with, and both SDKs refuse them
before the request leaves your process — see
server-bound arguments.
What it returns
| Field | What it is |
|---|---|
sync_id | The sync to pass to get-connector-sync. |
connector_id | The connector you named. |
joined | true when a running sync was joined, false when this call started one. |
status | Always running: the sync has just started, or is still running. |
The three surfaces wrap this differently, and code written against one will not read another correctly — see return shape.
A real response, captured from a live call to sync-connector that started a sync of a Linear connector.
Nothing is changed.
{
"content": [
{
"type": "text",
"text": "{\"lifecycle_id\":\"qlc_000002\",\"result\":{\"sync_id\":\"connector-sync-6aa9beb7ec8121a43b6c791b-6ab3608bf19beb4f0ed39e77-1790280549835063253\",\"connector_id\":\"6ab3608bf19beb4f0ed39e77\",\"joined\":false,\"status\":\"running\"}}"
}
],
"isError": false
}Keeping the lifecycle_id is what lets you ask later why a call was allowed, refused or held.
Waiting for the sync to end
With wait, both SDKs start or join the sync, then poll get-connector-sync until its status is no longer
running, and return that last status with joined added. A failed sync comes back as a status with
status: "failed"; it is not raised.
wait waits only for the refresh of the connector's actions and ontology. It never waits for ingestion to
finish, because a native connector such as Linear or Slack cannot report when its data is all in. Read the
ingestion field of the status for what is known.
When the time limit is reached, the SDK stops polling and returns the last status, which still says
status: "running". Nothing is raised, and the sync goes on. Poll get-connector-sync with its sync_id to
follow it further.
Calling it
The same call on all four surfaces. Pick a tab once and every code block in the documentation follows it.
The ids in this example are real, and resolve against the project the documentation is written
against. Swap them for your own. A value in angle brackets is one only you can supply, and the
platform refuses a literal <...>.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "sync-connector",
"arguments": {
"connector_id": "6ab3608bf19beb4f0ed39e77"
}
}
}Errors
Both SDKs raise the same typed errors, chosen from the gateway's own error string first and its
HTTP status second. sync-connector checks the fabric:connector.sync grant, and reaches the seven classes every
tool reaches — listed under the common set. These are the ones specific to it:
| Error | Status | Raised when |
|---|---|---|
ForbiddenError | 403 | The credential does not carry fabric:connector.sync. |
ForbiddenError | 403 | The connector is not one you can sync (S8:connector-not-usable): it does not exist, it is in another organization, it was provisioned in another project, or its access scope does not include you. |
ValidationError | 422 | connector_id is missing or is not a string. |
Governance
Every call to sync-connector runs through the same ten-stage lifecycle as every other Wexa tool: the
credential is resolved to a scope, the fabric:connector.sync grant is checked, quota is drawn down, the arguments are
validated, policy rules are evaluated, the call is executed, the result is shaped and redacted, and an audit
record is written. The lifecycle_id in the response is the handle to that record.
Every call also writes a sync-connector.run audit event, whether it started a sync, joined one or was
refused. The event records who called, the connector, its access scope and department, your department, the
sync_id, and the outcome: started, joined, refused or failed. A call refused because the credential
lacks the grant is recorded as sync-connector.rejected.
sync-connector is not marked consequential, so it does not wait for approval. A sync only reads from the
connected system, and scheduled automation must be able to run it.
A sync reads the connected system with the connector's own credential and can pull all of its data into your
project's context graph. That is why it needs its own grant, fabric:connector.sync, and why a key that may run
actions or read data does not gain it. Administrator keys carry it by default. An API key minted before the
grant existed does not carry it, and must be reissued to use this tool.
See also
get-connector-sync, list-connectors,
the tool index, errors, and
which identifier goes where.