# Optlyx Partner API — Riferimento completo > Documento unico, completo e auto-contenuto, pensato per essere ingerito da un LLM o > da uno sviluppatore che integra l'API. Versione 0.1 (bozza) — 2026-06-20. ## 1. Cos'è Optlyx Partner API è un **motore di conversione**: invii il PDF di una fattura estera (es. Anthropic, OpenAI, AWS, Stripe Irlanda) e ricevi l'**XML FatturaPA dell'autofattura italiana** corrispondente, con il codice TD corretto. Il motore fa OCR, estrazione AI, riconoscimento del documento estero, validazione (VIES, valuta, importi) e generazione XML. ## 2. Confine di responsabilità (importante) - **Optlyx (questa API)**: OCR → AI → riconoscimento → validazione → generazione XML FatturaPA. - **Recivu / cliente finale**: firma dell'XML (CAdES `.p7m`), invio a SDI, gestione di ricevute/notifiche SDI, conservazione a norma. Optlyx è un **puro processore dati (OCR/AI)**: non tocca il canale SDI. Il titolare fiscale e il soggetto che trasmette è sempre l'azienda cliente finale. L'XML restituito è **non firmato**. La conservazione potrà arrivare come add-on Optlyx (non in questa versione). ## 3. Base URL e ambienti ``` https://europe-west1-playground-optlyx.cloudfunctions.net/partnerApi/v1 ``` - Sandbox: API key con prefisso `pk_test_…` - Produzione: API key con prefisso `pk_live_…` L'ambiente è determinato dal prefisso della key, non dall'URL. (Prima del go-live verrà fornito un alias di dominio, es. `https://api.optlyx.com/v1`; i path restano identici.) URL alternativo equivalente: `…/clientHubStartPayment/partner/v1`. ## 4. Autenticazione Header obbligatorio su ogni richiesta: ``` Authorization: Bearer pk_live_xxxxxxxxxxxxxxxxxxxxxxxx ``` La key è "super-partner": agisce per conto di più aziende. L'azienda target va indicata nel campo `studioId` nel body di ogni chiamata. Se la key non è abilitata per quello `studioId`, la risposta è `403 TENANT_FORBIDDEN`. ## 5. Idempotenza Header opzionale su tutte le `POST`: ``` Idempotency-Key: ``` Ripetere la stessa richiesta con la stessa key restituisce la risposta originale senza rilavorare il documento. Una richiesta con la stessa key ancora in corso ⇒ `409 IDEMPOTENCY_CONFLICT`. ## 6. Rate limit 60 richieste/minuto per API key. Oltre soglia: `429 RATE_LIMITED`, con `details.retry_after_ms` (ms da attendere). ## 7. Soglia di confidenza e revisione Se l'OCR ha confidenza `< 0.95` (configurabile via `options.requireConfidence`) oppure emergono `blockingIssues`, la risposta ha `status: "needs_review"` e **non** viene prodotto un XML autoritativo. In quel caso, mostra i campi all'operatore per conferma e usa poi `POST /v1/autofatture` con i dati corretti. ## 8. Codici TD | TD | Quando | Note | |----|--------|------| | TD17 | Integrazione/autofattura per servizi da fornitore estero | Obbligatoria, reverse charge | | TD18 | Acquisto intracomunitario di beni | UE | | TD19 | Acquisto beni ex art.17 c.2 (fornitore estero, beni in IT) | incl. San Marino | | TD01 | Fattura ordinaria (companion volontario) | Contabilizzazione automatica | Il TD viene suggerito da `recognize`/`process`; può essere forzato passandolo in `:autofatture`. ## 9. Endpoint ### 9.1 POST /v1/documents:recognize — DISPONIBILE Anteprima: PDF → dati estratti + confidence + TD suggerito. Non genera XML. Request body (JSON): ```json { "studioId": "azienda-123", "fileBase64": "", "mimeType": "application/pdf", "fileName": "anthropic.pdf" } ``` Response 200: ```json { "status": "ok", "confidence": 0.97, "suggestedTd": "TD17", "tdReason": "servizi da fornitore extra-UE", "extracted": { "supplierName": "Anthropic PBC", "country": "US", "currency": "USD", "invoiceNumber": "INV-2026-42", "invoiceDate": "2026-05-31", "subtotal": 100 }, "isCreditNote": false, "isTaxRefund": false, "validationWarnings": [], "blockingIssues": [], "vies": { "valid": true } } ``` `status` è `"needs_review"` quando `confidence < 0.95` o `blockingIssues` non è vuoto. ### 9.2 POST /v1/autofatture:process — DISPONIBILE Pipeline completa: PDF → XML FatturaPA pronto all'invio. Se non passi `cessionario`, vengono usati i dati dell'azienda (tenant) come cessionario. Request body (JSON): ```json { "studioId": "azienda-123", "fileBase64": "", "mimeType": "application/pdf", "fileName": "anthropic.pdf", "cessionario": { "denominazione": "Alfa S.r.l.", "partitaIva": "09876543210", "sede": { "nazione": "IT" } }, "options": { "generateTd01": true, "requireConfidence": 0.95 } } ``` Response 200 (ok): ```json { "status": "ok", "autofatturaId": "AF/2026/00001", "td": "TD17", "confidence": 0.97, "xml": "", "companionTd01Xml": "", "importoTotaleCents": 12200, "extracted": { "supplierName": "Anthropic PBC" } } ``` Response 200 (needs_review): come `recognize`, senza `xml`. L'`xml` è **non firmato**: firma e invio a SDI sono a carico del partner. ### 9.3 POST /v1/autofatture — DISPONIBILE Genera l'XML da dati strutturati (es. estratti da `recognize` e corretti dall'operatore), senza ripassare dall'OCR. Request body (JSON): ```json { "studioId": "azienda-123", "fatturaData": { "tipo": "TD17", "generateTd01": true, "fornitoreEstero": { "denominazione": "Anthropic PBC", "paese": "US", "idFiscale": "US123456" }, "cessionario": { "denominazione": "Alfa S.r.l.", "partitaIva": "09876543210", "sede": { "nazione": "IT" } }, "fatturaOriginale": { "numero": "INV-2026-42", "data": "2026-05-31" }, "linee": [ { "descrizione": "API usage", "quantita": 1, "prezzoUnitario": 100, "aliquotaIva": 22, "natura": "N6.2" } ], "valuta": "EUR", "data": "2026-05-31" } } ``` Response 200: come `:process` (con `xml`, `companionTd01Xml`, `importoTotaleCents`). ### 9.4 Gestione e webhook (DISPONIBILI) `GET /v1/autofatture` (lista), `GET /v1/autofatture/{id}` (con XML), `GET /v1/autofatture/{id}/courtesy-pdf` (PDF non fiscale base64), `POST /v1/webhooks` (registra URL → ricevi `secret`; eventi `autofattura.created` firmati HMAC-SHA256 header `X-Optlyx-Signature`). Pianificato: `POST /v1/autofatture/{id}:corrections` (learning). - `GET /v1/autofatture?studioId=…&page=…` — lista paginata. - `GET /v1/autofatture/{id}?studioId=…` — recupera autofattura + XML. - `GET /v1/autofatture/{id}/courtesy-pdf?studioId=…` — PDF di cortesia (non fiscale). - `POST /v1/autofatture/{id}:corrections` — invia correzioni per il learning. - Webhook firmati per flussi asincroni. ## 10. Modello di errore Tutte le risposte di errore hanno la forma: ```json { "error": { "code": "TENANT_FORBIDDEN", "message": "…", "details": { "studioId": "studio-9" } } } ``` | HTTP | code | Significato | |------|------|-------------| | 400 | BAD_REQUEST | Payload mancante o malformato | | 401 | UNAUTHORIZED | API key assente / non valida / revocata | | 403 | TENANT_FORBIDDEN | La key non è abilitata per quello studioId | | 404 | NOT_FOUND | Risorsa/route inesistente | | 409 | IDEMPOTENCY_CONFLICT | Stessa Idempotency-Key ancora in elaborazione | | 422 | OCR_LOW_CONFIDENCE | Scansione illeggibile / sotto soglia | | 422 | VIES_FAILED | P.IVA UE non validabile su VIES | | 422 | INVALID_TD | Codice TD non coerente / mancante | | 429 | RATE_LIMITED | Troppe richieste (vedi details.retry_after_ms) | | 500 | INTERNAL | Errore interno | Regola per agenti/LLM: il campo `error.code` è stabile — gestirlo programmaticamente; non parsare `error.message`. ## 11. Esempio end-to-end (curl) ```bash curl -X POST \ 'https://europe-west1-playground-optlyx.cloudfunctions.net/partnerApi/v1/autofatture:process' \ -H 'Authorization: Bearer pk_test_xxx' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: 7f3c2b1a-...' \ -d '{ "studioId": "azienda-123", "fileBase64": "'"$(base64 -i anthropic.pdf)"'", "mimeType": "application/pdf", "fileName": "anthropic.pdf" }' ``` Ricevi l'XML, lo firmi e lo invii a SDI dal tuo canale. ## 12. Flusso consigliato per un'integrazione 1. (Opzionale) `POST /v1/documents:recognize` per anteprima e validazione UI. 2. Se `status: "needs_review"`, far correggere l'operatore. 3. `POST /v1/autofatture:process` (o `POST /v1/autofatture` con i dati corretti) per l'XML. 4. Firmare l'XML e inviarlo a SDI dal proprio canale. 5. Gestire le ricevute/notifiche SDI e la conservazione lato partner.