Collega Sanovia ai programmi che usi già. Con una chiave API un programma legge i dati che scegli tu; con un webhook riceve un avviso firmato quando succede qualcosa nel tuo studio.
Specifica OpenAPI (JSON) · Verifica della firma
Le chiavi API e i webhook sono inclusi nei piani Studio e Struttura.
Le chiavi sono del professionista o della struttura: in una struttura le crea l’amministratore. Segreteria e commercialista non possono crearle.
Se la scheda ti dice che le API non sono attive sul tuo account, per ora non puoi creare chiavi.
Ogni richiesta porta la chiave nell’intestazione Authorization. Una chiave mancante, sbagliata, revocata o scaduta riceve sempre la stessa risposta 401; una chiave senza l’ambito giusto riceve 403.
Authorization: Bearer snv_…
Gli elenchi rispondono con data e next_cursor: ripassa next_cursor come parametro cursor finché vale null. Gli importi sono in centesimi di euro.
Limiti: 120 richieste al minuto per chiave (tutte le rotte insieme) e 300 al minuto per indirizzo IP su ogni rotta. Oltre, la risposta è 429: riprova dopo un minuto.
Una chiave legge solo gli ambiti che le dai quando la crei. Questo elenco arriva dalla specifica OpenAPI, la stessa da cui Sanovia registra le sue rotte.
documents:readcounterparties:readpayments:readreceived:readexpenses:readpatients:readvisits:readavailability:readpatients:minimalbookings:writeGET /api/v1/public/me — La chiave stessa: i suoi ambiti e se è di un professionista o di una strutturaGET /api/v1/public/documents — Documenti fiscali emessi (documents:read)GET /api/v1/public/documents/{id} — Un documento fiscale emesso (documents:read)GET /api/v1/public/counterparties — Committenti (counterparties:read)GET /api/v1/public/payments — Incassi, rimborsi e storni (payments:read)GET /api/v1/public/received — Fatture ricevute dallo SdI (received:read)GET /api/v1/public/expenses — Spese registrate (expenses:read)GET /api/v1/public/visits — Appuntamenti: orari, stato, sede, tipo di visita e iniziali del paziente (visits:read)GET /api/v1/public/visits/{id} — Un appuntamento (visits:read)GET /api/v1/public/patients — Pazienti in forma ridotta: identificativo, iniziali e anno di nascita (patients:minimal)GET /api/v1/public/availability — Orari liberi di un professionista in una sede (availability:read)POST /api/v1/public/booking-requests — Ask Sanovia to e-mail a patient a booking confirmation link for a free slot — nothing is booked until the patient confirms (bookings:write)Parametri, risposte e schemi completi: specifica OpenAPI 3.1 (JSON)
Registri un indirizzo https pubblico sulla porta 443: Sanovia lo controlla quando lo salvi e prima di ogni invio, e non segue mai i reindirizzamenti. A ogni evento arriva una richiesta POST con un corpo JSON fatto solo di identificativi, numeri, date e importi: mai dati dei pazienti.
document.issueddocument.paidpayment.recordedreceived.arrivedvisit.createdvisit.rescheduledvisit.cancelledvisit.completedwebhook.testRispondi con un codice 2xx entro 10 secondi. Qualsiasi altra risposta, anche un 3xx, conta come errore: riproviamo più volte, con attese sempre più lunghe.
Ogni invio porta l’intestazione Sanovia-Signature nella forma t=<secondi unix>,v1=<firma>. La firma è l’HMAC-SHA256, in esadecimale, calcolato con il tuo segreto di firma (whsec_…) sulla stringa fatta da t, un punto e il corpo grezzo della richiesta.
Verifica sui byte grezzi del corpo, prima di leggere il JSON; confronta in tempo costante; scarta un t più vecchio di qualche minuto, così nessuno può rispedirti un invio vecchio.
Verifica in Node.js, da copiare:
// Node.js 18+, nessuna dipendenza
import { createHmac, timingSafeEqual } from "node:crypto";
const MAX_SKEW_S = 300; // finestra anti-replay: 5 minuti
/** true quando `header` (Sanovia-Signature) firma `rawBody` con `secret`. */
export function verifySignature(rawBody, header, secret, nowS = Math.floor(Date.now() / 1000)) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(String(header || ""));
if (!m) return false;
const t = Number(m[1]);
if (Math.abs(nowS - t) > MAX_SKEW_S) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`, "utf8").digest();
const given = Buffer.from(m[2], "hex");
return given.length === expected.length && timingSafeEqual(given, expected);
}
// Nel tuo server: leggi il corpo GREZZO (stringa), poi
// verifySignature(raw, req.headers["sanovia-signature"], process.env.SANOVIA_WEBHOOK_SECRET)
// false → rispondi 401; true → rispondi 2xx subito e lavora dopo.
Passaggi, non schermate. I nomi dei moduli sono quelli che questi strumenti usano oggi e possono cambiare: se non li trovi, cerca il modulo equivalente.
Crea l’account gratis · Prezzi · Sanovia — Gestionale cloud per studi e professionisti della salute