REST API
Tutte le operazioni REST con parametri, corpo della richiesta, risposte ed errori, generate dalla specifica OpenAPI.
Tutte le operazioni pubblicate dell'API fiscale, generate dalla specifica OpenAPI (https://app.billyssw.it/documentazione/openapi.json).
I percorsi sono relativi al base URL dell'ambiente: in staging https://pem-staging.billyssw.it (vedi Base URL, https://app.billyssw.it/documentazione/ambienti). Ogni richiesta porta Accept: application/json.
Autenticazione
Il bearer è un access token del realm Keycloak billy, ottenuto con Authorization Code + PKCE e il consenso dell'esercente. Per i client partner vale 10 minuti: alla scadenza (401 con error: token_expired) se ne chiede uno nuovo al token endpoint del realm con il refresh_token. Ogni endpoint dichiara lo scope richiesto ai client partner; quelli riservati all'app e al pannello Billy rispondono 403 a un client partner.
- Autorizzazione:
https://auth.billyssw.it/realms/billy/protocol/openid-connect/auth - Token e rinnovo:
https://auth.billyssw.it/realms/billy/protocol/openid-connect/token
| Scope | Descrizione |
|---|---|
fiscale:read |
Leggere lo stato dei PEM, consultare documenti commerciali e report |
fiscale:manage |
Emettere documenti commerciali, annulli, resi e documenti gestionali, eseguire la chiusura giornaliera e di emergenza, gestire il PEM (cambio stato, dismissione, cambio sede, periodi di inattività) |
catalogo:read |
Leggere reparti e codici ATECO |
catalogo:write |
Creare, modificare ed eliminare reparti, categorie e codici ATECO |
offline_access |
Refresh token di lunga durata (sessione offline) |
Indice delle operazioni
- Account - Registrazione
- POST /api/auth/register: Richiesta di registrazione esercente
- Anagrafica - PEM
- GET /api/pem: Lista PEM
- GET /api/pem/{serial_number}: Mostra PEM
- POST /api/pem/{serial_number}/cambio-sede: Richiedi il cambio sede
- DELETE /api/pem/{serial_number}/cambio-sede/{cambio_sede}: Annulla il cambio sede
- Catalogo - ATECO
- GET /api/pem/{serial_number}/dati/ateco: Lista ATECO
- POST /api/pem/{serial_number}/dati/ateco: Crea ATECO
- PUT /api/pem/{serial_number}/dati/ateco/{id}: Aggiorna ATECO
- DELETE /api/pem/{serial_number}/dati/ateco/{id}: Elimina ATECO
- Catalogo - Reparti
- GET /api/pem/{serial_number}/dati/reparti: Lista Reparti
- POST /api/pem/{serial_number}/dati/reparti: Crea Reparto
- PUT /api/pem/{serial_number}/dati/reparti/{reparto_id}: Aggiorna Reparto
- DELETE /api/pem/{serial_number}/dati/reparti/{reparto_id}: Elimina Reparto
- Funzioni fiscali - Consultazione
- GET /api/pem/{serial_number}/fiscale/chiusure/storico: Storico chiusure
- GET /api/pem/{serial_number}/fiscale/chiusure/{journalId}/documento: Dati di una chiusura
- POST /api/pem/{serial_number}/fiscale/consultazione/report: Report
- GET /api/pem/{serial_number}/fiscale/consultazione/dc: Dettaglio di un DC
- GET /pem/{serial_number}/fiscale/consultazione/dc/{hash}/pdf: PDF pubblico di un DC
- Funzioni fiscali - Controllo PEM
- GET /api/pem/{serial_number}/controllo: Dati di controllo AdE del PEM
- POST /api/pem/{serial_number}/fiscale/gestionali/controllo: Emetti Documento Gestionale di Controllo
- Funzioni fiscali - Documenti gestionali
- GET /api/pem/{serial_number}/fiscale/gestionali: Archivio documenti gestionali
- GET /api/pem/{serial_number}/fiscale/gestionali/{id}/pdf: Download di un documento gestionale archiviato
- POST /api/pem/{serial_number}/fiscale/gestionali/operazioni: Documento gestionale operazioni memorizzate
- POST /api/pem/{serial_number}/fiscale/gestionali/esiti-trasmissione: Documento gestionale esiti trasmissioni corrispettivi
- POST /api/pem/{serial_number}/fiscale/gestionali/storico-buoni-pasto: Documento gestionale storico opzione buoni pasto
- POST /api/pem/{serial_number}/fiscale/gestionali/chiusura/{journalId}: Documento gestionale di chiusura
- Funzioni fiscali - Emergenza
- POST /api/pem/{serial_number}/fiscale/emergenza/chiusura: Chiusura di emergenza
- Funzioni fiscali - Opzione buoni pasto
- GET /api/pem/{serial_number}/fiscale/opzione-buoni-pasto: Stato opzione buoni pasto
- POST /api/pem/{serial_number}/fiscale/opzione-buoni-pasto: Attiva/disattiva opzione buoni pasto
- GET /api/pem/{serial_number}/fiscale/opzione-buoni-pasto/storico: Storico opzione buoni pasto
- Funzioni fiscali - Richieste PEM
- GET /api/pem/{serial_number}/fiscale/richieste: Lista richieste
- GET /api/pem/{serial_number}/fiscale/richieste/stato/{idRichiesta}: Verifica stato richiesta
- GET /api/pem/{serial_number}/fiscale/richieste/esito/{idRichiesta}: Recupera esito richiesta
- Funzioni fiscali - Segnalazioni
- GET /api/pem/{serial_number}/fiscale/segnalazioni/inattivita: Periodi di inattività
- POST /api/pem/{serial_number}/fiscale/segnalazioni/inattivita: Segnala un periodo di inattività
- Funzioni fiscali - Stato PEM
- GET /api/pem/{serial_number}/fiscale/stati: Lista Stati PEM
- PUT /api/pem/{serial_number}/fiscale/stato: Modifica lo stato del PEM
- POST /api/pem/{serial_number}/fiscale/stato/dismissione: Dismissione del PEM
- Funzioni fiscali - Trasmissioni
- POST /api/pem/{serial_number}/fiscale/invio/dc: Invio DC
- POST /api/pem/{serial_number}/fiscale/invio/annullo: Annulla DC
- GET /api/pem/{serial_number}/fiscale/invio/reso: Recupera dati reso DC
- POST /api/pem/{serial_number}/fiscale/invio/reso: Reso DC
- POST /api/pem/{serial_number}/fiscale/invio/chiusura: Chiusura giornaliera
Account - Registrazione
Richiesta di registrazione esercente
POST /api/auth/register
Pubblica: nessun token.
Registra la richiesta di adesione di un esercente, senza credenziali: la
esamina l'erogatore e, all'approvazione, l'esercente riceve l'email per
scegliere la password. affiliate_code è il codice del partner che
l'ha portato (AFF-…), facoltativo.
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
nome |
string |
sì | Nome del titolare. Al massimo 60 caratteri. Esempio: Mario. |
cognome |
string |
sì | Cognome del titolare. Al massimo 60 caratteri. Esempio: Rossi. |
email |
string |
sì | Email del titolare, unica: è l'indirizzo dell'account Billy ed è anche il nome utente dell'account. Non si può cambiare dopo l'approvazione. Deve essere un indirizzo email valido. Al massimo 80 caratteri. Esempio: mario.rossi@example.it. |
telefono |
string |
sì | Telefono, da 6 a 11 cifre; il prefisso +39 o 0039, gli spazi e i separatori vengono tolti. Formato: /^\d{6,11}$/. Esempio: 3331234567. |
partita_iva |
string |
sì | Partita IVA dell'attività, verificata e unica. Va inviata come stringa: un numero JSON perderebbe gli zeri iniziali ed è rifiutato. Esempio: 01234567897. |
codice_fiscale |
string |
sì | Codice fiscale dell'attività o del titolare: 16 caratteri con carattere di controllo valido (omocodie ammesse, convertito in maiuscolo), oppure 11 cifre per le società, di solito uguali alla partita IVA. Esempio: RSSMRA80A01F205X. |
denominazione |
string |
sì | Denominazione dell'attività. Al massimo 80 caratteri. Esempio: Bar Centrale di Mario Rossi. |
indirizzo |
string |
sì | Indirizzo della sede legale. Al massimo 60 caratteri. Esempio: Via Roma. |
civico |
string |
sì | Numero civico della sede legale. Al massimo 8 caratteri. Esempio: 1. |
cap |
string |
sì | CAP della sede legale, 5 cifre. Deve essere composto da 5 cifre. Esempio: 20121. |
comune |
string |
sì | Comune della sede legale. Al massimo 60 caratteri. Esempio: Milano. |
provincia |
string |
sì | Sigla della provincia (elenco ISTAT; EE per l'estero). Deve essere lungo 2 caratteri. Valori: AG, AL, AN, AO, AP, AQ, AR, AT, AV, BA, BG, BI, BL, BN, BO, BR, BS, BT, BZ, CA, CB, CE, CH, CL, CN, CO, CR, CS, CT, CZ, EN, FC, FE, FG, FI, FM, FR, GE, GO, GR, IM, IS, KR, LC, LE, LI, LO, LT, LU, MB, MC, ME, MI, MN, MO, MS, MT, NA, NO, NU, OR, PA, PC, PD, PE, PG, PI, PN, PO, PR, PT, PU, PV, PZ, RA, RC, RE, RG, RI, RM, RN, RO, SA, SI, SO, SP, SR, SS, SU, SV, TA, TE, TN, TO, TP, TR, TS, TV, UD, VA, VB, VC, VE, VI, VR, VT, VV, EE. Esempio: MI. |
nazione |
string |
sì | Codice della nazione, 2 caratteri. Deve essere lungo 2 caratteri. Esempio: IT. |
pec |
string |
no | PEC dell'attività, facoltativa. Deve essere un indirizzo email valido. Al massimo 80 caratteri. Può essere null. Esempio: barcentrale@pec.it. |
sdi |
string |
no | Codice destinatario SDI, 7 lettere o cifre (convertito in maiuscolo), facoltativo. Formato: /^[A-Z0-9]{7}$/. Deve essere lungo 7 caratteri. Può essere null. Esempio: M5UXCR1. |
regime_fiscale |
string |
sì | Regime fiscale dell'attività. Valori: ordinario, semplificato, forfettario_minimo. Esempio: ordinario. |
sede_operativa |
object |
no | Facoltativa: sede e referente del punto vendita, sede del primo PEM. Se manca, è null o è vuota vale la sede legale con i dati del titolare. Può essere null. |
sede_operativa.nome_referente |
string |
sì | Al massimo 60 caratteri. Esempio: Mario. |
sede_operativa.cognome_referente |
string |
sì | Al massimo 60 caratteri. Esempio: Rossi. |
sede_operativa.email_referente |
string |
sì | Deve essere un indirizzo email valido. Al massimo 80 caratteri. Esempio: mario.rossi@example.it. |
sede_operativa.telefono_referente |
string |
sì | Formato: /^\d{6,11}$/. Esempio: 3331234567. |
sede_operativa.indirizzo |
string |
sì | Al massimo 60 caratteri. Esempio: Corso Buenos Aires. |
sede_operativa.civico |
string |
sì | Al massimo 8 caratteri. Esempio: 10. |
sede_operativa.cap |
string |
sì | Deve essere composto da 5 cifre. Esempio: 20124. |
sede_operativa.comune |
string |
sì | Al massimo 60 caratteri. Esempio: Milano. |
sede_operativa.provincia |
string |
sì | Deve essere lungo 2 caratteri. Valori: AG, AL, AN, AO, AP, AQ, AR, AT, AV, BA, BG, BI, BL, BN, BO, BR, BS, BT, BZ, CA, CB, CE, CH, CL, CN, CO, CR, CS, CT, CZ, EN, FC, FE, FG, FI, FM, FR, GE, GO, GR, IM, IS, KR, LC, LE, LI, LO, LT, LU, MB, MC, ME, MI, MN, MO, MS, MT, NA, NO, NU, OR, PA, PC, PD, PE, PG, PI, PN, PO, PR, PT, PU, PV, PZ, RA, RC, RE, RG, RI, RM, RN, RO, SA, SI, SO, SP, SR, SS, SU, SV, TA, TE, TN, TO, TP, TR, TS, TV, UD, VA, VB, VC, VE, VI, VR, VT, VV, EE. Esempio: MI. |
sede_operativa.nazione |
string |
sì | Deve essere lungo 2 caratteri. Esempio: IT. |
affiliate_code |
string |
no | Codice del partner affiliato che ha portato l'esercente, facoltativo. Al massimo 32 caratteri. Può essere null. Esempio: AFF-7K2M9QXA. |
privacy |
boolean |
sì | Accettazione dell'informativa privacy. Deve valere true. Esempio: true. |
Esempio:
{
"nome": "Mario",
"cognome": "Rossi",
"email": "mario.rossi@example.it",
"telefono": "3331234567",
"partita_iva": "01234567897",
"codice_fiscale": "RSSMRA80A01F205X",
"denominazione": "Bar Centrale di Mario Rossi",
"indirizzo": "Via Roma",
"civico": "1",
"cap": "20121",
"comune": "Milano",
"provincia": "MI",
"nazione": "IT",
"regime_fiscale": "ordinario",
"privacy": true
}
Risposte
200— Richiesta registrata
{
"success": true,
"message": "Registrazione avvenuta con successo"
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
429— Troppe richieste
{
"success": false,
"message": "Troppe richieste di registrazione: riprova tra qualche minuto",
"error": "too_many_requests"
}
Anagrafica - PEM
Lista PEM
GET /api/pem
Scope richiesto ai client partner: fiscale:read.
Mostra la lista dei PEM associati all'utente autenticato.
Risposte
200— success
{
"success": true,
"pem": [
{
"id": 1,
"serial_number": "ASVS-241232",
"stato": "In servizio",
"created_at": "01-01-2025 13:00:00",
"indirizzo": "Via Roma 1"
}
]
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
Mostra PEM
GET /api/pem/{serial_number}
Scope richiesto ai client partner: fiscale:read.
Mostra i dettagli del PEM indicato.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"pem": {
"id": 1,
"serial_number": "ASVS-241232",
"stato": "In servizio",
"created_at": "01-01-2025 13:00:00",
"indirizzo": "Via Roma 1"
}
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Richiedi il cambio sede
POST /api/pem/{serial_number}/cambio-sede
Scope richiesto ai client partner: fiscale:manage.
Chiede di spostare il PEM a un nuovo indirizzo. Se serve l'approvazione dell'erogatore la richiesta resta in attesa; una volta approvata l'emissione è sospesa fino alla chiusura di giornata e la nuova sede vale dalla prima emissione successiva.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
indirizzo |
string |
sì | Al massimo 60 caratteri. Esempio: Via Garibaldi. |
civico |
string |
sì | Al massimo 8 caratteri. Esempio: 12. |
cap |
string |
sì | Deve essere composto da 5 cifre. Esempio: 20121. |
comune |
string |
sì | Al massimo 60 caratteri. Esempio: Milano. |
provincia |
string |
sì | Deve essere lungo 2 caratteri. Esempio: MI. |
nazione |
string |
sì | Al massimo 2 caratteri. Esempio: IT. |
sede_legale |
boolean |
sì | Esempio: false. |
Esempio:
{
"indirizzo": "Via Garibaldi",
"civico": "12",
"cap": "20121",
"comune": "Milano",
"provincia": "MI",
"nazione": "IT",
"sede_legale": false
}
Risposte
200— Richiesta registrata
{
"success": true,
"cambio_sede": {
"id": 3,
"stato": "richiesta",
"indirizzo": "Via Garibaldi",
"civico": "12",
"cap": "20121",
"comune": "Milano",
"provincia": "MI",
"nazione": "IT",
"sede_legale": false,
"motivazione_rifiuto": null,
"created_at": "08-10-2026 10:15:42",
"approvato_il": null
},
"message": "Richiesta inviata: dopo l'approvazione dell'erogatore l'emissione sarà sospesa fino alla chiusura di giornata, poi la nuova sede sarà applicata automaticamente alla prima emissione"
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
Annulla il cambio sede
DELETE /api/pem/{serial_number}/cambio-sede/{cambio_sede}
Scope richiesto ai client partner: fiscale:manage.
Ritira una richiesta di cambio sede non ancora applicata (409 se non è più annullabile).
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
cambio_sede |
integer |
sì | L'id della richiesta di cambio sede. Esempio: 4. |
Risposte
200— success
{
"success": true,
"message": "Richiesta di cambio sede annullata"
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Catalogo - ATECO
Lista ATECO
GET /api/pem/{serial_number}/dati/ateco
Scope richiesto ai client partner: catalogo:read.
Restituisce i codici ATECO associati al PEM indicato.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"ateco": [
{
"id": 1,
"codice": "112233",
"descrizione": "TEST ATECO"
}
]
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Crea ATECO
POST /api/pem/{serial_number}/dati/ateco
Scope richiesto ai client partner: catalogo:write.
Crea un nuovo codice ATECO associato al PEM indicato.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
ateco |
object |
no | |
ateco.descrizione |
string |
sì | La descrizione dell'ATECO. Al massimo 100 caratteri. Esempio: Commercio al dettaglio. |
ateco.codice |
string |
sì | Il codice ATECO nel formato XX.XX.XX. Unico sul PEM. Formato: /^\d{2}.\d{2}.\d{2}$/. Esempio: 47.11.00. |
Esempio:
{
"ateco": {
"descrizione": "Commercio al dettaglio",
"codice": "47.11.00"
}
}
Risposte
200— success
{
"success": true,
"message": "ATECO creato con successo",
"ateco": {
"id": 1,
"codice": "112233",
"descrizione": "TEST ATECO"
}
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Validazione fallita
{
"success": false,
"message": "Il campo codice è obbligatorio",
"errors": {
"ateco.codice": [
"Il campo codice è obbligatorio"
]
}
}
Aggiorna ATECO
PUT /api/pem/{serial_number}/dati/ateco/{id}
Scope richiesto ai client partner: catalogo:write.
Aggiorna un codice ATECO esistente associato al PEM indicato.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
id |
integer |
sì | L'ID dell'ATECO. Esempio: 23. |
Corpo della richiesta (application/json)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
ateco |
object |
no | |
ateco.descrizione |
string |
no | La descrizione dell'ATECO. Al massimo 100 caratteri. Esempio: Commercio al dettaglio. |
ateco.codice |
string |
no | Il codice ATECO nel formato XX.XX.XX. Unico sul PEM. Formato: /^\d{2}.\d{2}.\d{2}$/. Esempio: 47.11.00. |
Esempio:
{
"ateco": {
"descrizione": "Commercio al dettaglio",
"codice": "47.11.00"
}
}
Risposte
200— success
{
"success": true,
"message": "ATECO aggiornato con successo",
"ateco": {
"id": 1,
"codice": "112233",
"descrizione": "TEST ATECO"
}
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— ATECO non trovato
{
"success": false,
"message": "La risorsa richiesta non è stata trovata."
}
422— Validazione fallita
{
"success": false,
"message": "Il campo codice è obbligatorio",
"errors": {
"ateco.codice": [
"Il campo codice è obbligatorio"
]
}
}
Elimina ATECO
DELETE /api/pem/{serial_number}/dati/ateco/{id}
Scope richiesto ai client partner: catalogo:write.
Elimina un codice ATECO associato al PEM indicato.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
id |
integer |
sì | L'ID dell'ATECO. Esempio: 23. |
Risposte
200— success
{
"success": true,
"message": "ATECO eliminato con successo"
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— ATECO non trovato
{
"success": false,
"message": "La risorsa richiesta non è stata trovata."
}
Catalogo - Reparti
Lista Reparti
GET /api/pem/{serial_number}/dati/reparti
Scope richiesto ai client partner: catalogo:read.
Mostra la lista dei reparti associati al PEM corrente.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"reparti": [
{
"id": 1,
"sigla": "R1",
"descrizione": "Reparto 1",
"importo": 100,
"iva": "22",
"colore": "#FFFFFF",
"bene_servizio": "B",
"id_categoria": 1,
"id_ateco": 1
}
]
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Crea Reparto
POST /api/pem/{serial_number}/dati/reparti
Scope richiesto ai client partner: catalogo:write.
Memorizza un nuovo reparto associato al PEM corrente.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
reparto |
object |
no | |
reparto.sigla |
string |
sì | La sigla del reparto. Al massimo 20 caratteri. Esempio: A. |
reparto.codice |
string |
no | Il codice del reparto. Al massimo 50 caratteri. Può essere null. Esempio: REP-001. |
reparto.descrizione |
string |
sì | La descrizione del reparto. Al massimo 100 caratteri. Esempio: Caffetteria. |
reparto.importo |
number |
sì | L'importo del reparto. Esempio: 1.2. |
reparto.iva |
string |
sì | L'aliquota IVA del reparto. Valori: 4, 5, 10, 22, N1, N2, N3, N4, N5, N6, VI. Esempio: 10. |
reparto.colore |
string |
no | Il colore del reparto. Formato: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/. Esempio: #FFFFFF. |
reparto.bene_servizio |
string |
sì | Il tipo di bene/servizio del reparto. Valori: B, S. Esempio: B. |
reparto.id_categoria |
number |
no | L'ID della categoria del reparto. Può essere null. Esempio: 1. |
reparto.id_ateco |
number |
no | L'ID dell'ATECO del reparto. Può essere null. Esempio: 1. |
Esempio:
{
"reparto": {
"sigla": "A",
"descrizione": "Caffetteria",
"importo": 1.2,
"iva": "10",
"bene_servizio": "B"
}
}
Risposte
200— success
{
"success": true,
"message": "Reparto creato con successo",
"reparto": {
"id": 1,
"sigla": "R1",
"descrizione": "Reparto 1",
"importo": 100,
"iva": "22",
"colore": "#FFFFFF",
"bene_servizio": "B",
"id_categoria": 1,
"id_ateco": 1
}
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Validazione fallita
{
"success": false,
"message": "Il campo iva è obbligatorio",
"errors": {
"reparto.iva": [
"Il campo iva è obbligatorio"
]
}
}
Aggiorna Reparto
PUT /api/pem/{serial_number}/dati/reparti/{reparto_id}
Scope richiesto ai client partner: catalogo:write.
Aggiorna un reparto esistente associato al PEM indicato.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
reparto_id |
integer |
sì | L'ID del reparto. Esempio: 23. |
Corpo della richiesta (application/json)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
reparto |
object |
no | |
reparto.sigla |
string |
no | La sigla del Reparto. Al massimo 20 caratteri. Esempio: A. |
reparto.codice |
string |
no | Il codice del Reparto. Al massimo 50 caratteri. Può essere null. Esempio: REP-001. |
reparto.descrizione |
string |
no | La descrizione del Reparto. Al massimo 100 caratteri. Esempio: Caffetteria. |
reparto.importo |
number |
no | L'importo del Reparto. Esempio: 1.2. |
reparto.iva |
string |
no | L'IVA del Reparto. Valori: 4, 5, 10, 22, N1, N2, N3, N4, N5, N6, VI. Esempio: 10. |
reparto.colore |
string |
no | Il colore del Reparto in esadecimale. Formato: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/. Esempio: #FFFFFF. |
reparto.ordine |
number |
no | L'ordine del Reparto. Esempio: 1. |
reparto.bene_servizio |
string |
no | Il tipo di Bene/Servizio del Reparto. Valori: B, S. Esempio: B. |
reparto.preferito |
boolean |
no | Indica se il Reparto è preferito. Esempio: true. |
reparto.id_categoria |
number |
no | L'ID della Categoria del Reparto. Può essere null. Esempio: 1. |
reparto.id_ateco |
number |
no | L'ID dell'ATECO del Reparto. Può essere null. Esempio: 1. |
Esempio:
{
"reparto": {
"sigla": "A",
"descrizione": "Caffetteria",
"importo": 1.2,
"iva": "10",
"bene_servizio": "B"
}
}
Risposte
200— success
{
"success": true,
"message": "Reparto aggiornato con successo",
"reparto": {
"id": 1,
"sigla": "R1",
"descrizione": "Reparto 1",
"importo": 100,
"iva": "22",
"colore": "#FFFFFF",
"bene_servizio": "B",
"id_categoria": 1,
"id_ateco": 1
}
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Reparto non trovato
{
"success": false,
"message": "La risorsa richiesta non è stata trovata."
}
422— Validazione fallita
{
"success": false,
"message": "Aliquota non valida",
"errors": {
"reparto.iva": [
"Aliquota non valida"
]
}
}
Elimina Reparto
DELETE /api/pem/{serial_number}/dati/reparti/{reparto_id}
Scope richiesto ai client partner: catalogo:write.
Elimina un reparto associato al PEM indicato.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
reparto_id |
integer |
sì | L'ID del reparto. Esempio: 23. |
Risposte
200— success
{
"success": true,
"message": "Reparto eliminato con successo"
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Reparto non trovato
{
"success": false,
"message": "La risorsa richiesta non è stata trovata."
}
Funzioni fiscali - Consultazione
Storico chiusure
GET /api/pem/{serial_number}/fiscale/chiusure/storico
Scope richiesto ai client partner: fiscale:read.
Elenca le giornate chiuse del PEM, dalla più recente, con il numero di DC
e la data di trasmissione al PEL (inviato_il nullo = chiusura non ancora
trasmessa). journal_aperto è la giornata in corso, nullo se la cassa è chiusa.
data_chiusura è in ora locale; inviato_il e aperto_il in UTC.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"chiusure": [
{
"id": 12,
"progressivo": 12,
"data_chiusura": "2026-10-07T21:30:00",
"numero_dc": 48,
"numero_dc_journal": 48,
"inviato_il": "2026-10-07T19:30:04.000000Z"
}
],
"journal_aperto": {
"id": 13,
"progressivo": 13,
"aperto_il": "2026-10-08T06:02:11.000000Z"
}
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Dati di una chiusura
GET /api/pem/{serial_number}/fiscale/chiusure/{journalId}/documento
Scope richiesto ai client partner: fiscale:read.
Restituisce i dati della giornata fiscale chiusa (journalId da Storico
chiusure): dati locali della chiusura uniti ai totali del PEL, unica fonte
fiscale. Finché la chiusura non è stata trasmessa all'AdE il PEL non ha i
totali e la risposta è 409.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
journalId |
integer |
sì | L'id della chiusura (campo id dello storico). Esempio: 12. |
Risposte
200— success
{
"success": true,
"documento": {
"pem": {
"serial_number": "ASVS-241232",
"indirizzo": "Via Roma 1",
"comune": "Milano",
"cap": "20100",
"provincia": "MI"
},
"esercente": {
"denominazione": "Bar Centrale srl",
"partita_iva": "01234567890"
},
"journal": {
"progressivo": 12,
"data_chiusura": "2026-10-07T21:30:00",
"numero_dc": 48,
"numero_dc_journal": 48
},
"riepilogo": [],
"pagamenti": [],
"riepiloghi": [],
"chiusure": [],
"buoni_pasto": {
"attiva": false,
"aggiornato_il": null
}
}
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
409— Corrispettivi non trasmessi
{
"success": false,
"message": "Chiusura non ancora trasmessa all'AdE"
}
Report
POST /api/pem/{serial_number}/fiscale/consultazione/report
Scope richiesto ai client partner: fiscale:read.
Elabora il report delle vendite del PEM indicato
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
data_inizio |
string |
no | Data di inizio del periodo di report. Deve essere una data valida. Esempio: 2026-10-01. |
data_fine |
string |
no | Data di fine del periodo di report. Deve essere una data valida. Esempio: 2026-10-31. |
metodi_pagamento |
array<string> |
no | Metodo di pagamento da filtrare, con i codici di emissione (PC, PP, TK, NRF, NRB, NRS, NRD). Esempio: ["PP"]. |
utenti |
array<integer> |
no | ID utente specifico da filtrare. Esempio: [121]. |
tipo_documenti |
array<string> |
no | Tipo di documento da filtrare: DC (vendita), ANNULLO o RESO. Esempio: ["DC"]. |
ricerca |
string |
no | Testo libero per filtrare per progressivo DC (es. '0089-0001') o per descrizione di un elemento contabile. Al massimo 255 caratteri. Può essere null. Esempio: 0089. |
Esempio:
{
"data_inizio": "2026-10-01",
"data_fine": "2026-10-31"
}
Risposte
200— success
{
"success": true,
"scontrini": [
{
"id": 102,
"user": "EsercenteTEST",
"tipo": "DC",
"progressivo": "0089-0001",
"data": "2025-07-22 14:58:57",
"inviato_il": "2025-07-22 14:59:02",
"importo": 377.5,
"pagamenti_metodo": "PC",
"progressivo_riferimento": null,
"annullato": false,
"reso_fatto": false,
"hash": "NmNhMzI5MDc3NjY2YzI5OTk2NDBiODg5YmFhMjEyMDI3MzZlZmNiNTMzMjEzNDQxNDE1YzQ1MmZlYWMyMjYyZTlmMTljMWVkYzFmN2UzMGU2ODYxMGIxMzVjZmJiMDBjNDAwMDI5NmQ5YTk1ODk4ZDI4NWQ3NmU1MjI5ZTkwMzg="
}
],
"totali": {
"totaleLordo": 377.5,
"totaleAnnulli": 0,
"totaleResi": 0,
"pagamenti": {
"contanti": 377,
"elettronico": 0,
"ticket": 0,
"nonRiscossoBeni": 0,
"nonRiscossoServizi": 0,
"nonRiscossoFattura": 0,
"scontoAPagare": 0
},
"iva": {
"10": {
"imponibile": 70.45454545,
"importo": 7.04545455
},
"N2": {
"imponibile": 100,
"importo": 0
},
"N4": {
"imponibile": 200,
"importo": 0
}
},
"reparto": {
"Nessuno": 377.5
},
"totaleOmaggi": 0
}
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
Dettaglio di un DC
GET /api/pem/{serial_number}/fiscale/consultazione/dc
Scope richiesto ai client partner: fiscale:read.
Restituisce un documento commerciale del PEM nello stesso formato della
risposta di emissione: con id quello indicato, senza l'ultimo emesso
dall'utente del token.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Parametri della query
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
id |
integer |
no | L'id del documento commerciale (dal report). Esempio: 1532. |
Risposte
200— Il documento commerciale (abbreviato)
{
"success": true,
"dati": {
"tipo": "DC",
"progressivo": "0012-0007",
"data": "2026-10-08 10:15:42",
"hash": "YjQ0ZDJmMGE5YzFl...MmEzYjQ=",
"codice_lotteria": null,
"cessionario_committente": null,
"elementi_contabili": [
{
"id": 5531,
"descrizione": "Caffè espresso",
"bene_servizio": "B",
"quantita": "2.00",
"prezzo_unitario": "1.20",
"sconto": "0.00",
"iva": "10",
"acconto_versato_beni_non_consegnati": false,
"omaggio": false
}
],
"pagamenti_dc": [
{
"importo": "2.40",
"metodo": "PC"
}
],
"condivisione": {
"testo_stampa": "G0AbYQFCQVIgQ0VOVFJBTEUg...",
"pdf_url": "https://pem-staging.billyssw.it/pem/ASVS-241232/fiscale/consultazione/dc/YjQ0ZDJmMGE5YzFl...MmEzYjQ%3D/pdf"
}
}
}
401—
{
"success": false,
"message": "Il token di accesso non è valido.",
"error": "token_invalid"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Documento inesistente
{
"success": false,
"errore": "Documento commerciale non trovato"
}
PDF pubblico di un DC
GET /pem/{serial_number}/fiscale/consultazione/dc/{hash}/pdf
Pubblica: nessun token.
Il PDF firmato del documento, senza token: è l'URL di Content-Location della risposta di emissione. Sta fuori da /api. Limite di 60 richieste al minuto per indirizzo IP. width e font_size cambiano solo il PDF: il testo ESC/POS nei metadati segue le impostazioni di stampa dell'esercente.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
hash |
string |
sì | L'hash del documento, URL-encoded. Esempio: YjQ0ZDJmMGE5YzFl...MmEzYjQ=. |
Parametri della query
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
width |
integer |
no | Larghezza in mm, da 58 a 120 (default 120); i valori fuori intervallo vengono riportati al limite. Esempio: 58. |
font_size |
integer |
no | Corpo del testo, da 6 a 14 (default 10), con lo stesso limite. Esempio: 8. |
regalo |
integer |
no | Con 1, la copia di cortesia senza importi (solo per i DC di vendita). Esempio: 1. |
Risposte
200— Il PDF firmato del documento.
Corpo: application/pdf, binario.
429— Più di 60 richieste al minuto dallo stesso indirizzo IP.
{
"message": "Too Many Attempts."
}
Funzioni fiscali - Controllo PEM
Dati di controllo AdE del PEM
GET /api/pem/{serial_number}/controllo
Scope richiesto ai client partner: fiscale:read.
Restituisce i dati identificativi, di stato e di versione richiesti per il controllo del PEM.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"data": {
"matricola": "ASVS-000001",
"stato": "In servizio",
"data_cambio_stato": "01-01-2025 10:00:00",
"esercente": {
"partita_iva": "12345678901",
"codice_fiscale": "RSSMRA80A01H501Z",
"denominazione": "Esercente Srl"
},
"erogatore": {
"partita_iva": "12345678901",
"codice_fiscale": "RSSMRA80A01H501Z",
"denominazione": "Erogatore Srl"
},
"soluzione_software": {
"sigla": "123e4567-e89b-12d3-a456-426614174000",
"id_approvazione": "0000",
"data_approvazione": null
},
"versione_installata": {
"versione": 1,
"sotto_versione": 0,
"patch": "0",
"data_ora": "01-01-2025 10:00:00",
"swid": null
},
"versione_disponibile": {
"versione": 1,
"sotto_versione": 0,
"patch": "0",
"data_creazione": "01-01-2025 10:00:00",
"data_approvazione": null,
"swid": null
},
"dc_non_trasmessi": {
"count": 3,
"importo_totale": 125.5
}
}
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa."
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— PEM non trovato
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Emetti Documento Gestionale di Controllo
POST /api/pem/{serial_number}/fiscale/gestionali/controllo
Scope richiesto ai client partner: fiscale:manage.
Genera il PDF dei dati di controllo del PEM lato backend e lo archivia
come Documento Gestionale (tipo controllo), restituendolo in download.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— Il PDF firmato del documento gestionale.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento gestionale. | attachment; filename="documento_gestionale_0012-0001.pdf" |
Corpo: application/pdf, binario.
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa."
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— PEM non trovato
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
409— Nessun Journal aperto
{
"success": false,
"message": "Nessun Journal aperto disponibile"
}
Funzioni fiscali - Documenti gestionali
Archivio documenti gestionali
GET /api/pem/{serial_number}/fiscale/gestionali
Scope richiesto ai client partner: fiscale:read.
Elenca i documenti gestionali del PEM, di qualunque tipo, filtrabili per
data di elaborazione e per tipo. Senza Accept: application/json rende la
pagina Inertia dell'archivio.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Parametri della query
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
data |
string |
no | Filtra per data di elaborazione. Esempio: 2026-08-20. |
tipo |
string |
no | Filtra per tipo di documento gestionale. Valori: chiusura, controllo, operazioni, esiti_trasmissione, storico_buoni_pasto. Esempio: operazioni. |
Risposte
200— I documenti gestionali del PEM, dal più recente
{
"success": true,
"gestionali": [
{
"id": 5,
"progressivo": "0012-0001",
"tipo": "operazioni",
"data_elaborazione": "2026-10-08T10:15:42+02:00",
"parametri": {
"selezione": "date",
"data_inizio": "2026-10-01",
"data_fine": "2026-10-08"
}
}
]
}
401—
{
"success": false,
"message": "Il token di accesso non è valido.",
"error": "token_invalid"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Download di un documento gestionale archiviato
GET /api/pem/{serial_number}/fiscale/gestionali/{id}/pdf
Scope richiesto ai client partner: fiscale:read.
Restituisce il PDF firmato già emesso, qualunque ne sia il tipo.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
id |
integer |
sì | L'id del documento gestionale (dall'archivio). Esempio: 5. |
Risposte
200— Il PDF firmato del documento gestionale.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento gestionale. | attachment; filename="documento_gestionale_0012-0001.pdf" |
Corpo: application/pdf, binario.
401—
{
"success": false,
"message": "Il token di accesso non è valido.",
"error": "token_invalid"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Non trovato
{
"success": false,
"message": "Documento gestionale non trovato"
}
Documento gestionale operazioni memorizzate
POST /api/pem/{serial_number}/fiscale/gestionali/operazioni
Scope richiesto ai client partner: fiscale:manage.
Emette e restituisce il documento gestionale con le operazioni memorizzate
dal PEM secondo la chiave di selezione indicata (ST v1.4 §3.4.2, punti 1-4).
La selezione integrale produce il solo riepilogo; le selezioni delimitate
includono anche il dettaglio per documento e gli aggregati giornalieri.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
selezione |
string |
sì | Chiave di selezione: integrale (tutto l'archivio, solo riepilogo), date (tra due date), documento (per numero di documento), intervallo (tra due numeri di documento dello stesso journal). Valori: integrale, date, documento, intervallo. Esempio: date. |
data_inizio |
string |
no | Data di inizio del periodo. Obbligatoria con selezione=date. Deve essere una data valida. Esempio: 2026-10-01. |
data_fine |
string |
no | Data di fine del periodo. Obbligatoria con selezione=date. Deve essere una data valida. Deve essere una data uguale o successiva a data_inizio. Esempio: 2026-10-08. |
progressivo |
string |
no | Numero del documento in forma NNNN-PPPP. Obbligatorio con selezione=documento. Al massimo 32 caratteri. Esempio: 0089-0001. |
journal |
integer |
no | Progressivo del journal (NNNN). Obbligatorio con selezione=intervallo. Almeno 1. Esempio: 89. |
progressivo_da |
integer |
no | Progressivo iniziale del documento (PPPP). Obbligatorio con selezione=intervallo. Almeno 1. Al massimo 9999. Esempio: 1. |
progressivo_a |
integer |
no | Progressivo finale del documento (PPPP). Obbligatorio con selezione=intervallo. Al massimo 9999. Esempio: 50. |
metodi_pagamento |
array<string> |
no | Metodo di pagamento specifico da filtrare (es. "PC" per contanti, "PP" per pagamento elettronico). Esempio: ["PP"]. |
utenti |
array<integer> |
no | ID utente specifico da filtrare. Esempio: [121]. |
tipo_documenti |
array<string> |
no | Tipo di documento specifico da filtrare (es. "DC", "A" per annullo, "R" per reso). Esempio: ["DC"]. |
ateco |
array<string> |
no | Codice ATECO specifico da filtrare. Esempio: ["011101"]. |
ricerca |
string |
no | Testo libero su progressivo DC (es. '0089-0001') o descrizione di un elemento contabile. Al massimo 255 caratteri. Può essere null. Esempio: 0089. |
Esempio:
{
"selezione": "date",
"data_inizio": "2026-10-01",
"data_fine": "2026-10-08"
}
Risposte
200— Il PDF firmato del documento gestionale.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento gestionale. | attachment; filename="documento_gestionale_0012-0001.pdf" |
Corpo: application/pdf, binario.
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
409— Cassa chiusa
{
"success": false,
"message": "Nessun Journal aperto disponibile"
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
Documento gestionale esiti trasmissioni corrispettivi
POST /api/pem/{serial_number}/fiscale/gestionali/esiti-trasmissione
Scope richiesto ai client partner: fiscale:manage.
Emette e restituisce il documento gestionale con gli esiti delle
trasmissioni dei corrispettivi comprese tra due date (ST v1.4 §3.4.2,
punto 5). I dati provengono da richieste_pem: nessuna chiamata al PEL.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
data_inizio |
string |
sì | Data di inizio dell'intervallo di trasmissioni. Deve essere una data valida. Esempio: 2026-01-01. |
data_fine |
string |
sì | Data di fine dell'intervallo di trasmissioni. Deve essere una data valida. Deve essere una data uguale o successiva a data_inizio. Esempio: 2026-08-20. |
Esempio:
{
"data_inizio": "2026-01-01",
"data_fine": "2026-08-20"
}
Risposte
200— Il PDF firmato del documento gestionale.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento gestionale. | attachment; filename="documento_gestionale_0012-0001.pdf" |
Corpo: application/pdf, binario.
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
409— Cassa chiusa
{
"success": false,
"message": "Nessun Journal aperto disponibile"
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
Documento gestionale storico opzione buoni pasto
POST /api/pem/{serial_number}/fiscale/gestionali/storico-buoni-pasto
Scope richiesto ai client partner: fiscale:manage.
Emette e restituisce il documento gestionale con lo storico delle attivazioni e disattivazioni dell'opzione buoni pasto (ST v1.4 §3.4.2, punto 8). Nessun parametro di selezione.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— Il PDF firmato del documento gestionale.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento gestionale. | attachment; filename="documento_gestionale_0012-0001.pdf" |
Corpo: application/pdf, binario.
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
409— Cassa chiusa
{
"success": false,
"message": "Nessun Journal aperto disponibile"
}
Documento gestionale di chiusura
POST /api/pem/{serial_number}/fiscale/gestionali/chiusura/{journalId}
Scope richiesto ai client partner: fiscale:manage.
Emette il Documento Gestionale PDF firmato della giornata fiscale chiusa. I totali provengono dal PEL, unica fonte fiscale. Come per il report vendite ogni richiesta emette un nuovo documento, numerato sul journal corrente; le copie già emesse restano scaricabili dall'archivio gestionali.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
journalId |
integer |
sì | L'id della chiusura (campo id dello storico chiusure). Esempio: 12. |
Risposte
200— Il PDF firmato del documento gestionale.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento gestionale. | attachment; filename="documento_gestionale_0012-0001.pdf" |
Corpo: application/pdf, binario.
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
409— Corrispettivi non trasmessi
{
"success": false,
"message": "Chiusura non ancora trasmessa all'AdE"
}
Funzioni fiscali - Emergenza
Chiusura di emergenza
POST /api/pem/{serial_number}/fiscale/emergenza/chiusura
Scope richiesto ai client partner: fiscale:manage.
Trasmette al PEL gli aggregati della giornata annotati sul registro di
emergenza dei corrispettivi: riepiloghi IVA e totali dei pagamenti,
dichiarati dall'esercente. Ammessa solo a PEM Fuori servizio; la
chiusura riguarda la giornata in cui è inviata.
Una giornata ammette più chiusure, anche con dati diversi: ogni
idempotency_key (UUID scelto dal client) è una chiusura e un invio
distinto al PEL. Ripetere la chiamata con la stessa chiave è sicuro: se
la chiusura è già trasmessa si riceve il suo esito senza un nuovo invio,
se l'invio era fallito lo si ritenta. La stessa chiave con dati diversi,
o già usata su un altro PEM, è rifiutata (422).
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
idempotency_key |
string |
sì | UUID scelto dal client, uno per chiusura e propagato al PEL. Ripetendo la chiamata con la stessa chiave non si crea una seconda chiusura: si riceve l'esito di quella già trasmessa, o si ritenta l'invio fallito. La stessa chiave con dati diversi, o già usata su un altro PEM, è rifiutata (422). Deve essere un UUID valido. Esempio: 3f1c2a9e-8b7d-4c1e-9a2f-5d6e7f8a9b0c. |
n_doc_commerciali |
integer |
sì | Numero di documenti commerciali annotati sul registro di emergenza nella giornata. Almeno 1. Al massimo 999999999. Esempio: 12. |
riepiloghi |
array<object> |
sì | |
riepiloghi[].iva |
string |
no | Aliquota IVA (4, 5, 10, 22). Richiede imposta. Può essere null. Esempio: 22. |
riepiloghi[].natura |
string |
no | Codice natura (N1–N6), in alternativa a iva. Valori: N1, N2, N3, N4, N5, N6. Può essere null. |
riepiloghi[].ventilazione_iva |
string |
no | Ventilazione IVA (SI), in alternativa a iva e natura. Valori: SI. Può essere null. |
riepiloghi[].importo_parziale |
string |
sì | Imponibile della riga, stringa decimale con al massimo 2 decimali (può essere negativo). Al netto dell'IVA (al lordo con ventilazione_iva), al netto di resi, annulli, beni in sospeso e non riscossi, ma comprensivo degli omaggi. Formato: /^-?\d{1,11}(.\d{1,2})?$/. Esempio: 100.00. |
riepiloghi[].imposta |
string |
no | Imposta della riga: obbligatoria se e solo se è indicata iva, coerente con importo_parziale × aliquota entro ±0,01. Formato: /^-?\d{1,11}(.\d{1,2})?$/. Può essere null. Esempio: 22.00. |
riepiloghi[].codice_attivita |
string |
no | Codice Ateco della riga (facoltativo), tra quelli configurati sul PEM. Valori: null. Può essere null. |
riepiloghi[].totale_ammontare_resi |
string |
no | Ammontare dei resi (facoltativo, ≥ 0, al netto dell'IVA; al lordo con ventilazione IVA). Formato: /^\d{1,11}(.\d{1,2})?$/. Può essere null. |
riepiloghi[].totale_ammontare_annulli |
string |
no | Ammontare degli annulli (facoltativo, ≥ 0). Formato: /^\d{1,11}(.\d{1,2})?$/. Può essere null. |
riepiloghi[].beni_in_sospeso |
string |
no | Beni in sospeso (facoltativo, ≥ 0). Formato: /^\d{1,11}(.\d{1,2})?$/. Può essere null. |
riepiloghi[].non_riscosso_servizi |
string |
no | Non riscosso servizi (facoltativo, ≥ 0). Formato: /^\d{1,11}(.\d{1,2})?$/. Può essere null. |
riepiloghi[].non_riscosso_fatture |
string |
no | Non riscosso fatture (facoltativo, ≥ 0). Formato: /^\d{1,11}(.\d{1,2})?$/. Può essere null. |
riepiloghi[].non_riscosso_dcra_ssn |
string |
no | Non riscosso DCR a SSN (facoltativo, ≥ 0). Formato: /^\d{1,11}(.\d{1,2})?$/. Può essere null. |
riepiloghi[].non_riscosso_omaggio |
string |
no | Non riscosso omaggio (facoltativo, ≥ 0). Formato: /^\d{1,11}(.\d{1,2})?$/. Può essere null. |
totali |
object |
sì | |
totali.pagato_contanti |
string |
sì | Totale pagato in contanti. Formato: /^\d{1,11}(.\d{1,2})?$/. Esempio: 100.00. |
totali.pagato_elettronico |
string |
sì | Totale pagato con strumenti elettronici. Formato: /^\d{1,11}(.\d{1,2})?$/. Esempio: 77.55. |
totali.sconto_a_pagare |
string |
sì | Totale degli sconti a pagare. Formato: /^\d{1,11}(.\d{1,2})?$/. Esempio: 0.00. |
totali.ticket |
object |
no | Buoni pasto incassati (facoltativo). Senza opzione buoni pasto sono un normale pagamento. Con l'opzione attiva nella giornata richiedono un riepilogo al 10% il cui lordo ((importo_parziale + non_riscosso_servizi) × 1,10) li copra, e il sistema attribuisce il riferimento normativo TICKET ai riepiloghi al 10%: il client non invia rif_normativo. Può essere null. |
totali.ticket.pagato_ticket |
string |
no | Importo pagato con buoni pasto. Obbligatorio se è presente totali.ticket. Formato: /^\d{1,11}(.\d{1,2})?$/. |
totali.ticket.numero_ticket |
integer |
no | Numero di buoni pasto (≥ 1). Obbligatorio se è presente totali.ticket. Almeno 1. Al massimo 999999999. |
Esempio:
{
"idempotency_key": "3f1c2a9e-8b7d-4c1e-9a2f-5d6e7f8a9b0c",
"n_doc_commerciali": 12,
"riepiloghi": [
{
"iva": "22",
"importo_parziale": "100.00",
"imposta": "22.00"
},
{
"iva": "10",
"importo_parziale": "50.50",
"imposta": "5.05"
}
],
"totali": {
"pagato_contanti": "100.00",
"pagato_elettronico": "77.55",
"sconto_a_pagare": "0.00"
}
}
Risposte
200— success
{
"success": true,
"dati": {
"id_presa_in_carico": "12345",
"n_doc_commerciali": 12
}
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422—
Funzioni fiscali - Opzione buoni pasto
Stato opzione buoni pasto
GET /api/pem/{serial_number}/fiscale/opzione-buoni-pasto
Scope richiesto ai client partner: fiscale:read.
Restituisce lo stato efficace dell'opzione (quello che governa l'emissione) e, se una scelta è stata registrata ma decorre dal primo giorno del mese successivo (§5.3), anche la scelta in sospeso.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"attiva": true,
"opzione": {
"attiva": true,
"aggiornato_il": "12-08-2026 10:00:00",
"decorre_dal": "12-08-2026 10:00:00"
},
"scelta_pendente": null,
"modificabile": true
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Attiva/disattiva opzione buoni pasto
POST /api/pem/{serial_number}/fiscale/opzione-buoni-pasto
Scope richiesto ai client partner: fiscale:manage.
Registra l'attivazione o disattivazione dell'opzione per il trattamento dei
buoni pasto (ST v1.4 §5.3). Ammessa solo a cassa chiusa. Ha effetto dal
momento della scelta, salvo che nel mese corrente sia già stato emesso
almeno un DC con buoni pasto accettati: in tal caso decorre dal primo
giorno del mese successivo (campo decorre_dal della risposta).
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
attiva |
boolean |
sì | true per attivare l'opzione di trattamento dei buoni pasto, false per disattivarla. Il cambio è ammesso solo a cassa chiusa. Esempio: true. |
Esempio:
{
"attiva": true
}
Risposte
200— success
{
"success": true,
"message": "Opzione buoni pasto aggiornata",
"opzione": {
"attiva": true,
"aggiornato_il": "12-08-2026 10:00:00",
"decorre_dal": "01-09-2026 00:00:00"
}
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Ruolo non ammesso
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Cassa aperta
{
"error_code": "BP001",
"message": "Impossibile modificare opzione buoni pasto. Effettua chiusura di cassa e riprova."
}
Storico opzione buoni pasto
GET /api/pem/{serial_number}/fiscale/opzione-buoni-pasto/storico
Scope richiesto ai client partner: fiscale:read.
Restituisce lo storico delle attivazioni/disattivazioni dell'opzione, come richiesto dalle ST v1.4 (§3.4.2, lettura e stampa).
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"storico": [
{
"attiva": true,
"aggiornato_il": "12-08-2026 10:00:00",
"utente": "Mario Rossi"
}
]
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Funzioni fiscali - Richieste PEM
Lista richieste
GET /api/pem/{serial_number}/fiscale/richieste
Scope richiesto ai client partner: fiscale:read.
Recupera la lista delle richieste effettuate dal PEM specificato.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Parametri della query
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
tipo |
string |
no | Filtra per tipo di richiesta (CENSIMENTO, CORRISPETTIVI). Valori: CENSIMENTO, CORRISPETTIVI. Esempio: CENSIMENTO. |
Risposte
200— success
{
"success": true,
"message": "Richieste PEM recuperate",
"richieste": [
{
"id": 1,
"id_presa_in_carico": "ABC123",
"stato": "PRONTA",
"data": "2025-07-01 10:30:00",
"tipo": "CENSIMENTO"
}
]
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
Verifica stato richiesta
GET /api/pem/{serial_number}/fiscale/richieste/stato/{idRichiesta}
Scope richiesto ai client partner: fiscale:read.
Controlla lo stato attuale di una richiesta PEM specifica.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
idRichiesta |
integer |
sì | L'id della richiesta (campo id della lista). Esempio: 1. |
Risposte
200— success
{
"success": true,
"message": "Stato richiesta: COMPLETED",
"stato": "COMPLETED"
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Recupera esito richiesta
GET /api/pem/{serial_number}/fiscale/richieste/esito/{idRichiesta}
Scope richiesto ai client partner: fiscale:read.
Recupera l'esito finale di una richiesta pronta. Se l'esito è già presente nel database, lo restituisce direttamente senza effettuare una nuova chiamata al PEL.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
idRichiesta |
integer |
sì | L'id della richiesta (campo id della lista). Esempio: 1. |
Risposte
200— success
{
"success": true,
"message": "Esito richiesta recuperato",
"esito": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4..."
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Funzioni fiscali - Segnalazioni
Periodi di inattività
GET /api/pem/{serial_number}/fiscale/segnalazioni/inattivita
Scope richiesto ai client partner: fiscale:read.
Elenca i periodi di inattività segnalati per il PEM, dal più recente, con lo stato dell'inoltro al PEL.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"status": "success",
"data": [
{
"id": 3,
"serial_number": "ASVS-241232",
"dal": "2026-12-24 00:00:00",
"al": "2027-01-06 23:59:59",
"stato": "PENDING"
}
]
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Segnala un periodo di inattività
POST /api/pem/{serial_number}/fiscale/segnalazioni/inattivita
Scope richiesto ai client partner: fiscale:manage.
Comunica all'AdE, tramite il PEL, un periodo futuro in cui il PEM non
emetterà documenti (ferie, chiusura stagionale). La segnalazione è
accodata e inoltrata in modo asincrono: la risposta è 202. Le date sono
nel formato Y-m-d H:i:s, al successiva a dal e nel futuro.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
dal |
string |
sì | Data nel formato Y-m-d H:i:s. Esempio: 2026-11-01 00:00:00. |
al |
string |
sì | Data nel formato Y-m-d H:i:s. Deve essere una data successiva a dal. Esempio: 2026-11-30 23:59:59. |
Esempio:
{
"dal": "2026-11-01 00:00:00",
"al": "2026-11-30 23:59:59"
}
Risposte
202— success
{
"status": "success",
"message": "Periodo inattivo registrato"
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
Funzioni fiscali - Stato PEM
Lista Stati PEM
GET /api/pem/{serial_number}/fiscale/stati
Scope richiesto ai client partner: fiscale:read.
Restituisce la lista degli stati del PEM corrente.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"data": [
{
"id": 1,
"stato": "In servizio"
},
{
"id": 2,
"stato": "Dismesso"
}
]
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
Modifica lo stato del PEM
PUT /api/pem/{serial_number}/fiscale/stato
Scope richiesto ai client partner: fiscale:manage.
Comunica al PEL il cambio di stato del PEM.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
stato |
string |
sì | Stato del PEM (01: Fuori servizio, 03: In servizio). La dismissione (02) deve usare endpoint dedicato. Formato: /^\d{2}$/D. Valori: 01, 03. Esempio: 01. |
motivazione |
string |
no | Motivazione del Fuori servizio (01), obbligatoria con quello stato (01: Problemi hardware PEM, 02: Problemi software PEM, 03: Problemi di comunicazione PEM-PEL, 08: Mancata integrità, 09: Messa in magazzino - periodo di inattività, 10: Altro). Da non inviare con stato In servizio (03): il sistema trasmette 06 (Inizio ciclo di vita PEM) al primo passaggio in servizio e 07 (Ripristino da un fuori servizio) altrimenti. Formato: /^\d{2}$/D. Valori: 01, 02, 03, 08, 09, 10. Può essere null. Esempio: 01. |
note |
string |
no | Note sul cambiamento di stato, obbligatorie con stato Fuori servizio (01) qualunque sia la motivazione (AdE rifiuta altrimenti con CS009); facoltative con stato In servizio (03). Massimo 255 caratteri. Al massimo 255 caratteri. Può essere null. Esempio: Guasto alla rete del punto vendita. |
Esempio:
{
"stato": "01",
"motivazione": "01",
"note": "Guasto alla rete del punto vendita"
}
Risposte
200— success
{
"success": true,
"message": "Stato PEM aggiornato con successo",
"data": {
"id": 1,
"stato": "In servizio"
}
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Validazione fallita
{
"success": false,
"message": "La motivazione è obbligatoria",
"errors": {
"motivazione": [
"Il campo motivazione è obbligatorio"
]
}
}
Dismissione del PEM
POST /api/pem/{serial_number}/fiscale/stato/dismissione
Scope richiesto ai client partner: fiscale:manage.
Porta il PEM nello stato definitivo Dismesso e lo comunica al PEL. Riservata all'esercente titolare; lo stato e la motivazione non si scelgono (campi rifiutati).
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
note |
string |
sì | Note sulla dismissione del PEM, obbligatorie (AdE rifiuta altrimenti con CS009). Massimo 255 caratteri. Al massimo 255 caratteri. Esempio: Chiusura definitiva del ciclo di vita PEM. |
Esempio:
{
"note": "Chiusura definitiva del ciclo di vita PEM"
}
Risposte
200— success
{
"success": true,
"message": "Dismissione PEM completata con successo",
"data": {
"id": 7,
"stato": "Dismesso"
}
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
Funzioni fiscali - Trasmissioni
Invio DC
POST /api/pem/{serial_number}/fiscale/invio/dc
Scope richiesto ai client partner: fiscale:manage.
Emette un documento commerciale di vendita: genera e firma l'XML, lo aggiunge al Journal e ne accoda la trasmissione al PEL (la risposta non attende il PEL). Ammesso solo su un PEM In servizio.
idempotency_key (UUID) rende sicuro ripetere la chiamata: con una chiave già
usata sul PEM la risposta è il documento già emesso, senza emetterne un altro.
Come richiesto dalle specifiche AdE, l'unico output è lo stream di byte del PDF
firmato (PAdES, application/pdf): il testo ESC/POS per la stampante termica è
nei metadati XMP del PDF (billy:escPosBase64) e Content-Location è l'URL
pubblico dello stesso PDF (con ?regalo=1 la copia di cortesia). Gli errori
restano JSON. Il primo DC dopo una chiusura apre la nuova giornata.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
idempotency_key |
string |
sì | UUID scelto dal client, uno per documento: ripetendo la chiamata con la stessa chiave si riceve il documento già emesso. Deve essere un UUID valido. Al massimo 36 caratteri. Esempio: 3f1c2a9e-8b7d-4c1e-9a2f-5d6e7f8a9b0c. |
sconto_a_pagare |
number |
no | Lo sconto a pagare sul documento commerciale. Può essere null. Esempio: 2. |
arrotondamento_dl50_difetto |
boolean |
no | Indica che lo sconto a pagare rappresenta l'arrotondamento DL 50/2017 per difetto. Ammesso solo con pagamento integralmente in contanti e importo massimo 0,02 euro. Può essere null. Esempio: false. |
arrotondamento_dl50_eccesso |
number |
no | Importo dell'arrotondamento DL 50/2017 per eccesso. Ammesso solo con pagamento integralmente in contanti, mutuamente esclusivo con arrotondamento_dl50_difetto e importo massimo 0,02 euro. Almeno 0. Può essere null. Esempio: 0.01. |
sconto_subtotale |
number |
no | Sconto applicato all'intero subtotale (importo assoluto in euro, dopo gli sconti di linea). Viene ripartito sulle singole linee ai soli fini fiscali e non può superare il subtotale al netto degli sconti di linea. Almeno 0. Può essere null. Esempio: 1.8. |
codice_lotteria |
string |
no | Codice lotteria del cliente (massimo 8 caratteri). Richiede un totale di almeno 1 euro pagato con un unico pagamento PP; alternativo a cessionario_committente. Al massimo 8 caratteri. Può essere null. Esempio: ABC12345. |
cessionario_committente |
string |
no | Codice fiscale del cliente (massimo 16 caratteri), per il documento commerciale con codice fiscale. Alternativo a codice_lotteria. Al massimo 16 caratteri. Può essere null. Esempio: RSSMRA85M01H501Z. |
ateco |
string |
no | Codice ATECO dell'operazione (massimo 6 caratteri). Oggi è accettato ma non riportato nel documento. Al massimo 6 caratteri. Può essere null. Esempio: 561011. |
appendice |
array<string> |
no | Una riga di appendice (massimo 255 caratteri). Al massimo 255 caratteri. Esempio: ["Grazie e arrivederci"]. |
elementi |
array<object> |
sì | Le righe (elementi contabili) del documento commerciale, al massimo 200 e con al massimo 40 aliquote distinte. Al massimo 200 elementi. |
elementi[].descrizione |
string |
sì | La descrizione dell'elemento. Al massimo 255 caratteri. Esempio: Caffè espresso. |
elementi[].bene_servizio |
string |
sì | Indica se l'elemento è un bene (B) o un servizio (S). Valori: B, S. Esempio: B. |
elementi[].quantita |
number |
sì | La quantità dell'elemento (due decimali). Almeno 0. Esempio: 2. |
elementi[].prezzo_unitario |
number |
sì | Il prezzo unitario dell'elemento, IVA inclusa, in euro (due decimali). Almeno 0. Esempio: 1.20. |
elementi[].iva |
string |
sì | Aliquota IVA (4, 5, 10, 22), natura dell'operazione (N1-N6) o VI per la ventilazione. Valori: 4, 5, 10, 22, N1, N2, N3, N4, N5, N6, VI. Esempio: 10. |
elementi[].sconto |
number |
no | Sconto sulla riga, importo assoluto in euro. Almeno 0. Può essere null. Esempio: 0.2. |
elementi[].maggiorazione |
number |
no | La maggiorazione applicata all'elemento come importo assoluto. Almeno 0. Può essere null. Esempio: 1.5. |
elementi[].acconto_versato_beni_non_consegnati |
boolean |
no | Indica se l'elemento è un acconto versato per beni non consegnati. Può essere null. Esempio: false. |
elementi[].omaggio |
boolean |
no | Indica se l'elemento è un omaggio. Può essere null. Esempio: false. |
elementi[].id_reparto |
integer |
no | L'ID del reparto associato all'elemento. Può essere null. Esempio: 1. |
pagamenti |
array<object> |
no | I pagamenti. Obbligatori se il totale da pagare è maggiore di zero; devono coprirlo (i contanti possono eccederlo: la differenza è il resto). |
pagamenti[].importo |
number |
sì | L'importo del pagamento in euro. Almeno 0. Esempio: 2.40. |
pagamenti[].metodo |
string |
sì | PC contanti, PP elettronico, TK buoni pasto (con l'opzione buoni pasto attiva solo su operazioni al 10%), NRF/NRB/NRS/NRD non riscosso (fattura, beni, servizi, DCR a SSN). NRF e NRD escludono altri pagamenti. Valori: PC, PP, TK, NRF, NRB, NRS, NRD. Esempio: PC. |
pagamenti[].numero_ticket |
integer |
no | Il numero del ticket per i pagamenti con metodo TK. Obbligatorio se pagamenti.*.metodo vale TK. Almeno 0. Esempio: 123456. |
pagamenti[].pos |
object |
no | Facoltativo, per i pagamenti PP: dati della transazione sul terminale. |
pagamenti[].pos.pos |
string |
no | Circuito o fornitore del terminale (massimo 32 caratteri). Obbligatorio se è presente pagamenti.*.pos. Esempio: Nexi. |
pagamenti[].pos.uuid |
string |
no | Identificativo univoco della transazione. Obbligatorio se è presente pagamenti.*.pos. Al massimo 50 caratteri. Esempio: 9f8e7d6c-5b4a-4c3d-8e2f-1a0b9c8d7e6f. |
pagamenti[].pos.data_ora |
string |
no | Data e ora della transazione. Obbligatorio se è presente pagamenti.*.pos. Deve essere una data valida. Esempio: 2026-10-08T10:15:00+02:00. |
pagamenti[].pos.tid |
string |
no | Terminal ID. Al massimo 36 caratteri. Può essere null. Esempio: 12345678. |
pagamenti[].pos.auth_code |
string |
no | Codice di autorizzazione (massimo 20 caratteri). Al massimo 255 caratteri. Può essere null. Esempio: A1B2C3. |
Esempio:
{
"idempotency_key": "3f1c2a9e-8b7d-4c1e-9a2f-5d6e7f8a9b0c",
"elementi": [
{
"descrizione": "Caffè espresso",
"bene_servizio": "B",
"quantita": "2",
"prezzo_unitario": "1.20",
"iva": "10"
}
],
"pagamenti": [
{
"metodo": "PC",
"importo": "2.40"
}
]
}
Risposte
200— Il PDF firmato (PAdES) del documento emesso.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento (NNNN-PPPP). | inline; filename="DC_0012-0007.pdf" |
Content-Location |
L'URL pubblico dello stesso PDF, senza token: con ?regalo=1 la copia di cortesia (solo DC di vendita). Il segmento prima di /pdf è l'hash del documento, URL-encoded. |
https://pem-staging.billyssw.it/pem/ASVS-241232/fiscale/consultazione/dc/YjQ0ZDJmMGE5YzFl...MmEzYjQ%3D/pdf |
Corpo: application/pdf, binario.
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
409— Giornata aperta da più di 24 ore
{
"error_code": "JN002",
"message": "Apertura effettuata da più di 24 ore (ID: 42, Data: 2026-10-07 08:00:00)"
}
422— Validazione fallita
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
502— Il PEL non ha aperto la nuova giornata (JN004): il documento non è emesso, ripetere con la stessa idempotency_key.
{
"error_code": "JN004",
"message": "Errore apertura journal PEL: …"
}
Annulla DC
POST /api/pem/{serial_number}/fiscale/invio/annullo
Scope richiesto ai client partner: fiscale:manage.
Emette il documento commerciale di annullo di una vendita e ne accoda la
trasmissione al PEL. Per una vendita dello stesso PEM basta il suo
progressivo (NNNN-PPPP): righe e codice lotteria si prendono dall'originale.
Per un documento di un altro dispositivo si indicano matricola_annullo,
progressivo, dataOra ed elementi; con matricola POS, VR o ND il
progressivo non serve. La risposta, come per Invio DC, è il PDF firmato del documento.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
idempotency_key |
string |
sì | Chiave UUID usata per rendere idempotente la richiesta di annullo. Deve essere un UUID valido. Al massimo 36 caratteri. Esempio: 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d. |
progressivo |
string |
no | Il progressivo (NNNN-PPPP) del documento da annullare. Obbligatorio salvo matricola_annullo POS, VR o ND. Al massimo 11 caratteri. Esempio: 0012-0007. |
matricola_annullo |
string |
no | Solo per un documento emesso da un altro dispositivo: la sua matricola, oppure POS, VR o ND. Vuoto per un documento di questo PEM. Al massimo 11 caratteri. Esempio: 99MEX012345. |
dataOra |
string |
no | Data e ora del documento da annullare. Obbligatoria con matricola_annullo. Deve essere una data valida. Esempio: 2026-01-15 18:30:00. |
codice_lotteria |
string |
no | Codice lotteria associato al documento. Questo campo è opzionale e va fornito se il documento da annullare è stato emesso da un altro dispositivo. Al massimo 8 caratteri. Può essere null. Esempio: ABC12345. |
elementi |
array<object> |
no | L'array di elementi del documento di annullo. Questo campo è obbligatorio se il documento da annullare è stato emesso da un altro dispositivo. |
elementi[].descrizione |
string |
sì | La descrizione dell'elemento. Al massimo 255 caratteri. Esempio: Prodotto A. |
elementi[].bene_servizio |
string |
sì | Indica se l'elemento è un bene (B) o un servizio (S). Valori: B, S. Esempio: B. |
elementi[].quantita |
number |
sì | La quantità dell'elemento. Esempio: 2. |
elementi[].prezzo_unitario |
number |
sì | Il prezzo unitario dell'elemento. Esempio: 100. |
elementi[].iva |
string |
no | Il codice IVA applicato all'elemento. Obbligatorio se manca elementi.*.id. Valori: 4, 5, 10, 22, N1, N2, N3, N4, N5, N6, VI. |
elementi[].sconto |
number |
no | Lo sconto applicato all'elemento. Può essere null. Esempio: 10. |
elementi[].acconto_versato_beni_non_consegnati |
boolean |
no | Indica se l'elemento è un acconto versato per beni non consegnati. Può essere null. Esempio: false. |
elementi[].omaggio |
boolean |
no | Indica se l'elemento è un omaggio. Può essere null. Esempio: false. |
elementi[].ateco |
string |
no | Al massimo 6 caratteri. Può essere null. Esempio: bngz. |
Esempio:
{
"idempotency_key": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"progressivo": "0012-0007"
}
Risposte
200— Il PDF firmato (PAdES) del documento emesso.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento (NNNN-PPPP). | inline; filename="DC_0012-0007.pdf" |
Content-Location |
L'URL pubblico dello stesso PDF, senza token: con ?regalo=1 la copia di cortesia (solo DC di vendita). Il segmento prima di /pdf è l'hash del documento, URL-encoded. |
https://pem-staging.billyssw.it/pem/ASVS-241232/fiscale/consultazione/dc/YjQ0ZDJmMGE5YzFl...MmEzYjQ%3D/pdf |
Corpo: application/pdf, binario.
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Documento inesistente
{
"error_code": "DC001",
"message": "Documento commerciale non trovato"
}
409— Già annullato
{
"error_code": "DC003",
"message": "Il documento commerciale è già stato annullato"
}
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
502— Il PEL non ha aperto la nuova giornata (JN004): il documento non è emesso, ripetere con la stessa idempotency_key.
{
"error_code": "JN004",
"message": "Errore apertura journal PEL: …"
}
Recupera dati reso DC
GET /api/pem/{serial_number}/fiscale/invio/reso
Scope richiesto ai client partner: fiscale:manage.
Restituisce le righe di un documento commerciale, con il loro id e la
quantità già resa (reso), per comporre la richiesta di reso.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Parametri della query
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
hash |
string |
sì | L'hash del documento commerciale (campo hash della risposta di emissione). Esempio: YjQ0ZDJmMGE5YzFlNGI3ZDhmMDAxMmFiMzRjZDU2ZWY3ODkwYTFiMmMzZDRlNWY2YTdiOGM5ZDBlMWYyYTNiNA==. |
Risposte
200— success
{
"success": true,
"dati": {
"progressivo": "0012-0007",
"data": "2026-10-08 10:15:42",
"serial_number": "ASVS-241232",
"elementi_contabili": [
{
"id": 5531,
"descrizione": "Caffè espresso",
"bene_servizio": "B",
"quantita": "2.00",
"prezzo_unitario": "1.20",
"sconto": "0.00",
"iva": "10",
"acconto_versato_beni_non_consegnati": false,
"omaggio": false,
"reso": 0
}
]
}
}
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Documento inesistente
{
"success": false,
"message": "Documento commerciale non trovato"
}
Reso DC
POST /api/pem/{serial_number}/fiscale/invio/reso
Scope richiesto ai client partner: fiscale:manage.
Emette il documento commerciale di reso, totale o parziale, e ne accoda la
trasmissione al PEL. Per una vendita dello stesso PEM si indicano il suo
progressivo e, per ogni riga resa, l'id della riga originale (da Recupera
dati reso DC) con la quantita: il resto si prende dall'originale. Le righe di
servizio non sono rendibili. Per un documento di un altro dispositivo si
indicano matricola_reso, progressivo, dataOra e le righe complete.
La risposta, come per Invio DC, è il PDF firmato del documento.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Corpo della richiesta (application/json, obbligatorio)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
idempotency_key |
string |
sì | Chiave UUID usata per rendere idempotente la richiesta di reso. Deve essere un UUID valido. Al massimo 36 caratteri. Esempio: c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f. |
progressivo |
string |
no | Il progressivo (NNNN-PPPP) del documento di vendita da rendere. Obbligatorio salvo matricola_reso POS, VR o ND. Al massimo 11 caratteri. Esempio: 0012-0007. |
matricola_reso |
string |
no | Solo per un documento emesso da un altro dispositivo: la sua matricola, oppure POS, VR o ND. Vuoto per un documento di questo PEM. Al massimo 11 caratteri. Esempio: 99MEX012345. |
dataOra |
string |
no | Data e ora del documento da rendere. Obbligatoria con matricola_reso. Deve essere una data valida. Esempio: 2026-01-15 18:30:00. |
codice_lotteria |
string |
no | Il codice lotteria associato al reso. Questo campo è opzionale e va fornito se il documento di cui si vuole fare il reso è stato emesso da un altro dispositivo. Al massimo 8 caratteri. Può essere null. Esempio: ABC12345. |
elementi |
array<object> |
sì | L'array di elementi contabili del documento commerciale. |
elementi[].quantita |
number |
sì | La quantità dell'elemento da rendere. Esempio: 1. |
elementi[].id |
integer |
no | L'id della riga originale da rendere (da Recupera dati reso DC). Obbligatorio se il documento è stato emesso dallo stesso PEM. Esempio: 5531. |
elementi[].descrizione |
string |
no | La descrizione dell'elemento. Questo campo è obbligatorio se il documento di cui si vuole fare il reso è stato emesso da un altro dispositivo. Al massimo 255 caratteri. Esempio: Prodotto A. |
elementi[].bene_servizio |
string |
no | Indica se l'elemento è un bene (B). I servizi (S) non sono ammessi al reso. Questo campo è obbligatorio se il documento di cui si vuole fare il reso è stato emesso da un altro dispositivo. Valori: B. Esempio: B. |
elementi[].prezzo_unitario |
number |
no | Il prezzo unitario dell'elemento da rendere. Questo campo è obbligatorio se il documento di cui si vuole fare il reso è stato emesso da un altro dispositivo. Esempio: 10.5. |
elementi[].iva |
string |
no | Il codice IVA applicato all'elemento da rendere. Questo campo è obbligatorio se il documento di cui si vuole fare il reso è stato emesso da un altro dispositivo. Valori: 4, 5, 10, 22, N1, N2, N3, N4, N5, N6, VI. |
elementi[].sconto |
number |
no | Lo sconto applicato all'elemento da rendere. Può essere null. Esempio: 1. |
elementi[].acconto_versato_beni_non_consegnati |
boolean |
no | Indica se l'elemento è un acconto versato per beni non consegnati. Può essere null. Esempio: false. |
elementi[].omaggio |
boolean |
no | Indica se l'elemento è un omaggio. Può essere null. Esempio: false. |
elementi[].ateco |
string |
no | Il codice ATECO associato all'elemento. Al massimo 6 caratteri. Può essere null. Esempio: 123456. |
Esempio:
{
"idempotency_key": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"progressivo": "0012-0007",
"elementi": [
{
"id": 5531,
"quantita": "1"
}
]
}
Risposte
200— Il PDF firmato (PAdES) del documento emesso.
| Header | Descrizione | Esempio |
|---|---|---|
Content-Disposition |
Il nome del file contiene il progressivo del documento (NNNN-PPPP). | inline; filename="DC_0012-0007.pdf" |
Content-Location |
L'URL pubblico dello stesso PDF, senza token: con ?regalo=1 la copia di cortesia (solo DC di vendita). Il segmento prima di /pdf è l'hash del documento, URL-encoded. |
https://pem-staging.billyssw.it/pem/ASVS-241232/fiscale/consultazione/dc/YjQ0ZDJmMGE5YzFl...MmEzYjQ%3D/pdf |
Corpo: application/pdf, binario.
401— Token assente (error: unauthenticated), scaduto (error: token_expired) o non valido (error: token_invalid).
{
"success": false,
"message": "Il token di accesso è scaduto.",
"error": "token_expired"
}
403— Scope non concesso al client partner o ruolo non ammesso per l'operazione.
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
-
409— -
422— Dati non validi: errors riporta i messaggi per campo. Richiede Accept: application/json.
{
"success": false,
"message": "La somma degli importi dei pagamenti è inferiore al totale da pagare",
"errors": {
"pagamenti": [
"La somma degli importi dei pagamenti è inferiore al totale da pagare"
]
}
}
502— Il PEL non ha aperto la nuova giornata (JN004): il documento non è emesso, ripetere con la stessa idempotency_key.
{
"error_code": "JN004",
"message": "Errore apertura journal PEL: …"
}
Chiusura giornaliera
POST /api/pem/{serial_number}/fiscale/invio/chiusura
Scope richiesto ai client partner: fiscale:manage.
Chiude la giornata fiscale: scrive il blocco di chiusura del Journal e accoda
l'invio firmato al PEL, che trasmette i corrispettivi all'AdE. La risposta
arriva subito: l'esito si segue con Storico chiusure (inviato_il) e con le
richieste di tipo CORRISPETTIVI. Se ci sono DC appena emessi ancora in invio al
PEL la risposta è 409 JN005: riprovare dopo qualche istante. Una giornata
aperta da 23 ore viene chiusa in automatico.
Parametri di percorso
| Nome | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
serial_number |
string |
sì | Il seriale del PEM. Esempio: ASVS-241232. |
Risposte
200— success
{
"success": true,
"message": "Chiusura in elaborazione"
}
401— Non autenticato
{
"message": "Non hai i permessi per accedere a questa risorsa.",
"error": "unauthenticated"
}
403— Non autorizzato
{
"success": false,
"message": "Richiesta non autorizzata"
}
404— Seriale inesistente o PEM non accessibile all'utente.
{
"success": false,
"message": "Il PEM specificato non è stato trovato."
}
409—