Appearance
Chiudere un mese di fatturazione
Dal file che arriva dal distributore al CSV che alimenta la fatturazione ci sono cinque passi. Si possono fare tutti dal pannello, e tutti dalle API: qui ci sono entrambe le strade, e soprattutto come si capisce a che punto si è fra un passo e l'altro.
Il passo che si dimentica più facilmente è il terzo.
In breve
| # | passo | API | quando |
|---|---|---|---|
| 1 | Caricare gli archivi | POST /v1/metering/uploads | quando arrivano |
| 2 | Elaborarli | automatico alle 02:00, o POST /v1/metering/uploads/{id}/elabora | dopo il caricamento |
| 3 | Ricalcolare gli aggregati del mese | POST /v1/metering/reprocess con solo_aggregati | prima di fatturare, sempre |
| 4 | Verificare che il mese sia chiudibile | GET /v1/metering/chiusura?mese= | prima di fatturare |
| 5 | Esportare | GET /v1/metering/export/tracciato?mese= | a verifica superata |
1. Caricare gli archivi
Si apre una sessione dichiarando i file, si caricano agli indirizzi ricevuti, si chiude.
http
POST /v1/metering/uploads
X-Tenant-Id: TENANT_NAME
{ "file": ["2026-09-29_2026-09-30.zip", "2026-10-01_2026-10-03.zip"],
"dimensioni": { "2026-09-29_2026-09-30.zip": 2062548992 } }La risposta porta un upload_id e, per ogni file, o un url unico oppure — sopra i 100 MB — un elenco di parti da caricare una per una. Gli archivi del SII stanno quasi sempre fra 2 e 3,5 GB, quindi si va quasi sempre a parti.
Caricati i file si chiude la sessione:
http
POST /v1/metering/uploads/{upload_id}/completaCome si capisce se un caricamento è andato a buon fine
Questa è la domanda che il diario da solo non risponde, perché registra la sessione e non i singoli file.
http
GET /v1/metering/uploadsRestituisce, per ogni lotto, una riga per file con uno di quattro stati:
| stato | significa |
|---|---|
completato | il file è su S3, con i byte che occupa |
in_corso | sta ancora salendo: byte, parti, percentuale se si conosce l'atteso |
interrotto | fermo da più di cinque minuti senza una parte nuova: va ricaricato |
mai_iniziato | dichiarato all'apertura ma mai partito |
fermo_da_minuti conta dall'ultima parte arrivata, non dall'apertura del caricamento: serve a distinguere un trasferimento lento da uno morto.
Lo stesso si vede nel pannello, in Misure → Caricamenti.
Lo stesso file può comparire in due lotti
Se un trasferimento si pianta e lo si riapre, il file sale in un lotto nuovo e quello vecchio resta mezzo salito. Dopo sei ore la pulizia chiude il trasferimento morto e lo annota nel diario — ma guarda prima se quel file è arrivato per altra via:
- se non è arrivato, l'evento è
fallito: «non è mai stato completato … va ricaricato»; - se è arrivato con un altro caricamento, l'evento è
saltato: «il file però è arrivato intero con un altro caricamento … non serve ricaricarlo».
Vale la pena saperlo perché il diario e l'elenco dei caricamenti possono sembrare in contraddizione sullo stesso nome di file: il diario racconta un trasferimento, l'elenco riconcilia da S3 e guarda il file. Fino al 2026-10-14 l'avviso diceva «va ricaricato» senza fare quel controllo.
2. Elaborare
L'elaborazione parte da sola alle 02:00 (ora di Roma) e prende tutti i file nuovi. Se non si vuole aspettare:
http
POST /v1/metering/uploads/{upload_id}/elaboraUn archivio sopra i 2 GB viene prima scompattato e poi letto, in un'unica corsa: non serve fare nulla di diverso.
Per seguirla:
http
GET /v1/metering/batches/{upload_id} # quanti file sono stati letti
GET /v1/metering/stato?mese=2026-09 # lo stato della catena, contato sul meseIl mese qui non è un dettaglio
Senza mese, /stato conta su tutti i mesi presenti: su tutto l'archivio i POD-mese che quadrano sono il 34,7%, su settembre 2026 da solo il 15,6%. Chiudendo un mese si guarda quel mese — il totale risponde a un'altra domanda. Vedi su quale periodo contano quei numeri.
3. Ricalcolare gli aggregati del mese
È il passo obbligatorio, ed è quello che si dimentica.
http
POST /v1/metering/reprocess
{ "da": "2026-09", "a": "2026-09", "solo_aggregati": true }Pochi minuti. Non rilegge nessun file: ricalcola il mensile dal giornaliero già a terra.
Perché serve sempre
Gli aggregati mensili vengono costruiti durante la corsa che trasforma i file. Se nella stessa corsa arrivano più archivi — ed è la norma, se ne caricano quattro o cinque alla volta — i primi aggregati nascono su un mese ancora incompleto e restano così.
Non è un'ipotesi. Il 13 ottobre 2026, dopo aver elaborato gli archivi che completavano settembre:
| prima del ricalcolo | dopo | |
|---|---|---|
| MWh del mese | 9.061 | 29.324 |
| POD fatturabili | 1.990 | 25.214 |
| giorni coperti, media per POD | 7,4 | 22,1 |
Tre volte il consumo. Il sistema non stava sbagliando in silenzio — teneva quei POD fuori dai fatturabili — ma nessuna schermata diceva che bastavano pochi minuti per sistemarli.
4. Verificare che il mese sia chiudibile
http
GET /v1/metering/chiusura?mese=2026-09Due cose nella risposta contano più delle altre.
coerenza confronta il totale degli aggregati con la somma del giornaliero:
json
"coerenza": {
"mwh_mensile": 29323.939,
"mwh_giornaliero": 27522.315,
"rapporto": 0.94,
"aggregato_da_ricalcolare": false
}Se aggregato_da_ricalcolare è true, lo scarto supera il 15 % e il passo 3 non è stato fatto, o è stato fatto prima che arrivassero altri file. La risposta dice anche come rimediare.
pronto è true solo se tutti i POD-mese sono in stato quadrato e la coerenza regge. Un mese il cui aggregato non concorda con il giornaliero non è pronto nemmeno se i conteggi tornano: si starebbe fatturando un numero costruito su meno dati di quelli disponibili.
Gli stati intermedi, e cosa farci
Ogni POD-mese ha uno stato. Solo quadrato è fatturabile.
| stato | cosa è successo | cosa fare |
|---|---|---|
quadrato | il consumo viene dalla curva, oppure registri e curva coincidono entro tolleranza | niente: è fatturabile |
periodo_incompleto | calcolato dai registri, ma la finestra di lettura è più corta del mese | servono le letture mancanti: caricare gli archivi del periodo |
periodo_esteso | la finestra è più lunga: tira dentro giorni del mese precedente | va corretto a mano: fattura di più del dovuto |
curva_incompleta | non quadra e la curva copre pochi giorni | caricare gli archivi mancanti, poi rifare il passo 3 |
da_verificare | registri e curva divergono oltre tolleranza | serve un controllo: le due fonti non raccontano la stessa cosa |
periodo_incompleto e periodo_esteso sono errori opposti e vanno distinti. Il primo fattura meno del dovuto, il secondo di più. Il secondo è meno intuitivo ma più grave davanti a un cliente.
La finestra giusta è dall'ultimo giorno del mese precedente all'ultimo giorno del mese: è la convenzione con cui fattura il distributore, verificata su bollette reali.
Su settembre 2026, dopo il ricalcolo:
periodo_incompleto 89.351 ← mancano letture
da_verificare 46.533 ← registri e curva divergono
quadrato 25.214 ← fatturabili
curva_incompleta 566
periodo_esteso 30 ← da correggere a manoLa regola: certo e stimato
Dal primo giorno del mese successivo si fattura, ci siano o no tutti i consumi. I giorni misurati sono certi; quelli che mancano si stimano. Le due cose restano separate fino alla bolletta.
L'esportazione estesa porta sei colonne che applicano questa regola:
| colonna | cosa contiene |
|---|---|
giorni_certi | giorni con misura vera nel mese |
giorni_stimati_calc | i restanti |
kwh_certi | consumo dei giorni misurati |
kwh_stimati | stima dei giorni mancanti |
kwh_mese_regola | il totale da fatturare |
quota_stimata_pct | quanta parte del totale è stimata |
base_certezza | in parole, su cosa poggia la riga |
I tre casi
Il totale è già certo quando i registri aprono l'ultimo giorno del mese precedente e chiudono l'ultimo del mese: è quanto ha contato il contatore. Non si stima niente, anche se la curva ha buchi — il contatore accumula lo stesso. Vale anche quando è il distributore a dichiarare i totali.
A settembre 2026 sono 70.965 POD su 161.694, il 44 %.
Parzialmente misurato: i giorni con misura sono certi, i mancanti si stimano con la media giornaliera di quel POD in quel mese. Non una media di categoria, non un profilo standard: la media del POD stesso, che ne rispetta la taglia e la stagione.
Nessun giorno misurato: non si stima dal POD stesso, perché non c'è niente da cui partire. La riga esce con totale vuoto e base_certezza lo dichiara. A settembre sono 9.497 righe.
Quanto è affidabile la stima
Verificata sul dato vero, non assunta. Su 387 POD che avevano il totale certo dai contatori e solo 10–25 giorni di curva, la stima per media giornaliera sbaglia in media il 4,3 %, e sta entro il 15 % nel 94,3 % dei casi.
Su settembre 2026 nel complesso:
kWh certi 27.522 MWh
kWh stimati 10.512 MWh
totale 38.795 MWh ← 27,1 % stimatoPerché le colonne sono in più e non al posto delle altre
delivery_net_total resta quello che era: il totale calcolato dal metodo scelto dal sistema. kwh_mese_regola applica questa regola. Tenerle entrambe permette di confrontarle su fatture vere prima di spostare la fatturazione sulla seconda — e sull'esempio reale differiscono del 21 %, che è esattamente la settimana mancante.
5. Esportare
http
GET /v1/metering/export/tracciato?mese=2026-09
→ { "job": "…", "stato": "in_coda" }
GET /v1/metering/export/tracciato?job=…
→ { "stato": "pronto", "scarica": "/v1/metering/export/scarica/…", "righe": 168222 }
GET /v1/metering/export/scarica/{job}
→ { "url": "https://…", "vale_secondi": 300 }Il collegamento si firma al momento della richiesta e vale cinque minuti. I file restano disponibili sessanta giorni, poi si cancellano da soli; dal pannello si possono eliminare prima.
Nel pannello: Esportazioni.
Il giro completo, in sequenza
bash
T="X-Tenant-Id: TENANT_NAME"
A="Authorization: Bearer $TOKEN"
# 3 — ricalcolo degli aggregati del mese
curl -X POST https://api.base9.app/v1/metering/reprocess -H "$T" -H "$A" \
-H 'Content-Type: application/json' \
-d '{"da":"2026-09","a":"2026-09","solo_aggregati":true}'
# 4 — il mese è chiudibile?
curl "https://api.base9.app/v1/metering/chiusura?mese=2026-09" -H "$T" -H "$A" \
| jq '{pronto, fatturabili, coerenza}'
# 5 — esportazione
JOB=$(curl -s "https://api.base9.app/v1/metering/export/tracciato?mese=2026-09" \
-H "$T" -H "$A" | jq -r .data.job)
curl -s "https://api.base9.app/v1/metering/export/tracciato?job=$JOB" -H "$T" -H "$A" | jq .dataErrori che si fanno, in ordine di frequenza
Saltare il passo 3. È il più comune e il più silenzioso: i numeri ci sono, sono solo più bassi del vero. Dalla versione del 13 ottobre 2026 GET /chiusura lo dice da solo, nel blocco coerenza.
Fidarsi del diario per sapere se un caricamento è finito. Il diario registra la sessione; i file li dice GET /v1/metering/uploads.
Leggere fatturabili senza guardare coerenza. Si può avere un numero alto di POD quadrati su un aggregato costruito a metà.
Fatturare righe in periodo_esteso. Sono poche — trenta su centosessantamila a settembre — ma ognuna fattura più del dovuto.

