Last active
April 1, 2026 08:44
-
-
Save aborruso/8f4693916761b88cd0bd3c70559602a5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="it"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>CAP Professional Open – Poste Italiane</title> | |
| <style> | |
| * { margin:0; padding:0; box-sizing:border-box; } | |
| body { font-family: Arial, sans-serif; color: #333; background:#fff; } | |
| /* TOP BAR */ | |
| .topbar { background:#f5f5f5; display:flex; justify-content:space-between; align-items:center; padding:6px 16px; font-size:11px; color:#555; border-bottom:1px solid #ddd; flex-wrap:wrap; gap:4px; } | |
| .topbar a { color:#555; text-decoration:none; margin-left:10px; } | |
| .topbar-left { display:flex; flex-wrap:wrap; gap:8px; } | |
| .topbar-left span { cursor:pointer; } | |
| .topbar-left span.active { color:#003399; font-weight:bold; border-bottom:2px solid #003399; } | |
| /* NAVBAR */ | |
| .navbar { background:#003399; display:flex; align-items:center; padding:0 16px; height:52px; gap:16px; overflow-x:auto; } | |
| .navbar::-webkit-scrollbar { display:none; } | |
| .logo { background:#f5e100; padding:5px 10px; font-size:18px; font-weight:bold; color:#003399; white-space:nowrap; flex-shrink:0; } | |
| .nav-item { color:#fff; font-size:11px; font-weight:bold; text-transform:uppercase; cursor:pointer; padding:16px 2px; white-space:nowrap; flex-shrink:0; } | |
| .nav-right { margin-left:auto; color:#fff; font-size:16px; flex-shrink:0; } | |
| /* SUBTABS */ | |
| .subtabs { display:flex; overflow-x:auto; padding:0 8px; border-bottom:2px solid #e0e0e0; background:#fff; } | |
| .subtabs::-webkit-scrollbar { display:none; } | |
| .subtab { padding:12px 10px; font-size:11px; cursor:pointer; color:#555; border-bottom:3px solid transparent; margin-bottom:-2px; white-space:nowrap; flex-shrink:0; } | |
| .subtab.active { color:#003399; font-weight:bold; border-bottom:3px solid #003399; } | |
| /* HERO */ | |
| .hero { padding:24px 16px; display:flex; flex-direction:column; gap:20px; } | |
| @media(min-width:700px){ | |
| .hero { flex-direction:row; align-items:flex-start; gap:32px; padding:40px 24px; } | |
| .hero-right { width:380px; flex-shrink:0; } | |
| } | |
| .hero-left h1 { font-size:30px; font-weight:300; color:#222; margin-bottom:12px; line-height:1.2; } | |
| @media(min-width:700px){ .hero-left h1 { font-size:38px; } } | |
| .hero-left p { font-size:14px; color:#555; line-height:1.5; } | |
| .hero-right { background:#fff; border:1px solid #e0e0e0; border-radius:4px; padding:20px; box-shadow:0 2px 8px rgba(0,0,0,.07); } | |
| .hero-right ul { list-style:none; } | |
| .hero-right ul li { font-size:13px; color:#333; margin-bottom:12px; padding-left:22px; position:relative; line-height:1.5; } | |
| .hero-right ul li::before { content:"✓"; color:#003399; font-weight:bold; position:absolute; left:0; } | |
| .hero-right ul li.new-item::before { color:#e30613; } | |
| .hero-right ul li a { color:#003399; } | |
| .badge-open { display:inline-block; background:#e30613; color:#fff; font-size:10px; font-weight:bold; padding:2px 6px; border-radius:3px; margin-left:6px; vertical-align:middle; } | |
| /* SECTION TABS */ | |
| .section-tabs { display:flex; overflow-x:auto; gap:16px; padding:16px 16px 0; border-top:1px solid #e0e0e0; } | |
| .section-tabs::-webkit-scrollbar { display:none; } | |
| .section-tab { font-size:11px; font-weight:bold; color:#003399; text-transform:uppercase; cursor:pointer; padding-bottom:8px; white-space:nowrap; letter-spacing:.5px; } | |
| /* HERO IMG */ | |
| .hero-img { width:100%; height:160px; background:linear-gradient(135deg,#1a1a2e,#0f3460); display:flex; align-items:center; justify-content:center; overflow:hidden; } | |
| @media(min-width:700px){ .hero-img { height:240px; } } | |
| .hero-img-text { color:rgba(255,255,255,.2); font-family:monospace; font-size:10px; line-height:2; text-align:left; } | |
| @media(min-width:700px){ .hero-img-text { font-size:12px; } } | |
| /* LICENSE BANNER */ | |
| .license-banner { background:#f0f4ff; border-left:4px solid #003399; padding:14px 16px; margin:16px; border-radius:0 6px 6px 0; font-size:13px; line-height:1.6; } | |
| .license-banner a { color:#003399; font-weight:bold; } | |
| .license-banner code { background:#dde8ff; padding:1px 4px; border-radius:3px; font-size:11px; word-break:break-all; } | |
| /* API SECTION */ | |
| .api-section { padding:24px 16px; } | |
| @media(min-width:700px){ .api-section { padding:40px 24px; max-width:1100px; margin:0 auto; } } | |
| .api-section h2 { font-size:22px; font-weight:300; color:#222; margin-bottom:6px; } | |
| .api-section .subtitle { font-size:13px; color:#666; margin-bottom:24px; line-height:1.5; } | |
| .endpoints { display:flex; flex-direction:column; gap:12px; } | |
| .endpoint-card { border:1px solid #e0e0e0; border-radius:6px; overflow:hidden; } | |
| .endpoint-header { display:flex; align-items:center; gap:10px; padding:12px 14px; background:#f8f8f8; cursor:pointer; flex-wrap:wrap; } | |
| .method { font-size:10px; font-weight:bold; padding:3px 7px; border-radius:3px; font-family:monospace; flex-shrink:0; } | |
| .method.get { background:#e8f5e9; color:#2e7d32; } | |
| .method.post { background:#e3f2fd; color:#1565c0; } | |
| .endpoint-path { font-family:monospace; font-size:12px; color:#333; font-weight:bold; } | |
| .endpoint-desc { font-size:12px; color:#666; } | |
| .chevron { margin-left:auto; color:#999; flex-shrink:0; } | |
| .endpoint-body { padding:16px; background:#fff; border-top:1px solid #eee; display:none; } | |
| .endpoint-body.open { display:block; } | |
| .endpoint-body p { font-size:13px; color:#444; margin-bottom:12px; line-height:1.6; } | |
| .param-table { width:100%; border-collapse:collapse; font-size:11px; margin-top:8px; overflow-x:auto; display:block; } | |
| .param-table th { text-align:left; background:#f0f0f0; padding:6px 8px; font-weight:bold; white-space:nowrap; } | |
| .param-table td { padding:6px 8px; border-top:1px solid #eee; vertical-align:top; } | |
| .param-table td code { background:#f5f5f5; padding:1px 4px; border-radius:3px; } | |
| .resp-example { background:#1e1e1e; color:#d4d4d4; border-radius:4px; padding:12px; font-family:monospace; font-size:10px; line-height:1.8; margin-top:10px; overflow-x:auto; white-space:pre; } | |
| .key { color:#9cdcfe; } | |
| .str { color:#ce9178; } | |
| .num { color:#b5cea8; } | |
| /* MEME OVERLAY */ | |
| #meme-overlay { | |
| display:none; position:fixed; inset:0; background:rgba(0,0,0,.88); | |
| z-index:9999; align-items:center; justify-content:center; | |
| padding:16px; | |
| } | |
| #meme-overlay.show { display:flex; } | |
| .meme-box { | |
| background:#fff; border-radius:16px; padding:28px 24px; | |
| max-width:480px; width:100%; text-align:center; | |
| animation:popIn .4s cubic-bezier(.34,1.56,.64,1); | |
| } | |
| @keyframes popIn { from{transform:scale(.5);opacity:0} to{transform:scale(1);opacity:1} } | |
| .meme-emoji { font-size:72px; display:block; margin-bottom:10px; } | |
| .meme-box h2 { font-size:26px; color:#e30613; margin-bottom:10px; } | |
| .meme-box p { font-size:14px; color:#444; line-height:1.7; margin-bottom:16px; } | |
| .meme-caption { font-size:12px; color:#999; font-style:italic; } | |
| .meme-btn { background:#003399; color:#fff; border:none; padding:12px 28px; border-radius:8px; font-size:15px; cursor:pointer; margin-top:16px; width:100%; } | |
| footer { background:#003399; color:#fff; text-align:center; padding:20px 16px; font-size:11px; margin-top:32px; line-height:1.8; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="topbar"> | |
| <div class="topbar-left"> | |
| <span>PRIVATI</span> | |
| <span class="active">BUSINESS ▾</span> | |
| <span>PREMIUM</span> | |
| <span>POSTE ITALIANE</span> | |
| <span>TGPOSTE</span> | |
| </div> | |
| <div> | |
| <a href="#">❓ ASSISTENZA</a> | |
| <a href="#">👤 AREA PERSONALE</a> | |
| </div> | |
| </div> | |
| <nav class="navbar"> | |
| <div class="logo">Poste<em style="font-style:normal;color:#555">italiane</em></div> | |
| <span class="nav-item">SERVIZI FINANZIARI</span> | |
| <span class="nav-item">CORRIERE ESPRESSO E PACCHI</span> | |
| <span class="nav-item">SERVIZI POSTALI</span> | |
| <span class="nav-item">SERVIZI ASSICURATIVI</span> | |
| <span class="nav-item">SOLUZIONI DIGITALI</span> | |
| <span class="nav-item">SERVIZI ONLINE</span> | |
| <div class="nav-right">🔍</div> | |
| </nav> | |
| <div class="subtabs"> | |
| <div class="subtab active">CAP Professional</div> | |
| <div class="subtab">CAP Street File</div> | |
| <div class="subtab">CAP Zone</div> | |
| <div class="subtab">CAP Delivery Points</div> | |
| <div class="subtab">Points of Interest</div> | |
| <div class="subtab" style="color:#e30613;font-weight:bold;">CAP Open API ✨</div> | |
| </div> | |
| <div class="hero"> | |
| <div class="hero-left"> | |
| <h1>CAP Professional <span class="badge-open">OPEN</span></h1> | |
| <p>Dove trovare i CAP di tutti i comuni e località italiani — ora anche via API aperta, machine to machine, con dati in licenza libera.</p> | |
| </div> | |
| <div class="hero-right"> | |
| <ul> | |
| <li>I CAP di tutte le località italiane ed i dati toponomastici delle strade delle 41 città divise in più zone CAP</li> | |
| <li>Contiene oltre 90.000 strade</li> | |
| <li>Contiene le denominazioni, standard e abbreviate, di comuni, frazioni e strade</li> | |
| <li class="new-item">Accesso via <a href="#api-start" id="api-link"><strong>API REST</strong></a>, machine to machine, senza registrazione</li> | |
| <li class="new-item">Dati in licenza <a href="https://creativecommons.org/licenses/by/4.0/deed.it" target="_blank"><strong>CC BY 4.0</strong></a> — riutilizzabili con attribuzione</li> | |
| <li class="new-item">Aggiornamento mensile, formato JSON e CSV</li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div class="section-tabs"> | |
| <span class="section-tab">DESCRIZIONE</span> | |
| <span class="section-tab">SCOPRI DI PIÙ</span> | |
| <span class="section-tab">LINK UTILI</span> | |
| <span class="section-tab">ALTRI PRODOTTI</span> | |
| <span class="section-tab" style="color:#e30613;">▶ ENDPOINT API</span> | |
| </div> | |
| <div class="hero-img"> | |
| <div class="hero-img-text">GET /api/cap/lookup?q=Palermo → 200 OK GET /api/cap/street?city=Roma → 200 OK GET /api/cap/comuni?regione=sicilia → 200 OK POST /api/cap/batch → 200 OK GET /api/cap/frazioni?comune=Milano → 200 OK</div> | |
| </div> | |
| <div class="license-banner" id="api-start"> | |
| 📄 Dati rilasciati sotto <a href="https://creativecommons.org/licenses/by/4.0/deed.it" target="_blank">CC BY 4.0</a>. Obbligo di citare "Poste Italiane S.p.A." come fonte.<br> | |
| Base URL: <code>https://api.cap.poste.it/v1</code> | |
| </div> | |
| <div class="api-section"> | |
| <h2>Endpoint disponibili</h2> | |
| <p class="subtitle">Tocca un endpoint per vedere dettagli, parametri ed esempio di risposta.</p> | |
| <div class="endpoints"> | |
| <div class="endpoint-card"> | |
| <div class="endpoint-header" onclick="toggle(this)"> | |
| <span class="method get">GET</span> | |
| <span class="endpoint-path">/cap/lookup</span> | |
| <span class="endpoint-desc">Ricerca CAP per comune</span> | |
| <span class="chevron">▼</span> | |
| </div> | |
| <div class="endpoint-body"> | |
| <p>Restituisce i CAP associati a un comune o frazione. Supporta ricerca fuzzy sul nome.</p> | |
| <table class="param-table"><tr><th>Param</th><th>Tipo</th><th>Req</th><th>Descrizione</th></tr> | |
| <tr><td><code>q</code></td><td>string</td><td>✅</td><td>Nome comune o località</td></tr> | |
| <tr><td><code>regione</code></td><td>string</td><td>❌</td><td>Filtra per regione</td></tr> | |
| <tr><td><code>limit</code></td><td>int</td><td>❌</td><td>Max risultati (default 10)</td></tr> | |
| </table> | |
| <div class="resp-example"><span class="key">"results"</span>: [ | |
| { <span class="key">"cap"</span>: <span class="str">"90121"</span>, <span class="key">"comune"</span>: <span class="str">"Palermo"</span>, <span class="key">"zona"</span>: <span class="str">"Centro"</span> }, | |
| { <span class="key">"cap"</span>: <span class="str">"90128"</span>, <span class="key">"comune"</span>: <span class="str">"Palermo"</span>, <span class="key">"zona"</span>: <span class="str">"Uditore"</span> } | |
| ]</div> | |
| </div> | |
| </div> | |
| <div class="endpoint-card"> | |
| <div class="endpoint-header" onclick="toggle(this)"> | |
| <span class="method get">GET</span> | |
| <span class="endpoint-path">/cap/street</span> | |
| <span class="endpoint-desc">Toponomastica per via e città</span> | |
| <span class="chevron">▼</span> | |
| </div> | |
| <div class="endpoint-body"> | |
| <p>Denominazione standard, abbreviata, CAP di zona e municipio per una strada specifica.</p> | |
| <table class="param-table"><tr><th>Param</th><th>Tipo</th><th>Req</th><th>Descrizione</th></tr> | |
| <tr><td><code>city</code></td><td>string</td><td>✅</td><td>Nome del comune</td></tr> | |
| <tr><td><code>name</code></td><td>string</td><td>✅</td><td>Nome strada (anche parziale)</td></tr> | |
| </table> | |
| <div class="resp-example">{ <span class="key">"via_standard"</span>: <span class="str">"Via Nazionale"</span>, | |
| <span class="key">"via_abbreviata"</span>: <span class="str">"V. Nazionale"</span>, | |
| <span class="key">"cap"</span>: <span class="str">"00184"</span>, <span class="key">"municipio"</span>: <span class="str">"I"</span> }</div> | |
| </div> | |
| </div> | |
| <div class="endpoint-card"> | |
| <div class="endpoint-header" onclick="toggle(this)"> | |
| <span class="method get">GET</span> | |
| <span class="endpoint-path">/cap/comuni</span> | |
| <span class="endpoint-desc">Elenco comuni con CAP</span> | |
| <span class="chevron">▼</span> | |
| </div> | |
| <div class="endpoint-body"> | |
| <p>Tutti i comuni italiani con CAP principale. Filtrabile per regione o provincia, esportabile in CSV.</p> | |
| <table class="param-table"><tr><th>Param</th><th>Tipo</th><th>Req</th><th>Descrizione</th></tr> | |
| <tr><td><code>regione</code></td><td>string</td><td>❌</td><td>Nome regione</td></tr> | |
| <tr><td><code>provincia</code></td><td>string</td><td>❌</td><td>Sigla (es. <code>PA</code>)</td></tr> | |
| <tr><td><code>format</code></td><td>string</td><td>❌</td><td><code>json</code> o <code>csv</code></td></tr> | |
| </table> | |
| <div class="resp-example">[ | |
| { <span class="key">"istat"</span>: <span class="str">"082053"</span>, <span class="key">"comune"</span>: <span class="str">"Palermo"</span>, <span class="key">"cap"</span>: <span class="str">"90121"</span> }, | |
| { <span class="key">"istat"</span>: <span class="str">"082067"</span>, <span class="key">"comune"</span>: <span class="str">"Termini Imerese"</span>, <span class="key">"cap"</span>: <span class="str">"90018"</span> } | |
| ]</div> | |
| </div> | |
| </div> | |
| <div class="endpoint-card"> | |
| <div class="endpoint-header" onclick="toggle(this)"> | |
| <span class="method post">POST</span> | |
| <span class="endpoint-path">/cap/batch</span> | |
| <span class="endpoint-desc">Risoluzione massiva indirizzi</span> | |
| <span class="chevron">▼</span> | |
| </div> | |
| <div class="endpoint-body"> | |
| <p>Fino a 500 indirizzi in una chiamata. Ideale per normalizzazione di database CRM o mailing list.</p> | |
| <table class="param-table"><tr><th>Campo</th><th>Tipo</th><th>Descrizione</th></tr> | |
| <tr><td><code>addresses</code></td><td>array</td><td>Lista di <code>{ via, comune }</code></td></tr> | |
| </table> | |
| <div class="resp-example">{ <span class="key">"results"</span>: [ | |
| { <span class="key">"input"</span>: <span class="str">"Via Roma 1, Milano"</span>, | |
| <span class="key">"cap"</span>: <span class="str">"20122"</span>, <span class="key">"confidence"</span>: <span class="num">0.97</span> } | |
| ]}</div> | |
| </div> | |
| </div> | |
| <div class="endpoint-card"> | |
| <div class="endpoint-header" onclick="toggle(this)"> | |
| <span class="method get">GET</span> | |
| <span class="endpoint-path">/cap/frazioni</span> | |
| <span class="endpoint-desc">Frazioni e località di un comune</span> | |
| <span class="chevron">▼</span> | |
| </div> | |
| <div class="endpoint-body"> | |
| <p>Frazioni e località abitate con CAP e denominazioni abbreviate standardizzate.</p> | |
| <table class="param-table"><tr><th>Param</th><th>Tipo</th><th>Req</th><th>Descrizione</th></tr> | |
| <tr><td><code>comune</code></td><td>string</td><td>✅</td><td>Nome del comune</td></tr> | |
| </table> | |
| <div class="resp-example">[ | |
| { <span class="key">"localita"</span>: <span class="str">"Sesto San Giovanni"</span>, <span class="key">"abbrev"</span>: <span class="str">"Sesto S.G."</span>, <span class="key">"cap"</span>: <span class="str">"20099"</span> } | |
| ]</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- MEME OVERLAY --> | |
| <div id="meme-overlay"> | |
| <div class="meme-box"> | |
| <span class="meme-emoji">🤡</span> | |
| <h2>PESCE D'APRILE!</h2> | |
| <p>Caro sviluppatore,<br> | |
| questa API <strong>non esiste</strong>.<br> | |
| I CAP di Poste Italiane sono ancora <em>blindati</em>, a pagamento, e con licenza proprietaria.<br><br> | |
| <strong>La vera notizia è che dovrebbero essere aperti. 📢</strong></p> | |
| <p class="meme-caption">"Ma la CC BY 4.0 era così bella…" — tutti gli sviluppatori italiani, ogni anno</p> | |
| <button class="meme-btn" onclick="document.getElementById('meme-overlay').classList.remove('show')">😭 Lo so, lo so</button> | |
| </div> | |
| </div> | |
| <footer> | |
| © 2026 Poste Italiane S.p.A. – Sede Legale: Piazza Matteotti, 3 – 00144 Roma<br> | |
| <span style="opacity:.5">Pagina dimostrativa. I dati CAP reali di Poste Italiane NON sono open data.</span> | |
| </footer> | |
| <script> | |
| // Smooth scroll per il link API REST | |
| document.getElementById('api-link').addEventListener('click', function(e){ | |
| e.preventDefault(); | |
| document.getElementById('api-start').scrollIntoView({behavior:'smooth'}); | |
| }); | |
| function toggle(header) { | |
| const body = header.nextElementSibling; | |
| body.classList.toggle('open'); | |
| header.querySelector('.chevron').textContent = body.classList.contains('open') ? '▲' : '▼'; | |
| } | |
| // Trigger meme: scatta solo quando l'ultima endpoint card entra nel viewport | |
| let memeShown = false; | |
| const cards = document.querySelectorAll('.endpoint-card'); | |
| const lastCard = cards[cards.length - 1]; | |
| const observer = new IntersectionObserver((entries) => { | |
| entries.forEach(entry => { | |
| if (entry.isIntersecting && !memeShown) { | |
| memeShown = true; // blocca subito per evitare doppi trigger | |
| setTimeout(() => { | |
| document.getElementById('meme-overlay').classList.add('show'); | |
| }, 2000); | |
| } | |
| }); | |
| }, { threshold: 0.5 }); | |
| observer.observe(lastCard); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment