Quickstart
Last updated
A Sync API batch groups all records from one extraction run. Only one batch can be active for a direct integration installation at a time.
The official SDKs manage the authenticated gRPC channel, attach the active batch ID to writes, and prevent local operations after the batch is completed or aborted.
Before You Start
You need:
- A passive direct integration installation under which the source's data can be reported.
- The direct integration installation ID.
- A Viio API key with the
integration:syncpermission. - An official Sync API SDK.
Install an official SDK:
dotnet add package Viio.SyncApi.Sdk --version 1.1.0
python -m pip install viio-sync-api-sdk==0.2.0
SDK Lifecycle
| Step | Purpose |
|---|---|
| Start | Acquire the integration lock and create a batch |
| Write | Send one typed collection or chunk for the batch |
| Complete | Reconcile snapshot-backed data and release the lock |
| Abort | Stop the run and release the lock without completing snapshots |
Configure the Client
using Viio.SyncApi;
using Viio.SyncApi.V1.Contracts;
var apiKey = Environment.GetEnvironmentVariable("VIIO_API_KEY")
?? throw new InvalidOperationException("VIIO_API_KEY is required.");
using var client = new SyncApiClient(
new SyncApiClientOptions(
new Uri("https://sync.viio.io"),
SyncApiAuthentication.ApiKey(apiKey)
)
);
var cancellationToken = CancellationToken.None;
import os
from viio_sync_api import SyncApiAuthentication, SyncApiClient, SyncApiClientOptions
from viio_sync_api.v1 import Account, AccountRecords, GenericAccountDetails, SyncRecordsRequest
options = SyncApiClientOptions(
endpoint="https://sync.viio.io",
authentication=SyncApiAuthentication.api_key(os.environ["VIIO_API_KEY"]),
)
async with SyncApiClient(options) as client:
...
The API key must have the integration:sync permission. The SDK sends it using the Authorization: ApiKey YOUR_API_KEY gRPC metadata value.
StartSyncBatch
Start a batch for the direct integration installation receiving the data.
var directIntegrationInstallationId =
Environment.GetEnvironmentVariable(
"VIIO_DIRECT_INTEGRATION_INSTALLATION_ID"
)
?? throw new InvalidOperationException(
"VIIO_DIRECT_INTEGRATION_INSTALLATION_ID is required."
);
using var batch = await client.StartBatch(
directIntegrationInstallationId,
cancellationToken
);
Console.WriteLine(batch.BatchId);
batch = await client.start_batch(
os.environ["VIIO_DIRECT_INTEGRATION_INSTALLATION_ID"]
)
print(batch.batch_id)
The SDK keeps the returned batch ID on the batch object and adds it to subsequent writes. If another run owns the integration lock, the SDK raises a batch-already-in-progress error.
SyncRecords
Create a typed records wrapper and send it through the active batch.
var accounts = new AccountRecords();
accounts.Records.Add(
new Account
{
Generic = new GenericAccountDetails
{
Id = "account-100",
Email = "owner@example.com",
Active = true,
},
}
);
await batch.Write(
new SyncRecordsRequest { Accounts = accounts },
cancellationToken
);
await batch.write(
SyncRecordsRequest(
accounts=AccountRecords(
records=[
Account(
generic=GenericAccountDetails(
id="account-100",
email="owner@example.com",
active=True,
)
)
]
)
)
)
The collection and record model must describe the same data type, and each record selects one supported details model. See the Model Reference for every collection, record model, and property.
The SDK adds the active batch identifier automatically and requires exactly one typed collection in each write request. Use repeated writes for additional data types or chunks.
You may:
- Split a large typed collection across several writes.
- Send data types in any order across writes.
Writes for one batch must be sequential. Wait for the current write to finish before starting the next one, and finish every write before completing the batch.
Each SyncRecordsRequest message must be smaller than 16 MiB. Use stable source IDs so later batches update the same logical records.
Empty snapshots
A present typed collection with an empty record list means that the source was processed successfully and currently contains no records of that type.
await batch.Write(
new SyncRecordsRequest { Accounts = new AccountRecords() },
cancellationToken
);
await batch.write(
SyncRecordsRequest(accounts=AccountRecords())
)
When the batch completes, Viio reconciles that empty account snapshot and marks accounts from the previous snapshot as removed. Omitting accounts means accounts were not processed in that message; omission alone does not register an empty snapshot.
CompleteSyncBatch
Complete the batch after every intended record has been accepted and every snapshot-backed collection included in the run is complete.
await batch.Complete(cancellationToken);
await batch.complete()
Viio tracks each typed collection accepted during the batch. On completion, it reconciles the snapshot-backed collections that were processed and retains accepted event records. Existing snapshot records that were not included are removed.
| Processing model | Data types | Completion behavior |
|---|---|---|
| Snapshot | Account, plan, license, employee, group, group member, device | Records missing from the completed snapshot are removed |
| Event | Usage, externally discovered usage, audit log, AI usage, AI cost | Accepted records are processed as events; absence does not remove earlier events |
AbortSyncBatch
Abort an unfinished batch through its SDK batch object.
await batch.Abort(cancellationToken);
await batch.abort()
Abort releases only that batch's active lock so a new run can start. A delayed abort for an old batch cannot release a newer batch's lock. Aborting does not roll back records already accepted during the batch and does not run full-snapshot deletion.
Retry Strategy
Wrap the complete write lifecycle so an unsuccessful run is aborted before the error is propagated.
try
{
await WriteBatchRecords(batch, cancellationToken);
await batch.Complete(cancellationToken);
}
catch
{
await batch.Abort(CancellationToken.None);
throw;
}
try:
await write_batch_records(batch)
await batch.complete()
except BaseException:
await batch.abort()
raise
Use this recovery sequence after a network, source, or validation failure:
- Stop sending records for the failed run.
- Call
AbortSyncBatch. - Fix the source or payload problem.
- Start a new batch.
- Resend every snapshot-backed collection in full and retry event records that were not accepted.
If a records stream is interrupted, requests already accepted by Viio remain associated with the batch. Retry the failed chunk using a new stream, or abort the batch and restart the run. After aborting, resend snapshot-backed collections in full because accepted records are not carried into the new batch.
The SDK batch object retains the batch identifier needed for completion and abort. If the process can terminate between operations, persist that identifier so recovery tooling can identify the unfinished server-side batch.
Batch Lease
An active batch has a renewable 15-minute lease. Successfully accepted record requests refresh the lease. If the lease expires, the batch is no longer available and a new batch can acquire the installation lock.
Authentication and Authorization Errors
| gRPC status | Meaning |
|---|---|
Unauthenticated | The API key is missing, inactive, malformed, or could not be verified |
PermissionDenied | The key lacks integration:sync or the installation or batch belongs to another workspace |
The SDK raises the corresponding authentication, protocol, or transport error. API keys are workspace-scoped, so a key cannot start, write to, complete, or abort a batch owned by another workspace. See the language-specific SDK guide for concrete error types.
Browse model properties