Factum Parse API
⚡️ Zero-Friction Quickstart
Section titled “⚡️ Zero-Friction Quickstart”Invia un payload documentale (XML, UBL, FacturaPA, PDF, testo grezzo) e ottieni un DocumentEnvelope v2 strutturato e validato contro schema formale:
curl -X POST https://api.factum.pyragogy.org/v2/parse \ -H "Authorization: Bearer YOUR_ZYLA_API_KEY" \ -H "Accept: application/json" \ -F "file=@fattura_elettronica.xml" \ -F "deterministic_only=true"import requests
resp = requests.post( "https://api.factum.pyragogy.org/v2/parse", headers={"Authorization": "Bearer YOUR_ZYLA_API_KEY"}, files={"file": open("fattura_elettronica.xml", "rb")}, data={"deterministic_only": "true"},)print(resp.json())const resp = await fetch("https://api.factum.pyragogy.org/v2/parse", { method: "POST", headers: { Authorization: "Bearer YOUR_ZYLA_API_KEY" }, body: new FormData(),});// append "file" as Blob, "deterministic_only" as "true"Risultato — envelope strutturato validato da Pydantic v2:
{ "job_id": "a1b2c3d4e5", "status": "completed", "schema_version": "2.0", "document_type": "invoice", "meta": { "cost_eur": 0.0, "confidence": 0.99, "provider": "fast-path", "prompt_version": "" }, "payload": { "kind": "invoice", "dati_trasmissione": { "IdTrasmittente": { "IdPaese": "IT", "IdCodice": "01234567890" } }, "cedente_prestatore": { "Denominazione": "Mario Rossi S.r.l." }, "corpi": [ { "DatiGenerali": {}, "DatiBeniServizi": {} } ] }}XML deterministico Nessun token LLM consumato. 41ms roundtrip misurati.
Benchmark Matrix
Section titled “Benchmark Matrix”Tempi di risposta misurati su produzione (Hetzner eu-central, Coolify). Test suite: 284 passati / 6 skipped, coverage 83.4%.
| Scenario | Endpoint | Percorso | Latency (p50) | Costo | Note |
|---|---|---|---|---|---|
| FatturaPA XML | POST /v2/parse |
Deterministico (fast-path) | 41 ms | €0 | Senza LLM. Zero emissioni. |
| PDF fattura | POST /v2/parse |
Ibrido (Rizzo + LLM) | ~520 ms | €0.002 | Pseudonimizzato in-RAM prima dell’LLM |
| Testo libero (F24) | POST /v2/parse |
LLM + restore | ~890 ms | €0.005 | Restore locale dopo risposta LLM |
| Upload XML + poll | POST /v1/uploads → GET /v1/uploads/{id} |
Async (due chiamate) | ~120 ms | €0 | Upload job, polling callback |
Repository measurements, non SLA live. 41ms e 83.4% sono storici — esegui benchmark e build prima di fare affidamento sui valori correnti. Costi LLM basati su prezzi OpenRouter al modello standard.
Routing Decision Tree
Section titled “Routing Decision Tree” ┌──────────────────────────────┐ │ POST /v2/parse │ │ Auth: X-API-Key │ │ Fail-closed: 401 se assente │ └──────────────┬───────────────┘ │ ┌───────────┴───────────┐ │ Content-Type / │ │ file extension │ └───────┬───────────────┘ │ ┌─────────────────────┼─────────────────────┐ │ │ │ ┌─────┴──────┐ ┌───────┴───────┐ ┌──────┴──────┐ │ │ │ │ │ │ │ XML │ │ PDF │ │ TEXT │ │ FacturaPA/ │ │ (application/ │ │ (plain/ │ │ UBL │ │ pdf) │ │ markdown) │ │ │ │ │ │ │ └──────┬─────┘ └───────┬───────┘ └──────┬──────┘ │ │ │ ┌──────┴──────┐ ┌──────┴───────┐ ┌──────┴──────┐ │ │ │ │ │ │ │ Fast Parser │ │ Rizzo PII │ │ Rizzo PII │ │ (XSLT + │ │ /analyze │ │ /analyze │ │ validation)│ │ (22 categ.) │ │ (22 categ.) │ │ │ │ │ │ │ └──────┬──────┘ └──────┬───────┘ └──────┬──────┘ │ │ │ │ ┌────────┴────────┐ │ │ │ Pseudonymized │ │ │ │ text → LLM │ │ │ │ (OpenRouter) │ │ │ └────────┬────────┘ │ │ │ │ └──────────┬─────────┴──────────┬──────────┘ │ │ ┌──────┴──────┐ ┌──────┴──────┐ │ restore() │ │ restore() │ │ mapping │ │ mapping │ │ in RAM │ │ in RAM │ └──────┬──────┘ └──────┬──────┘ │ │ └────────┬───────────┘ │ ┌────────┴────────┐ │ DocumentEnvelope│ │ v2 │ │ Union discr. │ │ Pydantic valid. │ │ HTTP 200 │ └─────────────────┘Fail-closed Se Rizzo sidecar non è raggiungibile → HTTP 503. Il sistema non degrada mai a testo scoperto.
Architettura: Asymmetric Routing
Section titled “Architettura: Asymmetric Routing”┌──────────┐ ┌──────────┐ ┌──────────────────────────────────────────────┐│ │ │ │ │ EU BOUNDARY ││ Client │────►│ Auth │────►│ ┌────────┐ ┌──────────┐ ┌──────────────┐ ││ │ │ Gateway │ │ │ Router │ │ Fast │ │ Document │ ││ │ │ fail- │ │ │ (by │──►│ Parser │─►│ Envelope v2 │ ││ │ │ closed │ │ │ type) │ │ (XSLT) │ │ (Pydantic) │ │└──────────┘ └──────────┘ │ └────────┘ ├──────────┤ └──────────────┘ │ │ │ Rizzo │ │ │ │ /analyze │──► LLM (esterno) │ │ │ (22 cat) │ (solo testo │ │ │ restore()│ pseudonimizzato) │ │ └──────────┘ │ └──────────────────────────────────────────────┘- 41ms deterministici: FatturaPA XML, UBL — zero LLM, zero token, zero emissioni
- Asimmetria di routing: Il router sceglie il percorso in base a
content-type— non c’è un unico modello che fa tutto - ZDR strutturale: I file esistono solo in RAM volatile durante la transazione.
DROPdopo la risposta HTTP - Confine EU: Il sidecar Rizzo (CPU, RAM, nessuna chiamata esterna) genera il mapping PII locale. L’LLM non vede mai plaintext
Surface API
Section titled “Surface API”| Metodo | Route | Auth | Scopo |
|---|---|---|---|
GET |
/health |
— | Liveness probe |
GET |
/status |
— | Stato operativo pubblico |
POST |
/v2/parse |
X-API-Key |
Parsing sincrono (XML/PDF/text) |
POST |
/v1/uploads |
X-API-Key |
Ingest asincrono (file pesanti) |
GET |
/v1/uploads/{job_id} |
X-API-Key |
Polling risultato |
Tutti gli errori seguono RFC 7807 (application/problem+json). Rate limiting per tier: Free 60 req/min, Basic 100 req/min, Pro 1000 req/min.
Niente JSON piatto Ogni risposta è un DocumentEnvelope v2 validato da Pydantic con union discriminata sul campo kind.
Inizia in 3 minuti
Section titled “Inizia in 3 minuti”- Ottieni una chiave su Zyla API Hub
- Copia il comando dalla scheda cURL qui sopra
- Invia il tuo primo documento — ricevi un envelope strutturato in < 1 secondo
Reality-first: 41ms e 83.4% coverage sono repository measurements, non un live SLA. €0 si applica solo al fast-path deterministico. “EU boundary” è la proprietà architetturale del sidecar Rizzo — l’infrastruttura di produzione è Hetzner eu-central (Nürnberg) gestita da Coolify. Verifica sempre in produzione prima di fare affidamento su qualsiasi claim.