Skip to main content

Official Python SDK for the Clicksign e-signature API (v3)

Project description

Clicksign Python SDK

versão CI Python TestPyPI PyPI licença documentação API v3

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


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) EventEnvelope.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 — use AsyncClicksignClient explí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

  • UrllibHTTPClient não reutiliza conexões — use HttpxHTTPClient sob carga.
  • Services.use() usa threading.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 Resource base.

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

clicksign_python_sdk-0.1.2.tar.gz (41.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clicksign_python_sdk-0.1.2-py3-none-any.whl (71.9 kB view details)

Uploaded Python 3

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

Hashes for clicksign_python_sdk-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3d5fedde69848fce0a53bfbc20c60dc05c20421aba9a7a51d19e90e29af6904a
MD5 bcd79f5318a8c19511037479b2a3e2ba
BLAKE2b-256 210f3569ee683f0bc9a54c99ac5e44eef3437e8da3f7137ba02059895f14f3f5

See more details on using hashes here.

File details

Details for the file clicksign_python_sdk-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for clicksign_python_sdk-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 6393df95e7f7c477088635f27e8daf684cbe919925529b9511c487b82a588ea5
MD5 9d9e750745dbe734ecd4ca872def0ca5
BLAKE2b-256 e0b6a88319c295996c11825922ad1c86f9685f6ff2f248bb2ec49e3a9d663e3f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page