Clicksign Ruby SDK
Cliente Ruby oficial para a API v3 da Clicksign (JSON:API). Permite criar envelopes, adicionar documentos e signatários, configurar requisitos de assinatura, webhooks e demais recursos da plataforma com uma API idiomática em Ruby.
Requisitos: Ruby >= 3.0 · dependências de runtime: apenas biblioteca padrão (net/http, json).
Documentação da API: Sandbox · Produção · Referência interna: docs/SPEC.md
Índice
- Instalação
- Configuração
- Início rápido
- Fluxo de assinatura (notarial)
- Filtros, ordenação e paginação
- Outros recursos
- Tratamento de erros
- Ambientes
- Desenvolvimento
- Licença
Exemplo passo a passo:
docs/WORKFLOW.md— fluxo completo de envelope → documento → signatário → requisitos → ativação → notificação.
Instalação
Adicione ao Gemfile:
source 'https://rubygems.org'
gem 'clicksign-ruby-sdk'
Depois:
bundle install
Ou instale diretamente:
gem install clicksign-ruby-sdk
Configuração
Configure a chave de API e a URL base uma vez no boot da aplicação (initializer, config/initializers/clicksign.rb, script, etc.):
require 'clicksign'
Clicksign.configure do |c|
c.api_key = ENV.fetch('CLICKSIGN_API_KEY')
c.base_url = ENV.fetch('CLICKSIGN_API_BASE_URL', 'https://sandbox.clicksign.com/api/v3')
end
A API usa o header Authorization: <seu-token> sem o prefixo Bearer.
Segurança: não commite tokens no código. Use variáveis de ambiente ou cofre de secrets (Rails credentials, etc.).
Para testar interativamente no console da gem:
CLICKSIGN_API_KEY=seu-token bundle exec ruby bin/console
Início rápido
Listar envelopes em rascunho e criar um novo:
require 'clicksign'
Clicksign.configure do |c|
c.api_key = ENV['CLICKSIGN_API_KEY']
c.base_url = 'https://sandbox.clicksign.com/api/v3'
end
Envelope = Clicksign::Resources::Notarial::Envelope
# Listar com filtro
drafts = Envelope.filter(status: 'draft').to_a
puts drafts.map { |e| [e.id, e.name, e.status] }
# Criar envelope (status inicial: draft)
envelope = Envelope.create(
name: 'Contrato de prestação de serviços',
locale: 'pt-BR',
auto_close: true
)
puts envelope.id # UUID do envelope
puts envelope.status # => "draft"
Buscar, atualizar e excluir:
found = Envelope.retrieve(envelope.id)
found.update(name: 'Contrato — revisão 2')
found.delete
Fluxo de assinatura (notarial)
Namespace principal: Clicksign::Resources::Notarial.
1. Envelope
Envelope = Clicksign::Resources::Notarial::Envelope
Folder = Clicksign::Resources::Folder
# Opcional: associar a uma pasta
folder = Folder.filter(in_root: true).first
envelope = Envelope.create(
name: 'Proposta comercial #1042',
folder_id: folder&.id,
deadline_at: '2026-12-31T23:59:59.000-03:00',
default_subject: 'Documentos para assinatura',
default_message: 'Por favor, assine os documentos em anexo.'
)
2. Documento
Envie o PDF em Base64, via URL ou a partir de um template:
Document = Clicksign::Resources::Notarial::Document
document = Document.create(
envelope_id: envelope.id,
filename: 'contrato.pdf',
content_base64: 'data:application/pdf;base64,JVBERi0xLjQK...'
)
# Alternativas (mutuamente exclusivas na API):
# content_url: 'https://exemplo.com/arquivo.pdf'
# template: { key: template_id, data: {} } # filename deve ser .doc ou .docx
# Listar documentos do envelope
Envelope.list_documents(envelope.id).each do |doc|
puts "#{doc.id} — #{doc.filename} (#{doc.status})"
end
3. Signatário
Signer = Clicksign::Resources::Notarial::Signer
signer = Signer.create(
envelope_id: envelope.id,
name: 'Maria Silva',
email: 'maria.silva@example.com',
phone_number: '11999998888',
has_documentation: true,
documentation: '12345678909',
refusable: true,
communicate_events: {
signature_request: 'email', # canal de convite para assinar
signature_reminder: 'email', # canal de lembrete automático
document_signed: 'email', # canal de confirmação pós-assinatura
},
)
# Reenviar notificação por e-mail
signer.notify(message: 'Lembrete: seu documento aguarda assinatura.')
# Ou via classe
Signer.notify(signer.id, envelope_id: envelope.id, message: 'Lembrete de assinatura')
4. Requisitos (requirements)
Cada requisito associa um signatário a um documento com uma ação (agree, provide_evidence, rubricate). O envelope precisa estar em draft para criar ou remover requisitos.
4.1 Endpoint padrão
POST /envelopes/:envelope_id/requirements — uma operação por requisição.
Requirement = Clicksign::Resources::Notarial::Requirement
rels = {
document: { data: { type: 'documents', id: document.id } },
signer: { data: { type: 'signers', id: signer.id } },
}
# Concordância (agree)
agree = Requirement.create(
envelope_id: envelope.id,
action: 'agree',
role: 'sign',
relationships: rels
)
# Evidência de autenticação (ex.: e-mail)
Requirement.create(
envelope_id: envelope.id,
action: 'provide_evidence',
auth: 'email',
relationships: rels
)
# Rubrica em todas as páginas
Requirement.create(
envelope_id: envelope.id,
action: 'rubricate',
pages: 'all',
relationships: rels
)
# Rubrica em campo específico do documento
Requirement.create(
envelope_id: envelope.id,
action: 'rubricate',
rubric_field: 'campo_rubrica_1',
relationships: rels
)
# Consultar
Requirement.retrieve(agree.id, envelope_id: envelope.id)
Envelope.list_requirements(envelope.id, 'signer.key': signer.id)
Requirement.list_for_document(document.id)
Requirement.list_for_signer(signer.id)
# Remover (envelope em draft)
agree.delete
4.2 Operações em lote (bulk)
POST /envelopes/:envelope_id/bulk_requirements — várias operações em uma requisição (atomic:operations → atomic:results). Indicado quando você monta o setup completo de uma vez.
BulkRequirement = Clicksign::Resources::Notarial::BulkRequirement
response = BulkRequirement.create(envelope_id: envelope.id) do |ops|
ops.add_agree(
signer_id: signer.id,
document_id: document.id,
role: 'sign'
)
ops.add_provide_evidence(
signer_id: signer.id,
document_id: document.id,
auth: 'email'
)
ops.add_rubricate(
signer_id: signer.id,
document_id: document.id,
pages: 'all'
)
# ops.remove(requirement_id: requisito_antigo.id)
end
if response.success?
response.requirements.each { |r| puts "OK: #{r.id} (#{r.action})" }
else
response.failures.each do |failure|
puts "Falha na operação #{failure.index}: #{failure.errors}"
end
end
| Abordagem | Endpoint | Quando usar |
|---|---|---|
| 4.1 Padrão | /requirements |
Criar/alterar requisitos um a um, fluxos incrementais |
| 4.2 Bulk | /bulk_requirements |
Várias ações na mesma chamada; tratar sucesso/falha por slot |
5. Ativar o envelope
Atualize o status para running via PATCH:
activated = envelope.update(status: 'running')
puts activated.status # => "running"
6. Observadores e eventos
SignatureWatcher = Clicksign::Resources::Notarial::SignatureWatcher
Event = Clicksign::Resources::Notarial::Event
watcher = SignatureWatcher.create(
envelope_id: envelope.id,
email: 'compliance@empresa.com',
kind: 'all_steps',
attach_documents_enabled: true
)
# Eventos do envelope
Envelope.list_events(envelope.id)
# Eventos de um documento
Document.list_events(document.id, envelope_id: envelope.id)
# Criar evento customizado no documento
Event.create_for_document(
envelope_id: envelope.id,
document_id: document.id,
name: 'custom',
data: { description: 'Etapa interna concluída' }
)
Filtros, ordenação e paginação
A API de listagem é chainable:
Envelope
.filter(status: 'running', name: 'Contrato')
.order('-created')
.page(1)
.per(20)
.to_a
# Atalho quando há poucos filtros
Template.filter(name: 'NDA padrão').first
# Navegação no resultado
Envelope.order('-created').first # mais recente
Envelope.order('-created').last # mais antigo
Envelope.filter(status: 'draft').count # total de rascunhos
Atributos dos objetos retornados são acessados como métodos ou por chave string:
envelope.name # método gerado dinamicamente
envelope['name'] # equivalente via operador []
envelope['status'] # útil quando a chave é uma variável
O QueryProxy inclui Enumerable, então each, map, select e afins funcionam diretamente na chain sem precisar de .to_a:
Envelope.filter(status: 'draft').each { |e| puts e.id }
Envelope.filter(status: 'running').map(&:name)
Envelope.order('-created').select { |e| e.auto_close }
Outros recursos
| Recurso | Classe | Exemplo |
|---|---|---|
| Webhook | Clicksign::Resources::Webhook |
Webhook.create(endpoint: 'https://...', events: ['envelope.completed'], status: 'active') |
| Pasta | Clicksign::Resources::Folder |
Folder.create(name: 'Contratos 2026', folder_id: pai&.id) |
| Template | Clicksign::Resources::Template |
Template.list · Template.list_template_fields(id) |
| Usuário | Clicksign::Resources::User |
User.me · User.filter(email: '...') |
| Membership | Clicksign::Resources::Membership |
Membership.create(role: 'member', user_id: user.id) |
| Grupo | Clicksign::Resources::Group |
Group.add_users(group_id, [user.id]) |
| ACL pasta/grupo | Clicksign::Resources::AccessControlList |
AccessControlList.create(folder_id:, group_id:) |
| Criação em lote de envelopes | Clicksign::Resources::EnvelopeBulkCreation |
Ver exemplo abaixo |
| Auto assinatura | Clicksign::Resources::AutoSignature::Term |
AutoSignature::Term.create(...) |
| Termo WhatsApp | Clicksign::Resources::AcceptanceTerm::Whatsapp |
AcceptanceTerm::Whatsapp.list |
Exemplo de webhook:
Webhook = Clicksign::Resources::Webhook
hook = Webhook.create(
endpoint: 'https://minhaapp.com/webhooks/clicksign',
events: %w[sign close cancel add_signer],
status: 'active'
)
hook.update(status: 'inactive')
hook.delete
Exemplo de usuário e membership:
User = Clicksign::Resources::User
Membership = Clicksign::Resources::Membership
eu = User.me
puts "#{eu.name} <#{eu.email}>"
novo = User.create(
name: 'João Integração',
email: 'joao.integracao@example.com',
phone_number: '11988887777'
)
Membership.create(role: 'admin', user_id: novo.id)
Criação de envelope em lote (job assíncrono):
EnvelopeBulkCreation = Clicksign::Resources::EnvelopeBulkCreation
job = EnvelopeBulkCreation.create(
envelope: { name: 'Contrato Lote', locale: 'pt-BR', auto_close: true },
document: {
filename: 'contrato.docx',
content_base64: 'data:application/msword;base64,...'
},
signers: [
{
name: 'Carlos',
email: 'carlos@example.com',
requirements: [{ action: 'agree', role: 'sign', auth: 'email' }]
}
]
)
puts job.job_id # UUID do job enfileirado
puts job.enqueued_at # timestamp de enfileiramento
Controle de acesso em pasta:
AccessControlList = Clicksign::Resources::AccessControlList
AccessControlList.create(folder_id: folder.id, group_id: group.id)
AccessControlList.destroy(folder_id: folder.id, group_id: group.id)
Tratamento de erros
Erros HTTP são convertidos em exceções antes de chegar ao seu código:
| HTTP | Exceção |
|---|---|
| 401, 403 | Clicksign::AuthenticationError |
| 404 | Clicksign::NotFoundError |
| 400, 422 | Clicksign::ValidationError |
| 409 | Clicksign::ConflictError |
| 429 | Clicksign::RateLimitError |
| 5xx | Clicksign::ServerError |
| Timeout / conexão | Clicksign::TimeoutError |
Exemplo:
begin
Envelope.retrieve('00000000-0000-0000-0000-000000000000')
rescue Clicksign::NotFoundError
puts 'Envelope não encontrado'
rescue Clicksign::ValidationError => e
puts "Dados inválidos: #{e.}"
rescue Clicksign::AuthenticationError
puts 'Verifique CLICKSIGN_API_KEY'
end
Operações em lote (BulkRequirement) podem retornar falhas por slot em response.failures sem lançar exceção, quando a API responde com atomic:results parcial.
Ambientes
| Ambiente | base_url |
|---|---|
| Sandbox | https://sandbox.clicksign.com/api/v3 |
| Produção | https://app.clicksign.com/api/v3 |
O padrão da gem em Clicksign::Configuration é produção (app.clicksign.com). Para desenvolvimento, defina explicitamente o sandbox:
Clicksign.configure do |c|
c.api_key = ENV['CLICKSIGN_API_KEY']
c.base_url = 'https://sandbox.clicksign.com/api/v3'
end
Gere tokens de API no painel da Clicksign do ambiente correspondente.
Desenvolvimento
Clone o repositório e instale dependências de desenvolvimento:
bundle install
bundle exec rspec
| Variável | Uso |
|---|---|
CLICKSIGN_API_KEY |
Token para testes contra sandbox (opcional) |
CLICKSIGN_API_BASE_URL |
URL da API (padrão sandbox nos specs de integração legados) |
A suíte principal usa WebMock e não exige rede. Alguns specs antigos ainda podem usar VCR com gravação no sandbox.
Estrutura relevante:
lib/clicksign/
client.rb # HTTP (GET, POST, PATCH, DELETE)
resource.rb # CRUD base, filtros, nested lists
resources/notarial/ # Envelope, Document, Signer, Requirement, ...
json_api/ # Serializer, Parser, bulk operations
docs/SPEC.md # mapa completo de resources e rotas
Licença
MIT — ver clicksign-ruby-sdk.gemspec.