Skip to main content

Managed Sync HTTP API

The managed Sync HTTP API accepts authenticated run requests, records a stable Sync run identity, and delegates execution to a separate Prefect deployment. Sync owns the HTTP, authorization, plan, result, artifact, audit, and idempotency contracts. Prefect owns live execution state, workers, retries, logs, and cancellation.

The direct Prefect remote run remains a separate four-parameter deployment. Use the managed API when a trusted automation client needs reviewed-plan apply, durable results, artifact retrieval, or actor-scoped mutation control.

Install the managed profile

The managed profile requires Python 3.11 or later. No published package carries this profile yet, so install from a repository checkout on the API host and every worker that can run its deployment:

uv sync --extra dev --extra prefect --extra managed

Once a release with the managed profile is published, pip install 'infrahub-sync[managed]' becomes the deployment path.

The profile directly installs FastAPI, HTTPX, Uvicorn, and Prefect 3.8.1. The OpsMill Prefect Extras integration ships with the package itself as a vendored copy of upstream commit 84688eb8d8db7e17770413640a66481ccdc3e725. The base installation does not import any of these modules. Ordinary CLI and Python API imports remain Prefect-free.

You also need:

  • a Prefect API and an existing process work pool;
  • a worker with access to the allowed Sync configuration directory;
  • an absolute saved-plan cache path shared by worker processes; and
  • one absolute durable product-cache path visible to both the API and workers.

The MVP product-cache profile uses SQLite and the local filesystem. Run the API and workers on infrastructure where they can use the same filesystem paths. The API does not copy worker-local paths through Prefect.

Configure principals

INFRAHUB_SYNC_MANAGED_BEARER_TOKENS contains a non-empty JSON object keyed by actor. Each entry has a bearer token of at least 16 characters and an optional administrator flag:

export INFRAHUB_SYNC_MANAGED_BEARER_TOKENS='{
"automation@example.com": {
"token": "replace-with-a-secret-token",
"administrator": false
},
"sync-admin@example.com": {
"token": "replace-with-another-secret-token",
"administrator": true
}
}'

Inject this value through your deployment's secret mechanism. Do not put a real token in a shell history, Sync configuration, request body, idempotency key, or Prefect parameter. Tokens must be unique. The resolver compares them with a timing-safe operation and never persists, returns, or submits them to Prefect.

Any authenticated principal can create and inspect a run. Only the initiating actor or an administrator can verify, apply, or cancel it. Every accepted mutation and authorization refusal records secret-safe actor, reason, and outcome evidence.

Deploy the managed flow

Set the work pool name and the absolute directory managed flow runs execute from — relative paths in Sync configurations resolve against it — then apply the managed deployment:

export PREFECT_API_URL="http://127.0.0.1:4200/api"
export INFRAHUB_SYNC_MANAGED_WORK_POOL="sync-process-pool"
export INFRAHUB_SYNC_MANAGED_FLOW_WORKING_DIRECTORY="/path/to/checkout"
python -m infrahub_sync.managed.deploy

The command validates and applies infrahub-sync-managed/run through OpsMill Prefect Extras, then records the declared working directory as the deployment's only pull step. It does not create a work pool or start a worker.

Configure the worker environment before it starts:

VariableRequirement
PREFECT_API_URLPrefect API used by the deployment and worker.
INFRAHUB_SYNC_CONFIG_DIRECTORYExisting directory containing the Sync configurations allowed on this worker.
INFRAHUB_SYNC_CACHE_DIRAbsolute shared cache root for saved plans and run artifacts.
INFRAHUB_SYNC_MANAGED_CACHE_LOCATIONAbsolute durable product-cache root shared with the API.
Adapter credential variablesCredentials required by the selected Sync configuration. Keep them in the worker environment or its secret provider.

The managed flow accepts exactly seven bounded parameters:

ParameterTypePurpose
run_idstrAPI-created Sync run identity.
sync_namestrConfiguration selected from the worker's configured directory.
stageplan, verify, apply, or syncExecution stage accepted by the API.
configuration_referencestrImmutable, non-secret configuration revision recorded on the product run.
branchstr or nullOptional Infrahub branch.
expected_checksumSHA-256 string or nullReviewed checksum required by apply.
confirm_writesboolRequired for apply and composed sync.

The API rejects configured secret values in flow-bound request fields. Credentials, endpoints, adapter instances, and filesystem paths are never flow parameters.

Start the API

Set the same product-cache path used by the worker and start Uvicorn through the packaged entry point:

export PREFECT_API_URL="http://127.0.0.1:4200/api"
export INFRAHUB_SYNC_MANAGED_CACHE_LOCATION="/var/lib/infrahub-sync/product-cache"
export INFRAHUB_SYNC_MANAGED_HOST="127.0.0.1"
python -m infrahub_sync.managed.serve

The server listens on port 8000. Its host defaults to 127.0.0.1. Put TLS and any network access controls at your ingress boundary. The bearer-token provider is the MVP application authentication boundary, not a replacement for transport security.

Routes

Every route requires Authorization: Bearer <token>. Every POST route also requires a non-empty Idempotency-Key header and a non-empty reason in its JSON body.

RouteBehavior
POST /runsCreate one Sync run and accept plan or confirmed composed sync.
GET /runs/{run_id}Return the durable product record with current linked Prefect detail when available.
GET /runs/{run_id}/planReturn retained saved-plan review data.
GET /runs/{run_id}/resultsReturn retained results independently of Prefect result retention.
GET /runs/{run_id}/artifactsList immutable run-owned artifact references.
GET /runs/{run_id}/artifacts/{artifact_id}Return verified artifact bytes with their media type and Digest header.
POST /runs/{run_id}/verifyAccept read-only saved-plan verification without changing product lifecycle state.
POST /runs/{run_id}/applyAccept a confirmed apply for the exact retained reviewed checksum.
POST /runs/{run_id}/cancelAsk Prefect to cancel only the latest active linked execution.

Create a plan

Supply a stable non-secret reference for the exact configuration revision you intend the worker to resolve:

curl --request POST http://127.0.0.1:8000/runs \
--header "Authorization: Bearer $SYNC_API_TOKEN" \
--header "Idempotency-Key: plan-inventory-2026-08-10" \
--header "Content-Type: application/json" \
--data '{
"sync_name": "inventory",
"operation": "plan",
"configuration_reference": "sha256:7a15c1e2",
"reason": "review inventory changes"
}'

Acceptance returns 202 with the durable ProductRun and its first orchestration link. The run_id in that response is the identity for every later stage, result, artifact, and Prefect execution link.

Read the plan after the worker publishes it:

curl --header "Authorization: Bearer $SYNC_API_TOKEN" \
http://127.0.0.1:8000/runs/20260810T1500-0123abcd/plan

The plan response includes its checksum, checksum verification state, summary, verification notes, and per-object operations.

Verify and apply the reviewed plan

Verification is read-only and retains verification evidence without finishing or otherwise advancing the product run:

curl --request POST \
http://127.0.0.1:8000/runs/20260810T1500-0123abcd/verify \
--header "Authorization: Bearer $SYNC_API_TOKEN" \
--header "Idempotency-Key: verify-20260810T1500-0123abcd" \
--header "Content-Type: application/json" \
--data '{"reason":"verify the reviewed plan"}'

Apply requires the exact retained checksum and explicit write confirmation:

curl --request POST \
http://127.0.0.1:8000/runs/20260810T1500-0123abcd/apply \
--header "Authorization: Bearer $SYNC_API_TOKEN" \
--header "Idempotency-Key: apply-20260810T1500-0123abcd" \
--header "Content-Type: application/json" \
--data '{
"expected_checksum": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"confirm_writes": true,
"reason": "change approved"
}'

The worker verifies the saved plan again before its first destination write. Destination deletes remain disabled.

Idempotency and retries

An exact retry by the same actor with the same Idempotency-Key, target, and JSON body returns the stored status and body. A different request using that actor and key returns 409 idempotency-conflict.

Sync stores a SHA-256 digest of the client key, never the raw key. Before dispatch, it atomically reserves a durable mutation receipt; run creation reserves the receipt and product run in one transaction. The receipt owns a separate opaque key passed to Prefect's native idempotency field. If an HTTP or Prefect response is lost after submission, retry the exact request. The retry reuses the receipt, opaque Prefect key, Sync run ID, and Prefect flow-run ID.

Do not change the request body, including reason, while retrying. Use a new idempotency key for a new intent.

The first confirmed composed sync or reviewed apply permanently consumes that run's single write admission, including when the execution later fails, crashes, or is cancelled. Retry an uncertain request with its original idempotency key. To make another write attempt after a terminal failure or cancellation, create and review a new plan run; a new key on the old run returns 409 apply-already-admitted.

Errors and retained state

Every error uses the same envelope:

{
"error": {
"code": "checksum-conflict",
"message": "expected_checksum does not match the retained reviewed plan",
"status": 409,
"run_id": "20260810T1500-0123abcd",
"mutation_id": null
}
}
StatusMeaning
401Missing or invalid authentication.
403The actor does not own the mutation and is not an administrator.
404The Sync run or run-owned artifact does not exist.
409Idempotency conflict, missing confirmation, stale checksum, or non-cancellable execution.
410The retained plan or artifact has expired.
422Invalid request schema, missing idempotency key, or a secret-bearing flow parameter.
503Submission, live orchestration detail, or retained data cannot be confirmed or retrieved.

Prefect detail can expire or become unavailable while the durable Sync record, results, and published artifacts remain readable. Cancellation never deletes the product record or its execution history. The API does not add a Sync-owned queue, retry policy, scheduler, recovery state machine, or overlap policy.