惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
B
Blog
Stack Overflow Blog
Stack Overflow Blog
量子位
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tailwind CSS Blog
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
Recent Announcements
Recent Announcements
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
D
DataBreaches.Net
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
罗磊的独立博客
L
LangChain Blog
V
Visual Studio Blog
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
API Dati Aziendali: Guida Tecnica per Sviluppatori che La...
Alessandro B · 2026-05-17 · via DEV Community

Se hai mai tentato di accedere programmaticamente ai dati del Registro Imprese italiano, sai già che l'esperienza è... migliorabile. Questa guida documenta il landscape reale delle API disponibili, i workaround che funzionano in produzione, e come strutturare un'integrazione robusta.

Il Panorama delle Fonti Dati Ufficiali

Infocamere / Telemaco

È il sistema ufficiale di accesso ai dati delle Camere di Commercio italiane. Tecnicamente capace, ma costruito pensando a notai, avvocati e commercialisti — non agli sviluppatori.

Cosa offre:

  • Visure camerali complete (dati anagrafici, soci, amministratori, capitale)
  • Bilanci in formato XBRL
  • Atti depositati
  • Procedure concorsuali

Accesso:

  • Prevede registrazione professionale o rivenditori accreditati
  • Pricing per query (non per piano mensile)
  • Documentazione tecnica disponibile ma datata
  • Non esiste un ambiente sandbox

Per uno sviluppatore che vuole prototipare velocemente, questa non è la strada.

OpenAPI del MISE (Ministero delle Imprese)

Il Ministero ha pubblicato alcune API per l'accesso a dati aggregati e statistici, ma non per query individuali su singole aziende.

API di terze parti (aggregatori)

La strada pratica per la maggior parte degli use case è lavorare con un aggregatore che ha già costruito il layer di normalizzazione sopra le fonti ufficiali. L'API S.C.A.L.A. score è una di queste, con un free tier per il prototyping.

Schema della Risposta API

{
  "company_name": "Rossi e Figli Srl",
  "vat_number": "IT08765432109",
  "fiscal_code": "08765432109",
  "status": "active",
  "legal_form": "Srl",
  "ateco_code": "43.21.01",
  "ateco_description": "Installazione di impianti elettrici",
  "registered_address": {
    "street": "Via Roma 42",
    "city": "Milano",
    "province": "MI",
    "region": "Lombardia",
    "zip": "20121"
  },
  "founding_date": "2008-03-15",
  "employees_range": "10-49",
  "revenue": 2340000,
  "last_filing_year": 2023,
  "score": 71,
  "risk_category": "low",
  "financial_summary": {
    "total_assets": 1850000,
    "total_liabilities": 920000,
    "equity": 930000,
    "net_result": 145000
  },
  "data_confidence": 0.87,
  "last_updated": "2026-04-12"
}

Enter fullscreen mode Exit fullscreen mode

Validazione della Partita IVA Prima della Query

Risparmia quota API e gestisci gli errori in modo più chiaro validando il formato della P.IVA prima di chiamare l'API.

function validateItalianVAT(vat) {
  // Normalizza: rimuovi IT prefix se presente, rimuovi spazi
  const normalized = vat.replace(/^IT/i, '').replace(/\s/g, '');

  // Deve essere esattamente 11 cifre
  if (!/^\d{11}$/.test(normalized)) {
    return { valid: false, error: 'Formato non valido: attese 11 cifre numeriche' };
  }

  // Checksum (algoritmo Luhn adattato per P.IVA italiana)
  let sum = 0;
  for (let i = 0; i < 10; i++) {
    const digit = parseInt(normalized[i]);
    if (i % 2 === 0) {
      sum += digit;
    } else {
      const doubled = digit * 2;
      sum += doubled > 9 ? doubled - 9 : doubled;
    }
  }
  const checkDigit = (10 - (sum % 10)) % 10;

  if (checkDigit !== parseInt(normalized[10])) {
    return { valid: false, error: 'Checksum non valido' };
  }

  return { valid: true, normalized: `IT${normalized}` };
}

Enter fullscreen mode Exit fullscreen mode

Pattern di Integrazione per Casi d'Uso Comuni

Autofill del Form di Registrazione

