Skip to main content

zsyncstudio

SDK Python para robôs (RPA) se conectarem ao ZSync Tech Studio: buscar execuções pendentes, reportar o progresso de cada etapa (task) e finalizar a execução — usando o token de API gerado para a instância do robô.

Disponível em duas versões com a mesma interface: zsyncstudio.sync_api (síncrona) e zsyncstudio.async_api (assíncrona, com async/await).

Requisitos

  • Python ≥ 3.13
  • Uma instância do ZSync Tech Studio em execução
  • Token de API do robô, gerado no dashboard da plataforma (formato zst_<instanceId>.<secret>)

Instalação

uv add zsynctech-studio-sdk

ou

pip install zsynctech-studio-sdk

O pacote se chama zsynctech-studio-sdk no PyPI, mas o módulo Python é zsyncstudio — é ele que você importa nos exemplos abaixo.

Guia rápido

from zsyncstudio.sync_api import Client, ExecutionRun

client = Client("https://studio.exemplo.com", api_token)


def run(execution: ExecutionRun) -> None:
    execution.start()  # reivindica a execução: PENDING → RUNNING

    for invoice in invoices:
        task = execution.task(invoice.number)
        try:
            charge(invoice)
        except Exception as exc:
            task.error(str(exc))
        else:
            task.finish()

    execution.error("alguns itens falharam") if execution.had_errors else execution.finish()


if __name__ == "__main__":
    while execution := client.poll_pending_executions():
        try:
            run(execution)
        except Exception as exc:
            execution.error(str(exc))

O robô fica esperando em poll_pending_executions() até a plataforma disparar uma execução (pelo dashboard ou pela API). Cada task(...) representa um item processado; chame finish(), warning(), error() ou skip() para reportar o resultado. No fim, finish() marca a execução como concluída e error() como falha.

Sempre envolva run(execution) num try/except no loop principal, sem relançar a exceção — se ela escapar do while, o robô inteiro para e não volta a escutar por novas execuções. poll_pending_executions() já tolera sozinho falhas transitórias de rede (ConnectionError) e erros 5xx da API (retenta em vez de propagar); o try/except do loop é para erros da sua própria lógica de processamento (execution.start() falhando porque a execução já foi reivindicada por outro processo, por exemplo).

Para reportar progresso no meio de uma execução longa, sem finalizá-la:

execution.update_observation("processando lote 3 de 10")

Se você sabe de antemão quantos itens serão processados, informe logo após start() para o dashboard acompanhar o progresso real (ex.: "45/1000") em vez de reportado/reportado:

execution.set_total_tasks(1000)

Pode ser chamado mais de uma vez. Se você não informar, o total acompanha o que já foi processado (1/1, 2/2, ...); se processar mais itens do que declarou, o total passa a acompanhar o que já foi processado em vez de ultrapassar 100%.

Robôs que decidem sozinhos quando rodar

Se o robô não depende da plataforma para saber quando executar (por exemplo, dispara pelo agendador do próprio sistema operacional), use client.start_execution() em vez de poll_pending_executions() — a execução já nasce em andamento, então pule o execution.start() e vá direto para as tasks.

Credenciais (secrets)

Se o robô precisa de uma senha ou token guardado no cofre de credenciais da plataforma, revele o valor pelo id da credencial:

secret = client.get_secret(secret_id)
password = secret.value  # str, dict[str, str] ou dado JSON — depende do tipo da credencial

Uma credencial tem status ACTIVE, EXPIRED ou BLOCKED (além de DELETED, que já não aparece para o robô). get_secret() não lança por causa do status — se a credencial não estiver ACTIVE, secret.value vem None e secret.is_blocked/secret.is_expired já vêm preenchidos, sem precisar de uma segunda chamada:

secret = client.get_secret(secret_id)
if secret.is_blocked or secret.is_expired:
    ...  # avise alguém, ou pule esta credencial
else:
    password = secret.value

Depois de trocar a senha no sistema de destino, registre o novo valor (isso cria uma nova versão, nunca sobrescreve a atual, e reativa a credencial se ela estava EXPIRED/BLOCKED):

secret.rotate("nova-senha")

O próprio robô também pode sinalizar um problema (ex.: login rejeitado pelo sistema alvo) sem esperar a expiração automática:

secret.block("senha rejeitada pelo sistema X")   # ou secret.expire("...")

A única forma de tirar uma credencial de EXPIRED/BLOCKED é criar uma nova versão com rotate() — não existe um "desbloquear" manual. get_secret() ainda falha com NotFoundError se a credencial (ou a versão) não existir. Criar, excluir e ver o histórico completo (versões e eventos de status) só estão disponíveis para administradores pelo painel.

Uso assíncrono

from zsyncstudio.async_api import Client, ExecutionRun

client = Client(base_url, api_token)


async def run(execution: ExecutionRun) -> None:
    await execution.start()

    for invoice in invoices:
        task = execution.task(invoice.number)
        try:
            await charge(invoice)
        except Exception as exc:
            await task.error(str(exc))
        else:
            await task.finish()


async def main() -> None:
    while execution := await client.poll_pending_executions():
        try:
            await run(execution)
        except Exception as exc:
            await execution.error(str(exc))

Tratamento de erros

Problemas de comunicação com a plataforma chegam como exceções que você pode capturar:

from zsyncstudio.sync_api import AuthenticationError, ApiError

try:
    client.poll_pending_executions()
except AuthenticationError:
    print("Token inválido ou expirado.")
except ApiError as exc:
    print(f"Erro da plataforma ({exc.status_code}): {exc.message}")

As principais exceções: AuthenticationError (token inválido), NotFoundError (execução/instância inexistente), ConflictError (ex.: tentar finalizar uma execução já encerrada) e ConnectionError (falha de rede). Todas herdam de ApiError ou ZSyncStudioError e podem ser importadas de zsyncstudio.sync_api / zsyncstudio.async_api.

Dentro de uma task, você também pode levantar TaskWarning ou TaskSkipped para marcar o item como aviso ou pulado em vez de erro, sem interromper o processamento dos demais itens.

Metadados do projeto

  • Autor: Rodrigo Zavan
  • Proprietário: ZSync Tech LTDA
  • Requisito de Python: ≥ 3.13

Desenvolvimento

uv sync
uv run pytest
uv run mypy --strict src
uv run ruff check src tests
uv run black src tests

Release files for zsynctech-studio-sdk 1.3.25

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zsynctech-studio-sdk 1.3.25
File Size Uploaded
zsynctech_studio_sdk-1.3.25.tar.gz 22.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for zsynctech-studio-sdk 1.3.25
File Interpreter ABI Platform
zsynctech_studio_sdk-1.3.25-py3-none-any.whl Python 3 none any Details

Total release size: 51.1 kB

Release files / zsynctech_studio_sdk-1.3.25.tar.gz

Download URL zsynctech_studio_sdk-1.3.25.tar.gz
Size 22.7 kB
Tags Source
SHA-256 checksum
How to use checksums
b9f05c3e0d9d670bcb7b554bb3f80d7907584cd67899e8c26daceed5c3abf535
BLAKE2b-256 checksum
How to use checksums
c0151a989f5ca4ce860f50b27858182d300ea60f959b6b7378dd1556d3a6615b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Release files / zsynctech_studio_sdk-1.3.25-py3-none-any.whl

Download URL zsynctech_studio_sdk-1.3.25-py3-none-any.whl
Size 28.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0a9a5a2dd5d9ee6a7a2be2a96f86b3518442e097384388b459ed5dc076ea6a8b
BLAKE2b-256 checksum
How to use checksums
b8f092719e3b7bb4017a2427f0ccd4b890f79e208d069856b38e41418246e2c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.

Transparency log

Release history Release notifications | RSS feed

1.4.6

2 release files

1.4.5

2 release files

1.4.4

2 release files

1.4.3

2 release files

1.4.2

2 release files

1.4.1

2 release files

This release

1.3.25 This release

2 release files

1.3.24

2 release files

1.3.23

2 release files

1.3.22

2 release files

1.3.21

2 release files

1.3.20

2 release files

1.3.18

2 release files

1.3.17

2 release files

1.3.13

2 release files

1.3.12

2 release files

1.3.11

2 release files

1.3.10

2 release files

1.3.9

2 release files

1.3.8

2 release files

1.3.7

2 release files

1.3.6

2 release files

1.3.5

2 release files

1.3.4

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.5

2 release files

1.1.4

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.10

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page