Sviluppatori · API · Webhook

Un POST. Inviato per la firma.

Un'API REST per inviare PDF da firmare e seguire ogni firmatario, webhook firmati per ogni passaggio, chiavi di idempotenza e codici di errore stabili. Chiavi API e webhook sono inclusi nel piano Enterprise.

Cosa puoi costruire: firme dal tuo software
curl https://api.wesign.now/v1/signing-requests \
  -H "Authorization: Bearer $WSK_KEY" \
  -H "Idempotency-Key: order-123/sign" \
  -F "file=@contract.pdf" \
  -F 'signers=[{"email":"jane@acme.com","role":"client"}]' \
  -F "placement=auto_append"

# → 201 Created
# {
#   "documentId": "8a1e4f9a-…",
#   "status": "pending",
#   "signers": [{
#     "role": "client",
#     "signingUrl": "https://acme.wesign.now/en/sign/…",
#     "emailed": true, …
#   }], …
# }
Cosa ottieni

Un'API, webhook e una documentazione che anche i tuoi strumenti sanno leggere.

API REST

Invia un PDF, segui ogni firmatario, invia un promemoria o ritira la richiesta, scarica il PDF sigillato e il suo audit trail. Chiavi Bearer, risposte JSON e una specifica OpenAPI 3.1 con un id per ogni operazione.

Panoramica dell'API

Webhook firmati

signing_request.sent, .viewed, .signed, document.completed e altri, ognuno firmato con HMAC-SHA256. Una consegna non riuscita viene ritentata per circa 45 ore; dal registro delle consegne puoi inviarla di nuovo.

Eventi webhook

Documentazione per assistenti IA

llms.txt elenca ogni pagina della documentazione, llms-full.txt le contiene tutte in testo semplice, openapi.json la forma esatta di richieste e risposte. Dalli al tuo assistente di programmazione.

Per gli assistenti IA

Esempi concreti.

Quattro chiamate che servono alla maggior parte delle integrazioni. Nomi dei campi come nella specifica OpenAPI.

1. Invio con posizionamento ad ancora

Inserisci nel PDF un marcatore come [[ls:signature:buyer]]. Lì posizioniamo il campo firma dell'acquirente e nascondiamo il marcatore. Nessun marcatore nel PDF? Aggiungiamo una pagina di firma.

POST /v1/signing-requests
Content-Type: multipart/form-data

file=@offer.pdf        # the PDF contains [[ls:signature:buyer]]
signers=[{"email":"buyer@acme.com","role":"buyer","name":"Ann Buyer"}]
placement=anchors

2. Più firmatari, in ordine

Tre firmatari, uno dopo l'altro. Il firmatario 2 viene invitato solo dopo che il firmatario 1 ha firmato.

POST /v1/signing-requests
Content-Type: multipart/form-data

file=@contract.pdf
signing_mode=sequential
placement=auto_append
signers=[
  {"email":"founder@acme.com","role":"founder"},
  {"email":"investor@vc.example","role":"investor"},
  {"email":"witness@law.example","role":"witness"}
]

3. Ricevitore di webhook

Controlla il timestamp e l'HMAC sul corpo grezzo, poi gestisci l'evento.

// Node + Express. The full verifier (Node and PHP) is in the docs.
app.post('/wesign/callback', express.raw({ type: 'application/json' }), (req, res) => {
  // X-WeSign-Signature: t=<unix seconds>,v1=<hex>  (two v1 for 24 h after a rotation)
  const parts = (req.get('x-wesign-signature') ?? '').split(',')
  const t = parts[0]?.startsWith('t=') ? parts[0].slice(2) : ''
  if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return res.status(401).end()
  const expected = crypto.createHmac('sha256', SECRET)
    .update(`${t}.${req.body}`).digest()
  const valid = parts.filter((p) => p.startsWith('v1=')).some((p) => {
    const got = Buffer.from(p.slice(3), 'hex')
    return got.length === expected.length && crypto.timingSafeEqual(got, expected)
  })
  if (!valid) return res.status(401).end()

  const evt = JSON.parse(req.body.toString('utf8'))
  if (evt.event === 'document.completed') {
    // fetch evt.signed_pdf_url with your API key, compare evt.sha256, keep a copy
  }
  res.sendStatus(200)
})

4. Nuovo tentativo idempotente

La stessa chiave con lo stesso corpo entro 24 ore restituisce di nuovo la prima risposta: un nuovo tentativo dopo un errore di rete non invia mai due volte.

POST /v1/signing-requests
Idempotency-Key: order-123/sign

# First call:                      201 Created
# Same key + same body (24 h):     201, the same body, Idempotent-Replayed: true
# Same key while the first runs:   409 idempotency_in_progress + Retry-After
# Same key + a different body:     422 idempotency_key_reuse

Pensato per la produzione.

Chiavi Bearer, due ambiti

Ogni chiave appartiene a un solo workspace. Una chiave full chiama tutta l'API; una chiave embedded gestisce solo le sessioni di firma integrata. Limita una chiave ai tuoi indirizzi IP; una revoca ha effetto subito.

60 richieste al minuto per chiave

Una finestra fissa per chiave su tutti gli endpoint /v1. Le risposte riuscite hanno gli header RateLimit-*; una 429 ha Retry-After.

Codici di errore stabili

Ogni errore è un JSON con un messaggio leggibile (error), un code stabile e, dove serve, meta. Controlla il code; il messaggio può cambiare.

PDF sigillati e verificabili

Il PDF firmato porta un sigillo PAdES che qualsiasi lettore conforme può verificare. L'audit trail elenca ogni evento con l'orario, l'e-mail e l'indirizzo IP mascherato del firmatario e ogni verifica con codice SMS.

L'accesso API è incluso in Enterprise.

Chiavi API e webhook fanno parte del piano Enterprise. Dicci cosa vuoi collegare. La documentazione è pubblica: puoi leggerla prima.