API KEY PRO
Guida completa all'uso delle chiavi API
Documentazione ufficiale per l'integrazione programmatica con i dati premium del Portale Energia. Questa API è pubblica e accessibile dall'esterno, ma richiede una API key generata dal profilo utente. In questa guida trovi: come creare la chiave, come autenticarti, quale endpoint usare e come interpretare la risposta.
1. Prerequisiti
- Account registrato e attivo con piano Pro, Forecast o Admin.
- Sessione autenticata: accedi a Profilo utente per visualizzare la sezione Gestione API Keys.
- Connessione HTTPS obbligatoria (questa API richiede TLS per motivi di sicurezza).
1.1 Differenze per piano
Ogni tipo di abbonamento ha accesso alle API con limiti e permessi specifici:
| Piano | Accesso API | Rate limit consigliato | Note |
|---|---|---|---|
| Free | No | — | No sessione API Key; accesso solo via interfaccia utente. |
| Pro | Sì | Fino a 500 req/ora, 5000/giorno | Chiavi illimitate, tenere sotto monitoraggio i log in api_logs. |
| Forecast | Sì | Stessi limiti Pro, consigliato batch ogni 5 min | Ideale per carichi predittivi e forecast. Supporta più chiavi per ambiente. |
| Admin | Sì | Stessi limiti Pro con priorità di supporto | Accesso completo: puoi attivare/disattivare chiavi al volo e verificare i log. |
2. Generazione della chiave
Nella card Gestione API Keys puoi generare una nuova chiave:
- Inserisci un nome descrittivo (es. "CRM interno") e premi "Genera Chiave".
- La chiave viene mostrata una sola volta: copiala e salvala in modo sicuro.
- La lunghezza è di 64 caratteri esadecimali e viene registrata in tabella
api_keys.
La chiave può essere revocata in qualsiasi momento tramite lo stesso pannello oppure inviando una richiesta POST a /api-pro-backend.php con action=revoke_api_key e il key_id.
3. Autenticazione
Ogni richiesta al backend deve includere la chiave in uno dei seguenti modi:
X-API-KEYnell'header della richiesta (metodo consigliato).api_keycome parametro GET (utilizzare solo in ambienti controllati).
Il sistema ApiAuth confronta la chiave con la tabella api_keys, verifica che sia attiva, che l'account associato sia attivo e che la data di scadenza non sia superata. In caso contrario, riceverai un codice HTTP 401 o 403 e il messaggio corrispondente.
Base URL e versione
Tutti gli endpoint PRO sono esposti sotto /api/v2.
L'URL completo si ottiene aggiungendo il dominio del Portale Energia.
https://<tuo-dominio>/api/v2/<endpoint>
4. Endpoint disponibili
Gli endpoint PRO attualmente disponibili con autenticazione tramite API key sono elencati di seguito. Ogni endpoint ha parametri specifici e restituisce dati in formato JSON standardizzato.
| Endpoint | Metodo | Descrizione | Auth |
|---|---|---|---|
/api/v2/pun-hourly-pro.php |
GET | Prezzi PUN orari (dataset premium) | API key obbligatoria |
/api/v2/cte-offerte-pro.php |
GET | Condizioni Tecnico Economiche offerte luce e gas | API key obbligatoria |
/api/v2/psv-giornaliero-pro.php |
GET | Prezzi PSV giornalieri (gas naturale - Punto di Scambio Virtuale) | API key obbligatoria |
5. Endpoint principale
GET /api/v2/pun-hourly-pro.php
Restituisce i prezzi PUN orari (tutti i dati premium). Ogni chiamata legge i dati da prezzi_pun_orari filtrando per data e zona.
Autenticazione: obbligatoria tramite X-API-KEY (header) oppure api_key in query.
| Parametro | Descrizione | Default |
|---|---|---|
date | Data da interrogare (formato YYYY-MM-DD). | oggi |
zone | Zona geografica (es. NORD, CNOR, PUN per il prezzo nazionale). | PUN |
La risposta include array di 24 elementi (uno per ogni ora) con il prezzo e la fascia oraria.
GET https://portaleenergia.it/api/v2/pun-hourly-pro.php?date=2025-01-27&zone=PUN
Headers:
X-API-KEY:
{
"success": true,
"data": {
"date": "2025-01-27",
"zone": "PUN",
"prices": [
{
"data": "2025-01-27",
"ora": "00:00",
"prezzo_eur_mwh": 127.45,
"fascia_oraria": "F1",
"zona": "PUN"
},
{
"data": "2025-01-27",
"ora": "01:00",
"prezzo_eur_mwh": 125.10,
"fascia_oraria": "F1",
"zona": "PUN"
}
// ... altre ore ...
]
}
}
GET /api/v2/psv-giornaliero-pro.php
Restituisce i prezzi giornalieri del gas naturale al Punto di Scambio Virtuale (PSV). Include prezzo, minimo e massimo per ogni giorno.
Autenticazione: obbligatoria tramite X-API-KEY (header) oppure api_key in query.
| Parametro | Descrizione | Default |
|---|---|---|
start | Data inizio periodo (formato YYYY-MM-DD). | 90 giorni fa |
end | Data fine periodo (formato YYYY-MM-DD). | oggi |
limit | Numero massimo di record (max 5000). | 1000 |
GET https://portaleenergia.it/api/v2/psv-giornaliero-pro.php?start=2025-01-01&end=2025-03-17
Headers:
X-API-KEY: <chiave_pro>
{
"success": true,
"data": [
{
"data": "2025-01-15",
"prezzo": 30.166,
"minimo": 30.000,
"massimo": 30.250
}
],
"count": 76,
"period": { "start": "2025-01-01", "end": "2025-03-17" },
"data_availability": { "first_date": "2022-...", "last_date": "2025-03-17" },
"stats": { "prezzo": { "min": 28.5, "max": 35.2, "avg": 31.8 } },
"unit": "€/MWh"
}
6. Endpoint CTE Offerte
GET /api/v2/cte-offerte-pro.php
Restituisce l'elenco completo delle offerte luce e gas con le relative Condizioni Tecnico Economiche (CTE). Include sia offerte a prezzo fisso che variabile, con dettagli su quote fisse, spread, componenti tariffarie e fornitori.
Autenticazione: obbligatoria tramite X-API-KEY (header) oppure api_key in query.
| Parametro | Descrizione | Default |
|---|---|---|
tipo_cliente | Filtra per tipo cliente (es. domestico, business). | Nessun filtro |
tipo_prezzo | Filtra per tipo prezzo: Fisso o Variabile. | Nessun filtro |
fornitore | Filtra per nome fornitore o P.IVA (ricerca parziale, case-insensitive). | Nessun filtro |
data_inizio_min | Data inizio validità minima (formato YYYY-MM-DD). | Nessun filtro |
data_inizio_max | Data inizio validità massima (formato YYYY-MM-DD). | Nessun filtro |
data_fine_min | Data fine validità minima (formato YYYY-MM-DD). | Nessun filtro |
data_fine_max | Data fine validità massima (formato YYYY-MM-DD). | Nessun filtro |
attive | Se true, restituisce solo offerte attualmente valide. | false |
sort_by | Campo per ordinamento: data_caricamento, nome_fornitore, nome_offerta, tipo_prezzo, quota_fissa, quota_variabile_spread, data_inizio, data_fine. | data_caricamento |
sort_order | Direzione ordinamento: ASC (crescente) o DESC (decrescente). | DESC |
limit | Numero massimo di record da restituire (max 1000). | 100 |
offset | Offset per paginazione (salta i primi N record). | 0 |
La risposta include un array di offerte con tutte le informazioni tecniche ed economiche, oltre a metadati di paginazione per gestire dataset di grandi dimensioni.
GET https://portaleenergia.it/api/v2/cte-offerte-pro.php?tipo_prezzo=Variabile&limit=50
Headers:
X-API-KEY: <chiave_pro>
{
"success": true,
"data": [
{
"codice_offerta": "OFF-2025-001",
"piva_fornitore": "01234567890",
"nome_fornitore": "Enel Energia S.p.A.",
"nome_offerta": "E-Light Web",
"tipo_prezzo": "Variabile",
"quota_fissa": null,
"quota_variabile_spread": 0.015,
"data_inizio": "2025-01-01",
"data_fine": "2025-12-31",
"tipo_cliente": "domestico",
"data_caricamento": "2025-01-15 10:30:00",
"componenti": [
{
"macroarea": "04",
"descrizione": "Spread su PUN",
"prezzo": "0.015",
"unita": "03"
}
]
},
{
"codice_offerta": "OFF-2025-002",
"piva_fornitore": "09876543210",
"nome_fornitore": "A2A Energia S.p.A.",
"nome_offerta": "Click Fisso",
"tipo_prezzo": "Fisso",
"quota_fissa": 0.128,
"quota_variabile_spread": null,
"data_inizio": "2025-01-01",
"data_fine": "2025-06-30",
"tipo_cliente": "domestico",
"data_caricamento": "2025-01-14 15:20:00",
"componenti": [
{
"macroarea": "01",
"descrizione": "Spesa materia energia",
"prezzo": "0.128",
"unita": "01"
}
]
}
],
"pagination": {
"total": 245,
"count": 2,
"limit": 50,
"offset": 0,
"has_more": true
},
"filters_applied": {
"tipo_cliente": null,
"tipo_prezzo": "Variabile",
"fornitore": null,
"data_inizio_min": null,
"data_inizio_max": null,
"data_fine_min": null,
"data_fine_max": null,
"solo_attive": false
},
"sorting": {
"sort_by": "data_caricamento",
"sort_order": "DESC"
},
"description": "Condizioni Tecnico Economiche delle offerte luce e gas"
}
Casi d'uso comuni
1. Ricerca offerte di un fornitore specifico:
GET /api/v2/cte-offerte-pro.php?fornitore=Enel
2. Solo offerte a prezzo fisso per utenti business:
GET /api/v2/cte-offerte-pro.php?tipo_prezzo=Fisso&tipo_cliente=business
3. Offerte attualmente valide ordinate per prezzo:
GET /api/v2/cte-offerte-pro.php?attive=true&sort_by=quota_fissa&sort_order=ASC
4. Offerte attive a gennaio 2025:
GET /api/v2/cte-offerte-pro.php?data_inizio_max=2025-01-31&data_fine_min=2025-01-01
5. Offerte variabili ordinate per spread (dal più basso):
GET /api/v2/cte-offerte-pro.php?tipo_prezzo=Variabile&sort_by=quota_variabile_spread&sort_order=ASC
6. Paginazione per dataset grandi (seconda pagina, 100 record per pagina):
GET /api/v2/cte-offerte-pro.php?limit=100&offset=100
7. Offerte di Enel attive, ordinate per nome offerta:
GET /api/v2/cte-offerte-pro.php?fornitore=Enel&attive=true&sort_by=nome_offerta&sort_order=ASC
7. Esempi di integrazione
Esempi pronti per collegarsi dall'esterno con la tua API key.
Endpoint PUN Orari
cURL
curl -H "X-API-KEY: <la_tua_chiave>" \ "https://portaleenergia.it/api/v2/pun-hourly-pro.php?date=2025-01-27&zone=PUN"
JavaScript (fetch)
fetch("https://portaleenergia.it/api/v2/pun-hourly-pro.php?date=2025-01-27&zone=PUN", {
headers: { "X-API-KEY": "<la_tua_chiave>" }
})
.then(r => r.json())
.then(console.log)
.catch(console.error);
Python (requests)
import requests
url = "https://portaleenergia.it/api/v2/pun-hourly-pro.php"
params = {"date": "2025-01-27", "zone": "PUN"}
headers = {"X-API-KEY": "<la_tua_chiave>"}
response = requests.get(url, params=params, headers=headers, timeout=20)
print(response.status_code)
print(response.json())
Endpoint CTE Offerte
cURL - Offerte variabili ordinate per spread
curl -H "X-API-KEY: <la_tua_chiave>" \ "https://portaleenergia.it/api/v2/cte-offerte-pro.php?tipo_prezzo=Variabile&sort_by=quota_variabile_spread&sort_order=ASC&limit=50"
cURL - Solo offerte attualmente valide
curl -H "X-API-KEY: <la_tua_chiave>" \ "https://portaleenergia.it/api/v2/cte-offerte-pro.php?attive=true&sort_by=nome_fornitore&sort_order=ASC"
JavaScript (fetch) - Con filtri avanzati
// Esempio: offerte Enel attive ordinate per prezzo
const params = new URLSearchParams({
fornitore: "Enel",
attive: "true",
sort_by: "quota_fissa",
sort_order: "ASC",
limit: 20
});
fetch(`https://portaleenergia.it/api/v2/cte-offerte-pro.php?${params}`, {
headers: { "X-API-KEY": "<la_tua_chiave>" }
})
.then(r => r.json())
.then(data => {
console.log(`Trovate ${data.pagination.total} offerte`);
console.log(`Cache hit: ${r.headers.get('X-Cache-Hit')}`);
data.data.forEach(offerta => {
console.log(`${offerta.nome_fornitore}: ${offerta.nome_offerta}`);
console.log(` P.IVA: ${offerta.piva_fornitore}`);
console.log(` Prezzo: ${offerta.quota_fissa || offerta.quota_variabile_spread} €/kWh`);
});
})
.catch(console.error);
Python (requests) - Ricerca con filtri data
import requests
from datetime import datetime, timedelta
url = "https://portaleenergia.it/api/v2/cte-offerte-pro.php"
# Esempio: offerte attive nel prossimo mese
oggi = datetime.now().date()
tra_un_mese = oggi + timedelta(days=30)
params = {
"tipo_prezzo": "Fisso",
"tipo_cliente": "domestico",
"data_inizio_max": str(tra_un_mese), # Iniziate entro un mese
"data_fine_min": str(oggi), # Ancora valide oggi
"sort_by": "quota_fissa",
"sort_order": "ASC",
"limit": 100
}
headers = {"X-API-KEY": "<la_tua_chiave>"}
response = requests.get(url, params=params, headers=headers, timeout=20)
data = response.json()
if data["success"]:
print(f"Totale offerte trovate: {data['pagination']['total']}")
print(f"Cache hit: {response.headers.get('X-Cache-Hit', 'N/A')}")
print(f"Ordinamento: {data['sorting']['sort_by']} {data['sorting']['sort_order']}")
print("\nOfferte:")
for offerta in data["data"]:
fornitore = offerta['nome_fornitore']
nome = offerta['nome_offerta']
prezzo = offerta['quota_fissa']
validita = f"{offerta['data_inizio']} → {offerta['data_fine']}"
print(f"\n {fornitore}: {nome}")
print(f" Prezzo fisso: {prezzo} €/kWh")
print(f" Validità: {validita}")
print(f" P.IVA: {offerta['piva_fornitore']}")
else:
print(f"Errore: {data.get('message', 'Errore sconosciuto')}")
8. Sistema di Cache
Per migliorare le performance e ridurre il carico sul database, l'endpoint CTE Offerte implementa un sistema di caching intelligente.
Come funziona
- Cache automatica: Le risposte vengono automaticamente memorizzate in cache per 15 minuti (configurabile).
- Chiave univoca: Ogni combinazione di parametri genera una chiave di cache unica.
- Verifica cache: L'header
X-Cache-Hitindica se la risposta proviene dalla cache (true) o dal database (false). - Invalidazione automatica: La cache scade dopo il TTL (Time To Live) configurato.
Vantaggi
- ✅ Performance migliorate: Risposte fino a 10x più veloci per dati in cache
- ✅ Riduzione carico database: Meno query ripetute al database
- ✅ Risparmio rate limit: Richieste in cache non consumano quote aggiuntive di processing
- ✅ Trasparente: Funziona automaticamente senza configurazione client-side
Controllo della cache
Puoi verificare se una risposta proviene dalla cache controllando l'header HTTP:
// JavaScript
fetch(url, { headers: { "X-API-KEY": "..." } })
.then(response => {
const cacheHit = response.headers.get('X-Cache-Hit');
console.log(`Cache hit: ${cacheHit}`); // "true" o "false"
});
# Python
response = requests.get(url, headers=headers)
cache_hit = response.headers.get('X-Cache-Hit')
print(f"Dati dalla cache: {cache_hit == 'true'}")
Best practice con la cache
- Per dati in tempo reale, considera che potrebbero avere fino a 15 minuti di delay
- Per query frequenti con gli stessi parametri, la cache migliora notevolmente le performance
- Implementa il caching anche lato client per ridurre ulteriormente le chiamate API
9. Quote e rate limit
I limiti globali sono programmati in www/api/v2/config.php:
- 50 richieste/minuto (MAX_REQUESTS_PER_MINUTE)
- 500 richieste/ora (MAX_REQUESTS_PER_HOUR)
- 5000 richieste/giorno (MAX_REQUESTS_PER_DAY)
- 6 richieste concorrenti per utente (MAX_CONCURRENT_REQUESTS)
Quando entri in uno di questi limiti ricevi HTTP 429 con risposta JSON che include retry_after (default 3600s). Implementa backoff esponenziale o sleep prima di ritentare.
10. Risposte di errore
401– Chiave mancante o invalidata. Controlla header/query e stato attivo.403– Account PRO scaduto o disattivato.429– Limite superato. Rispetta il timeout indicato inretry_after.500– Errore interno. Log nel backend e prova più tardi.
11. Best practice
- Usa sempre HTTPS e cancelli le chiavi dai log client non necessari.
- Envialo tramite header
X-API-KEYe non in chiaro nella query. - Implementa caching lato client o reverse-proxy per ridurre il numero di chiamate.
- Gestisci la rotazione automatica creando nuove chiavi e revocando quelle vecchie.
- Monitora le richieste con i log generati da
api_logse registra il timestamp.
12. Revoca e monitoraggio
Tutte le operazioni vengono tracciate in api_logs (endpoint, indirizzo IP, data/ora). Se una chiave viene compromessa:
- Vai su Profilo → Gestione API Keys.
- Clicca su Revoca accanto alla chiave compromessa.
- Genera una chiave nuova e aggiorna i client esterni.
13. Risorse utili
- config.php: contiene quota, rate limit e configurazioni di sicurezza.
- ApiAuth.php: logica di validazione, incrementi contatori e risposta JSON.
- pun-hourly-pro.php: endpoint PRO per prezzi PUN orari.
- psv-giornaliero-pro.php: endpoint PRO per prezzi PSV giornalieri (gas naturale).
- cte-offerte-pro.php: endpoint PRO per Condizioni Tecnico Economiche offerte luce e gas.
- PIATTAFORMA_DATI_README: panoramica generale dei dataset.
14. FAQ rapida
Posso riutilizzare la stessa chiave su più server?
Sì, ma monitora l'utilizzo e rispetta i limiti: una singola chiave conta come un utente.
Come faccio a sapere se ho superato il limite?
Ricevi HTTP 429 con retry_after; su richiesta permanente consultare api_logs.