Skip to main content

Python API

SyncClient is the supported Python interface for the Sync HTTP API. It sends typed requests to the service and returns typed resources. It does not open a product store, load an adapter, resolve execution credentials, or run the execution core in the caller process.

The base infrahub-sync installation includes the client and HTTPX. FastAPI, Uvicorn, Prefect, Psycopg, and Boto3 remain optional service dependencies.

Connect

Construct a client with an absolute HTTP or HTTPS service URL, a bearer token, and a positive request timeout. TLS verification is enabled and redirects are refused.

HTTP provides no transport encryption for bearer credentials. Use HTTP only when the service connection stays inside a network you trust; use HTTPS across networks you do not trust.

from infrahub_sync.client import SyncClient

client = SyncClient("https://sync.example.com", "replace-with-a-token", timeout=30)

SyncClient.from_environment() reads INFRAHUB_SYNC_API_URL and INFRAHUB_SYNC_API_TOKEN:

from infrahub_sync.client import SyncClient

with SyncClient.from_environment(timeout=30) as client:
version = client.get_version()
status = client.get_status()

The first protected operation checks /version before sending the bearer token. The client requires the server to declare v3-unstable and caches a successful compatibility check for that client instance.

Register and inspect configurations

Configuration mutations require a reason and an idempotency key. A retry after an uncertain transport result must reuse the same key.

from infrahub_sync.client import ConfigMutationRequest, SyncClient

package = {
"format_version": 1,
"configuration": {
"name": "inventory",
"source": {"name": "netbox", "settings": {}},
"destination": {"name": "infrahub", "settings": {}},
},
}

with SyncClient.from_environment() as client:
registered = client.register_config(
ConfigMutationRequest(package=package, reason="Register inventory sync"),
idempotency_key="register-inventory-20260830",
)
config_id = registered.configuration.config_id
registry_version = registered.version.registry_version
report = client.validate_config(config_id, registry_version, offset=0, limit=256)

The client also exposes create_config_version, list_configs, get_config, list_config_versions, and get_config_version. Configuration list methods return the complete server response and do not expose pagination arguments. Validation exposes the server's finding page fields and preserves finding order.

Create and inspect runs

Create a plan from a registered configuration version:

from infrahub_sync.client import CreateRunRequest, SyncClient

with SyncClient.from_environment() as client:
accepted = client.plan(
CreateRunRequest(
operation="plan",
config_id=config_id,
registry_version=registry_version,
branch="main",
confirm_writes=False,
reason="Review inventory changes",
),
idempotency_key="plan-inventory-20260830",
)
finished = client.wait_for_run(accepted, timeout=1800, poll_interval=2)
saved_plan = client.get_plan(finished.run.run_id)

A confirmed composed sync uses operation="sync" and confirm_writes=True. The client also exposes get_run, get_results, list_artifacts, get_artifact, verify_run, apply_run, and cancel_run. The short method names sync, verify, and apply call the same HTTP operations.

apply_run sends the expected checksum from the reviewed PlanResource. It does not read or reconstruct plan bytes locally. get_artifact verifies the response Digest header against the received bytes before returning ArtifactContent.

Wait behavior

wait_for_run follows the final orchestration entry in the accepted mutation response by its flow_run_id. Earlier completed plan or verification executions do not make a later apply appear complete. Unknown non-terminal live states continue polling until the bounded deadline.

The durable terminal outcome decides the result:

  • completed/succeeded returns the latest RunResource;
  • failed, cancelled, abandoned, or ambiguous outcomes raise RunTerminalError;
  • reaching the deadline raises RunWaitTimeoutError with the run ID and last observed product and execution state.

A local KeyboardInterrupt stops the wait and crosses the Python boundary unchanged. It does not cancel the remote run.

Errors

Catch SyncClientError for all client-owned failures. More specific types are available for input, compatibility, transport, protocol, API refusal, configuration API refusal, wait timeout, and terminal run failures.

from infrahub_sync.client import ConfigsAPIError, SyncClientError

try:
configurations = client.list_configs()
except ConfigsAPIError as exc:
print(exc.status, exc.code, exc.family, exc.reason)
except SyncClientError:
raise

Exceptions contain fixed client-owned text. Valid API refusals retain only their documented machine fields. Raw response bodies, response headers, bearer values, and HTTPX exception chains do not cross the client boundary.