async function autofillFromVAT(vatNumber) {
  const validation = validateItalianVAT(vatNumber);
  if (!validation.valid) {
    return { error: validation.error };
  }

  try {
    const res = await fetch(
      `https://api.get-scala.com/score/company?vat=${validation.normalized}`,
      { headers: { Authorization: `Bearer ${process.env.SCALA_API_KEY}` } }
    );

    if (!res.ok) throw new Error(`API error: ${res.status}`);
    const data = await res.json();

    return {
      companyName: data.company_name,
      address: data.registered_address,
      ateco: data.ateco_code,
      employees: data.employees_range,
      status: data.status
    };
  } catch (err) {
    console.error('Company lookup failed:', err);
    return null; // Graceful degradation — lascia l'utente compilare manualmente
  }
}

Enter fullscreen mode Exit fullscreen mode

Screening di una Lista Fornitori

async function screenSuppliers(suppliers, riskThreshold = 40) {
  const BATCH_SIZE = 10;
  const results = [];

  for (let i = 0; i < suppliers.length; i += BATCH_SIZE) {
    const batch = suppliers.slice(i, i + BATCH_SIZE);

    const batchResults = await Promise.allSettled(
      batch.map(async (supplier) => {
        const res = await fetch(
          `https://api.get-scala.com/score/company?vat=${supplier.vat}`,
          { headers: { Authorization: `Bearer ${process.env.SCALA_API_KEY}` } }
        );
        const data = await res.json();
        return {
          ...supplier,
          score: data.score,
          riskCategory: data.risk_category,
          flagged: data.score < riskThreshold
        };
      })
    );

    results.push(...batchResults
      .filter(r => r.status === 'fulfilled')
      .map(r => r.value)
    );

    // Rispetta i rate limit — pausa tra batch
    if (i + BATCH_SIZE < suppliers.length) {
      await new Promise(resolve => setTimeout(resolve, 200));
    }
  }

  return {
    total: results.length,
    flagged: results.filter(r => r.flagged),
    clean: results.filter(r => !r.flagged)
  };
}

Enter fullscreen mode Exit fullscreen mode

Gestione della Qualità dei Dati

I dati del Registro Imprese hanno alcune caratteristiche specifiche da gestire:

Bilanci non ancora depositati: Le aziende hanno 6-7 mesi dalla chiusura dell'esercizio per depositare il bilancio. last_filing_year: 2022 in un'API call di maggio 2026 non significa necessariamente che l'azienda sia inattiva — potrebbe avere il 2023 in attesa di deposito.

function assessDataFreshness(lastFilingYear) {
  const currentYear = new Date().getFullYear();
  const lag = currentYear - lastFilingYear;

  if (lag <= 1) return 'fresh';
  if (lag === 2) return 'acceptable'; // probabile deposito in corso
  if (lag === 3) return 'stale';      // attenzione
  return 'very_stale';                // segnale negativo significativo
}

Enter fullscreen mode Exit fullscreen mode

Campo revenue nullo: Le microimprese possono depositare bilanci in forma abbreviata senza esporre il fatturato. Un campo revenue: null non è un errore — è un dato mancante per ragioni di legge.

Aziende in liquidazione: status: "in_liquidation" non significa insolvenza immediata, ma richiede attenzione. La liquidazione volontaria è normale alla fine della vita di un'azienda; quella forzata è un segnale negativo.

Caching e Rate Limiting

La maggior parte dei dati aziendali cambia lentamente. Un TTL di 24 ore è appropriato per la maggior parte degli use case:

const cache = new Map();

async function getCachedScore(vatNumber) {
  const cached = cache.get(vatNumber);
  if (cached && Date.now() - cached.timestamp < 24 * 60 * 60 * 1000) {
    return cached.data;
  }

  const data = await fetchFromAPI(vatNumber);
  cache.set(vatNumber, { data, timestamp: Date.now() });
  return data;
}

Enter fullscreen mode Exit fullscreen mode

In produzione, usa Redis con TTL nativo invece di una Map in memoria.


La documentazione completa dell'API S.C.A.L.A. score e il free tier sono disponibili su get-scala.com/score/. Registrazione su get-scala.com.