Official Python SDK for the Clicksign e-signature API (v3)
Project description
Clicksign Python SDK
Cliente Python para a Clicksign API v3 (JSON:API). Requer Python >= 3.10, sem dependências de runtime (apenas stdlib). Documentação detalhada em docs/.
Índice
- Instalação
- Configuração
- Multi-conta
- Timeouts, retry e instrumentação
- Início rápido
- Fluxo de assinatura (notarial) (criar → ativar → notificar → eventos)
- Filtros, ordenação e paginação
- Outros recursos
- Tratamento de erros
- Ambientes
- Async (FastAPI, asyncio)
- HTTP transport e connection pool
- Limitações e produção
- Desenvolvimento
Fluxo completo:
docs/WORKFLOW.md— envelope → documento → signatário → ativação passo a passo.
Examples:
docs/examples/— receitas prontas para retry, webhooks, multi-tenant, observabilidade e connection pool.
Contrato do SDK:
docs/SDK_CONTRACT.md— timeouts, retry, JSON:API, erros e paginação.
Observabilidade:
docs/OBSERVABILITY.md— hooks, log, correlation id, structlog, OpenTelemetry, PII.
Instalação
pip install clicksign-python-sdk
O módulo importado continua sendo clicksign (import clicksign).
Extras opcionais:
pip install clicksign-python-sdk[httpx] # connection pooling (alto QPS)
pip install clicksign-python-sdk[async] # AsyncClicksignClient (requer httpx)
Configuração
Dois padrões principais — escolha com base em como sua aplicação gerencia credenciais:
| Padrão | Quando usar |
|---|---|
configure() + resources |
Uma API key por processo; scripts; workers simples |
ClicksignClient |
Múltiplas keys; dependências explícitas; código novo |
Configuração global (single tenant)
import clicksign
from clicksign import Envelope, Document
clicksign.configure(
api_key="YOUR_API_KEY",
environment="sandbox", # or "production"
)
envelopes = Envelope.list()
envelope = Envelope.create(name="Contrato", locale="pt-BR")
document = Document.create(
envelope.id,
filename="contrato.pdf",
content_base64="...",
)
Cliente explícito (ClicksignClient)
from clicksign import ClicksignClient
client = ClicksignClient(api_key="YOUR_API_KEY", environment="sandbox")
envelopes = client.notarial.envelopes.list()
envelope = client.notarial.envelopes.create(name="Contrato", locale="pt-BR")
# Alias direto (shorthand)
envelope = client.envelopes.retrieve(envelope.id)
envelope.update(name="Contrato atualizado")
Multi-conta
Para apps multi-tenant onde cada requisição/job usa uma API key diferente, use Services para vincular um cliente à thread atual:
from clicksign import Envelope, Services
tenant = Services(api_key="TENANT_API_KEY", environment="sandbox")
with tenant.use():
Envelope.list() # roteado pelo cliente deste tenant
Services.use() define cliente HTTP e bulk para a thread. Em runtime async/fiber, prefira ClicksignClient ou AsyncClicksignClient explícito — contexto thread-local pode não se propagar.
Timeouts, retry e instrumentação
Timeouts por requisição
from clicksign import ClicksignClient, RequestOptions
client = ClicksignClient(api_key="YOUR_API_KEY", environment="sandbox")
client.envelopes.create(
name="Contrato",
options=RequestOptions(
read_timeout=30.0,
open_timeout=5.0,
),
)
Timeouts separados: open_timeout (TCP connect), write_timeout (envio do corpo), read_timeout (resposta).
Retry
Padrão 3 retries com full-jitter exponential backoff. Desative por chamada:
client.envelopes.retrieve("uuid", options={"max_retries": 0})
BulkRequirement.create retenta apenas TimeoutError — operações atômicas não são idempotentes.
Correlação de requisições
from clicksign import RequestOptions, correlation_id
client.envelopes.retrieve(
"uuid",
options=RequestOptions(headers=correlation_id("req-123")),
)
Em falhas, use error.request_id (header X-Request-Id) para tickets de suporte da Clicksign.
Hooks de instrumentação
import clicksign
clicksign.on_request(lambda e: print(e["method"], e["path"], e["status"]))
clicksign.on_retry(lambda e: print(e["attempt"], e["wait_ms"]))
clicksign.on_error(lambda e: print(e["error"]))
Veja docs/OBSERVABILITY.md para exemplos com structlog, OpenTelemetry e Prometheus, e como evitar PII em handlers on_error.
Log HTTP integrado
export CLICKSIGN_LOG=debug # ou info, warn, error
clicksign.configure(log="debug")
# Usa stdlib logger "clicksign"; header Authorization nunca é logado.
Início rápido
from clicksign import ClicksignClient
client = ClicksignClient(api_key="YOUR_API_KEY", environment="sandbox")
# Criar envelope
envelope = client.notarial.envelopes.create(name="Contrato NDA", locale="pt-BR")
# Adicionar documento
doc = client.notarial.documents.create(
envelope.id,
filename="nda.pdf",
content_base64="...",
)
# Adicionar signatário
signer = client.notarial.signers.create(
envelope.id,
name="Ana Souza",
email="ana@example.com",
has_documentation=True,
)
# Requisito de assinatura (atomic)
client.notarial.bulk_requirements.create(
envelope.id,
block=lambda ops: ops.add_agree(
signer_id=signer.id,
document_id=doc.id,
role="sign",
),
)
# Ativar envelope
envelope.update(status="running")
Fluxo de assinatura (notarial)
1. Envelope
envelope = client.notarial.envelopes.create(name="Contrato", locale="pt-BR")
envelope.update(deadline_at="2025-12-31T23:59:59Z")
2. Documento
import base64
doc = client.notarial.documents.create(
envelope.id,
filename="contrato.pdf",
content_base64=base64.b64encode(open("contrato.pdf", "rb").read()).decode(),
)
3. Signatário
signer = client.notarial.signers.create(
envelope.id,
name="João Silva",
email="joao@example.com",
has_documentation=True,
documentation="123.456.789-09",
)
4. Requisitos de assinatura (bulk atômico)
client.notarial.bulk_requirements.create(
envelope.id,
block=lambda ops: (
ops.add_agree(signer_id=signer.id, document_id=doc.id, role="sign"),
ops.add_provide_evidence(signer_id=signer.id, document_id=doc.id, auth="email"),
),
)
5. Ativar
envelope.update(status="running")
# ou: Envelope.activate(envelope.id) — POST /envelopes/:id/activate
6. Notificar signatários
from clicksign.resources.notarial.signer import Signer
# Um signatário (envelope_id e signer_id obrigatórios)
Signer.notify(envelope.id, signer.id, message="Seu contrato está disponível para assinatura.")
# Todos os pendentes do envelope
envelope.notify(message="Seu contrato está disponível para assinatura.")
Detalhes: docs/WORKFLOW.md (seção 6).
7. Monitorar eventos
from clicksign.resources.notarial.envelope import Envelope
for event in Envelope.list_events(envelope.id):
print(event.name, event.created)
# Eventos por documento (ex.: read, sign, custom)
from clicksign.resources.notarial.document import Document
for event in Document.list_events(doc.id, envelope_id=envelope.id):
print(event.name, event.data)
# Callbacks em tempo real: docs/examples/03-webhooks.md
Filtros, ordenação e paginação
# QueryProxy chain
drafts = (
client.envelopes
.filter(status="draft")
.order("-created_at")
.per(20)
.with_includes("folder")
.to_list()
)
# Auto-paginação (itera todas as páginas)
for envelope in client.envelopes.filter(status="running"):
print(envelope.id)
# page() + per() explícitos
page1 = client.envelopes.page(1).per(10).to_list()
per() máximo 50 — veja docs/PAGINATION.md.
JSON:API sideload (included)
envelopes = client.envelopes.with_includes("folder").to_list()
print(envelopes[0].folder.name) # sem chamada HTTP extra
Outros recursos
| Namespace | Resource |
|---|---|
client.notarial.envelopes |
Envelope |
client.notarial.documents |
Document |
client.notarial.signers |
Signer |
client.notarial.requirements |
Requirement |
client.notarial.bulk_requirements |
BulkRequirement |
client.notarial.signature_watchers |
SignatureWatcher |
| — (nested) | Event — Envelope.list_events, Document.list_events, Event.create_for_document |
client.webhooks |
Webhook |
client.users |
User |
client.templates / client.template_fields |
Template, TemplateField |
client.memberships / client.groups |
Membership, Group |
client.folders |
Folder |
client.access_control_lists |
AccessControlList |
client.envelope_bulk_creations |
EnvelopeBulkCreation |
client.acceptance_term.whatsapps |
Whatsapp |
client.auto_signature.terms |
Term |
Endpoints sem resource dedicado:
raw = client.raw_request("get", "/beta/feature")
envelope = client.deserialize(raw, Envelope)
print(envelope.last_response.status)
User-Agent e identificação da aplicação
clicksign.set_app_info("My CRM", "2.1.0", "https://example.com")
# User-Agent: clicksign-python/x.y.z Python/3.10.x My_CRM/2.1.0
Telemetria do provider (opt-in)
clicksign.configure(enable_telemetry=True)
Envia métricas de latência anonimizadas (sem API keys nem corpos). Desativado por padrão.
Tratamento de erros
from clicksign.errors import (
AuthenticationError,
PermissionError,
NotFoundError,
ValidationError,
RateLimitError,
ServerError,
TimeoutError,
)
try:
client.envelopes.create(name="")
except ValidationError as err:
print(err.message) # primeiro detalhe (compatível)
print(err.error_code) # código do primeiro erro
print(err.source_pointer) # ex: /data/attributes/name
for api_error in err.api_errors:
print(api_error.pointer, api_error.detail)
except RateLimitError as err:
print(err.rate_limit_reset)
except ServerError as err:
if err.retryable:
...
| Exceção | Status HTTP |
|---|---|
AuthenticationError |
401 |
PermissionError |
403 |
NotFoundError |
404 |
ValidationError |
400, 422 |
RateLimitError |
429 |
ServerError |
5xx |
TimeoutError |
timeout de rede |
Ambientes
| Ambiente | Base URL |
|---|---|
sandbox |
https://sandbox.clicksign.com/api/v3 |
production |
https://app.clicksign.com/api/v3 |
client = ClicksignClient(api_key="...", environment="production")
Async (FastAPI, asyncio)
Requer pip install clicksign-python-sdk[async]. Receita completa: docs/examples/13-async-fastapi.md.
import asyncio
from clicksign import AsyncClicksignClient
async def main():
async with AsyncClicksignClient(api_key="YOUR_API_KEY", environment="sandbox") as client:
envelopes = await client.notarial.envelopes.list()
async for env in client.envelopes.filter(status="draft"):
print(env.id)
envelope = await client.envelopes.retrieve("uuid")
await envelope.update_async(status="running")
# Ativar: await client.notarial.envelopes.activate(envelope.id)
asyncio.run(main())
- Não use
Services.use()no asyncio — useAsyncClicksignClientexplícito. - Paginação:
.page(n)só vale com.first();.to_list()auto-pagina desde a página 1 —docs/PAGINATION.md.
HTTP transport e connection pool
Padrão: UrllibHTTPClient (stdlib, sem connection pool — um handshake TCP/TLS por requisição). Adequado para scripts e baixo QPS.
Alto QPS: instale clicksign-python-sdk[httpx] e injete um cliente compartilhado:
from clicksign import ClicksignClient, HttpxHTTPClient
http = HttpxHTTPClient() # um por processo / worker
client = ClicksignClient(api_key="...", environment="production", http_client=http)
AsyncClicksignClient usa httpx com connection pool no event loop.
Receita singleton: docs/examples/12-http-connection-pool.md.
Limitações e produção
UrllibHTTPClientnão reutiliza conexões — useHttpxHTTPClientsob carga.Services.use()usathreading.local()— incompatível com asyncio/trio.- Operações bulk atômicas retentam apenas
TimeoutError(não são idempotentes). - Includes aninhados dependem do que a API retorna; tipos desconhecidos fazem fallback para
Resourcebase.
Veja docs/examples/08-production-limitations.md.
Desenvolvimento
pip install -e ".[dev]"
pytest
pytest --cov=clicksign --cov-report=term-missing
ruff format .
ruff check .
mypy
Licença
MIT — veja LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clicksign_python_sdk-0.1.2.tar.gz.
File metadata
- Download URL: clicksign_python_sdk-0.1.2.tar.gz
- Upload date:
- Size: 41.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d5fedde69848fce0a53bfbc20c60dc05c20421aba9a7a51d19e90e29af6904a
|
|
| MD5 |
bcd79f5318a8c19511037479b2a3e2ba
|
|
| BLAKE2b-256 |
210f3569ee683f0bc9a54c99ac5e44eef3437e8da3f7137ba02059895f14f3f5
|
File details
Details for the file clicksign_python_sdk-0.1.2-py3-none-any.whl.
File metadata
- Download URL: clicksign_python_sdk-0.1.2-py3-none-any.whl
- Upload date:
- Size: 71.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6393df95e7f7c477088635f27e8daf684cbe919925529b9511c487b82a588ea5
|
|
| MD5 |
9d9e750745dbe734ecd4ca872def0ca5
|
|
| BLAKE2b-256 |
e0b6a88319c295996c11825922ad1c86f9685f6ff2f248bb2ec49e3a9d663e3f
|