Código aberto · MIT · Um produto Montte

Um ponto único de assinatura tipado para cada documento.

A1/PKCS#12, PDF/PAdES, XML-DSig e provedores remotos, tudo nativo de Effect. Troque o assinador, mantenha o programa — navegador ou servidor, erros tipados, segredos Redacted.

Ler a documentação
  • Clicksign
  • Assinafy
  • ZapSign
  • DocuSeal
  • Documenso

Ao vivo · no seu navegador

Assine um PDF real, aqui mesmo.

Sem backend, sem upload, sem SaaS. Solte um PDF, clique onde a assinatura vai, carregue seu A1 (e-CPF / e-CNPJ) e assine com WebCrypto. O documento e a chave privada nunca saem da página.

signaturekit — assinador no navegador
01

Envie seu PDF

Renderizado localmente com pdf.js.

02

Clique para posicionar

Solte o retângulo de assinatura PAdES em qualquer lugar de qualquer página.

03

Assine com seu A1

Seu .pfx e a senha assinam no navegador via WebCrypto.

100% no cliente · WebCrypto · PAdES (AdES-BES)

Autoassinatura

Posicione uma vez. Assine a pilha inteira.

Vários contratos reais são gerados no seu navegador com @react-pdf/renderer, renderizados no mesmo canvas de posicionamento pdf.js que o assinador usa, e então posicionados e assinados automaticamente numa fila — um documento por vez.

Provedores remotos

Um SDK para cada assinador.

Oito provedores de assinatura, um único formato de requisição. Escolha um provedor — a chamada create*SignatureRequest muda, o código da sua aplicação não.

Adaptadores
Cada provedor é um create*SignatureRequest sobre um SignatureHttpClient compartilhado — o código específico do provedor fica fora do seu app.
Erros tipados
Nada lança exceção. Toda falha é um SignatureKitError no canal do Effect, marcado com o provedor e um código literal.
Segredos protegidos
Tokens e chaves de API permanecem em Redacted até a chamada HTTP — nunca logados, nunca vazados.
Um formato de requisição
A mesma requisição title / documents / recipients normaliza para um RemoteSignatureRequest em todos os oito provedores.
ProvedorClicksign
clicksign.ts
import { createClicksignSignatureRequest } from "@signature-kit/clicksign"
import { signatureHttpClientLive } from "@signature-kit/core/http"
import { Effect, Redacted } from "effect"

const request = yield* createClicksignSignatureRequest(
  {
    accessToken: Redacted.make(process.env.CLICKSIGN_TOKEN ?? ""),
    environment: "sandbox",
    locale: "pt-BR",
    autoClose: true,
  },
  {
    title: "Membership agreement",
    documents: [{ fileName: "agreement.pdf", mimeType: "application/pdf", content: pdfBytes }],
    recipients: [{ name: "Bruno Lima", email: "bruno@example.com", role: "signer" }],
  },
).pipe(Effect.provide(signatureHttpClientLive))

Sete capacidades

Tudo o que você assina, uma só API.

A1 / PKCS#12 no navegador ou no servidor, PDF·PAdES e XML-DSig, oito provedores remotos, um canal de erros tipado e uma camada React para assinatura no navegador — a mesma ergonomia nativa de Effect em todos os backends.

01
Um só serviço, todos os formatos
inspect, sign e verify partem de um único serviço Signatures — forneça uma layer e os mesmos três acessores conduzem todos os backends.
import { signatures } from "@signature-kit/core/signatures"
02
A1 no navegador ou no servidor
Carregue um A1 e-CPF / e-CNPJ (.pfx / PKCS#12) uma vez para uma layer Signatures; mesma chamada no servidor ou no navegador, senha guardada em Redacted.
a1SignaturesLayer({ pfx, password: Redacted.make(password) })
03
PDF, PAdES, ICP-Brasil
signPdf sela sob uma política PAdES: pades-icp-brasil para a cadeia ICP brasileira, ou pades-ades.
signPdf({ pdf, policy: "pades-icp-brasil" })
04
XML-DSig, por referência
signXml escreve um XML-DSig envelopado sobre um nó referenciado; verifyXml não precisa de layer — a chave viaja no documento.
signXml({ xml, referenceId: "nfe-1" })
05
Provedores remotos, um canal tipado
Clicksign, Assinafy, ZapSign, DocuSeal e Documenso recebem cada um um create*SignatureRequest sobre um único cliente HTTP.
createClicksignSignatureRequest(config, request)
06
Um canal de erros tipado
Nada lança exceção. Toda falha é um SignatureKitError carregando um de 18 códigos literais, capturado no canal de erros do Effect.
Effect.catchTag("SignatureKitError", handle)
07
Assine PDF no navegador
@signature-kit/pdf cuida de leitura de arquivo, estado de posicionamento e assinatura PDF A1 no navegador. O signer ao vivo renderiza a UI da app ao redor dessa fronteira tipada.
import { signBrowserPdf } from "@signature-kit/pdf/browser"

Dois passos

Sua primeira assinatura, de ponta a ponta.

Instale o núcleo e o assinador A1, depois construa uma layer e execute um programa que inspeciona o certificado e assina.

011. Instale
bun add @signature-kit/core @signature-kit/a1
npm install @signature-kit/core @signature-kit/a1
pnpm add @signature-kit/core @signature-kit/a1
yarn add @signature-kit/core @signature-kit/a1

@signature-kit/core é o ponto de entrada tipado. Cada assinador e formato é instalado apenas quando você precisa dele: /a1/pdf/xml

022. Faça sua primeira chamadafirst-signature.ts
import { a1SignaturesLayer } from "@signature-kit/a1/signer"
import { signatures } from "@signature-kit/core/signatures"
import { Effect, Redacted } from "effect"

// Load the A1 / PKCS#12 container once — pfx is the .pfx/.p12 *bytes*.
const layer = a1SignaturesLayer({
  pfx,
  password: Redacted.make(process.env.A1_PASSWORD ?? ""),
})

// Inspect the certificate, then sign — typed errors, no thrown exceptions.
const program = Effect.gen(function* () {
  const identity = yield* signatures.inspect()

  const artifact = yield* signatures.sign({
    content,
    algorithm: "rsa-sha256",
  })

  return { identity, artifact }
}).pipe(Effect.provide(layer))

const { identity, artifact } = await Effect.runPromise(program)

runPromiseresolve para aidentityanalisada e oartifactassinado. A partir daqui, troque a layer A1 por um formato —signPdfousignXml— ou entregue o programa a um provedor remoto.

Apoiado por

Quando você quiser

Implemente a camada de assinatura uma vez.

Código aberto, licença MIT, nativo de Effect. A1, PDF, XML e provedores remotos sob um único programa tipado — cada falha um valor no qual você pode fazer match.

Início rápido