API Reference
Tutti gli endpoint sono REST/JSON, accettano e restituiscono application/json (con eccezione dei download PDF, binari). Le date sono in formato ISO 8601 UTC. Gli ID di risorsa sono UUID v4.
Base URL
https://api.ezysign.net/api/v1Autenticazione
Tutti gli endpoint sotto /dossiers richiedono l'header X-API-Key. Le chiavi sono associate al tenant: ogni dossier creato eredita automaticamente l'identità del chiamante.
X-API-Key: esf_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxRate limiting
/api/v1/dossiers/*: 120 richieste / minuto per chiave API/verify/*: 20 richieste / minuto per IP
Quando il limite viene superato il server risponde con 429 Too Many Requests. Riprova con backoff esponenziale.
Codici di stato HTTP
| Codice | Significato |
|---|---|
200 OK | Richiesta riuscita |
400 Bad Request | Payload mancante o non valido (vedi message) |
401 Unauthorized | Header X-API-Key mancante o chiave non valida |
403 Forbidden | Operazione non consentita sullo stato corrente del dossier |
404 Not Found | Risorsa inesistente o non appartenente al tenant chiamante |
413 Payload Too Large | Body oltre 25 MB |
429 Too Many Requests | Rate limit superato |
500 Internal Server Error | Errore inatteso, riportare al supporto allegando il request-id |
Formato errori
{
"statusCode": 400,
"message": "Documento non e' un PDF valido",
"error": "Bad Request"
}POST /dossiers
Crea un nuovo dossier di firma e invia immediatamente l'OTP al firmatario.
Body
| Campo | Tipo | Obbl. | Descrizione |
|---|---|---|---|
signer.firstName | string (1-100) | sì | Nome del firmatario |
signer.lastName | string (1-100) | sì | Cognome del firmatario |
signer.email | string (email) | sì | Email del firmatario (sempre richiesta, anche con OTP via SMS) |
signer.phone | string | cond. | Telefono in formato E.164. Obbligatorio se otpChannel = sms |
signer.taxCode | string (max 32) | no | Codice fiscale, riportato nel report di evidenze |
otpChannel | "email" | "sms" | sì | Canale di invio del codice OTP |
document.name | string (1-200) | sì | Nome file mostrato al firmatario |
document.contentBase64 | string (base64) | sì | Contenuto del PDF codificato in base64 |
signPoints | array (max 20) | no | Coordinate dei riquadri di firma (vedi sotto) |
callbackUrl | string (URL https) | no | Endpoint per la ricezione di webhook eventi |
metadata | object | no | Coppie chiave/valore di tua scelta, ritornate nei webhook |
expiresInHours | integer (1-720) | no | Validità del link firma. Default: 168 (7 giorni) |
Schema signPoint
Le coordinate sono percentuali rispetto a larghezza/altezza della pagina (origine in basso a sinistra), così non dipendono dal formato (A4, Letter, custom):
{
"page": 3, // 1-based
"x": 60, // 0-100 (% larghezza)
"y": 10, // 0-100 (% altezza, dal basso)
"width": 35, // 1-100 (% larghezza)
"height": 10, // 1-30 (% altezza)
"label": "Firma Cliente" // opzionale, max 120 char
}Risposta 200
{
"id": "8c1e4f2a-...",
"status": "sent",
"signerUrl": "https://ezysign.net/sign/abc123...",
"signedDocumentUrl": null,
"evidenceUrl": null,
"createdAt": "2026-04-27T10:00:00.000Z",
"sentAt": "2026-04-27T10:00:00.000Z",
"viewedAt": null,
"signedAt": null,
"expiresAt": "2026-05-04T10:00:00.000Z"
}Errori
400— payload non valido, PDF non valido, telefono mancante con SMS401— chiave API non valida413— payload > 25 MB
GET /dossiers
Elenca i dossier del tenant chiamante, ordinati per data di creazione (più recenti prima).
Query params
limit(integer, default 50, max 200) — numero di elementi da restituire.
Risposta 200
[
{
"id": "8c1e4f2a-...",
"status": "signed",
"signerFirstName": "Mario",
"signerLastName": "Rossi",
"signerEmail": "[email protected]",
"otpChannel": "email",
"documentName": "Contratto.pdf",
"createdAt": "2026-04-27T10:00:00.000Z",
"signedAt": "2026-04-27T10:05:12.000Z",
"expiresAt": "2026-05-04T10:00:00.000Z"
},
...
]GET /dossiers/:id
Restituisce il dossier indicato. Tipico uso: polling lato integratore quando non si è configurato un callbackUrl.
Risposta 200
Stesso schema di POST /dossiers.
Errori
404— dossier inesistente o non appartenente al tuo tenant
POST /dossiers/:id/resend
Reinvia un nuovo OTP al firmatario sullo stesso canale del dossier. Utile se il primo codice non è stato ricevuto.
Risposta 200
{ "ok": true }Errori
403— il dossier è in stato terminale (signed,expired,cancelled)404— dossier inesistente
DELETE /dossiers/:id
Annulla un dossier in corso. Il link firma viene invalidato. Operazione irreversibile.
Risposta 200
{ "ok": true }Errori
403— il dossier è già firmato404— dossier inesistente
GET /verify/:id (pubblico)
Endpoint pubblico (no API key) per verificare la validità di una firma da parte di terzi. Ritorna solo informazioni minime (nome firmatario mascherato, hash documento, marca temporale, link al PDF firmato e alla prova OpenTimestamps). Usato dalla pagina pubblica https://ezysign.net/verify/{id}.
Risposta 200 (firmato)
{
"id": "8c1e4f2a-...",
"status": "signed",
"brandName": "Acme Srl",
"signer": { "name": "M. Rossi", "email": "m***@example.com" },
"document": { "name": "Contratto.pdf", "hash": "sha256:f3a1...c0" },
"signedAt": "2026-04-27T10:05:12.000Z",
"expiresAt": "2026-05-04T10:00:00.000Z",
"files": {
"signed": "https://...presigned...",
"ots": "https://...presigned..."
}
}Stati del dossier
| Stato | Descrizione |
|---|---|
pending | Creato, OTP non ancora inviato (transitorio) |
sent | OTP inviato al firmatario, in attesa di apertura |
viewed | Il firmatario ha aperto il link |
signed | OTP verificato, PDF sigillato e marcato temporalmente |
expired | Link scaduto senza completamento |
cancelled | Dossier annullato dall'integratore |
failed | Errore irreversibile (es. invio OTP impossibile) |
URL firmati per i file
I campi signedDocumentUrl e evidenceUrl sono URL pre-firmati con validità 2 ore. Per uso prolungato, scarica il file e archivialo nel tuo sistema oppure interroga di nuovo l'endpoint per ottenere un URL fresco.