Passa al contenuto principale

Guida all'utilizzo

Prerequisito

Assicurati di aver configurato un bridge NoPos nell'app con protocollo NoPos e di avere l'IP locale della cassa. Vedi Introduzione.

GET /status

Verifica che il server sia raggiungibile e controlla quali provider sono configurati.

Request

curl http://192.168.1.100:5200/status

Response

{
"success": true,
"data": {
"version": "NOPOS/1.0",
"payment": true,
"fiscal": true
}
}
CampoTipoDescrizione
versionstringVersione del protocollo
paymentbooleanProvider di pagamento configurato
fiscalbooleanProvider fiscale configurato

POST /payments

Avvia un pagamento sul terminale configurato nel bridge.

Request body

{
"amount": 25.50,
"currency": "EUR",
"description": "Ordine #1234"
}
CampoTipoObbligatorioDescrizione
amountnumberImporto in euro (es. 25.50)
currencystringValuta ISO 4217. Default: EUR
descriptionstringDescrizione visibile sul terminale
providerstringOverride del provider configurato nel bridge
terminalIdstringOverride del terminale configurato nel bridge

Response

{
"success": true,
"data": {
"id": "tx_abc123",
"status": "completed",
"amount": 25.50,
"currency": "EUR"
}
}
CampoTipoDescrizione
idstringID della transazione
statusstringpending · completed · failed · canceled · verification
amountnumberImporto confermato
currencystringValuta
Status del pagamento

Il server risponde solo quando il pagamento ha raggiunto uno stato finale. Non è necessario fare polling: la risposta arriva quando l'utente ha interagito con il terminale.

const response = await fetch('http://192.168.1.100:5200/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 25.50,
currency: 'EUR',
description: 'Ordine #1234'
})
});

const { success, data, error } = await response.json();

if (!success) {
console.error('Pagamento fallito:', error);
} else {
console.log('Transazione:', data.id, '—', data.status);
}

POST /payments/refund

Rimborsa una transazione precedente, in tutto o in parte.

Request body

{
"transactionId": "tx_abc123",
"amount": 10.00
}
CampoTipoObbligatorioDescrizione
transactionIdstringID della transazione originale
amountnumberImporto da rimborsare. Se assente, rimborso totale
providerstringOverride del provider

Response — stessa shape di /payments.


POST /receipts

Emette uno scontrino fiscale tramite il provider fiscale configurato nel bridge.

Request body

{
"type": "sale",
"items": [
{
"description": "Pizza Margherita",
"quantity": 2,
"price": 8.50,
"vat": "22"
},
{
"description": "Acqua naturale",
"quantity": 1,
"price": 2.00,
"vat": "22"
}
],
"payment": {
"cash": 19.00
}
}

Campi type disponibili

ValoreDescrizione
saleVendita normale
returnAnnullo documento (reso)
refundRimborso parziale

Per return e refund passa original con l'ID dello scontrino da annullare.

Campi items

CampoTipoObbligatorioDescrizione
descriptionstringDescrizione del prodotto
quantitynumberQuantità
pricenumberPrezzo unitario in euro
vatstringAliquota IVA. Valori: 4 · 5 · 10 · 22 · N4 (esente) · N2 (non soggetto) · ecc.
discountnumberSconto sull'articolo in euro
giftbooleanArticolo omaggio (prezzo = 0 in scontrino)

Campi payment

CampoTipoDescrizione
cashnumberImporto pagato in contanti
electronicnumberImporto pagato con carta/POS
ticketnumberImporto pagato con buoni pasto
ticketCountnumberNumero di buoni pasto
discountnumberSconto applicato al totale
creditnumberImporto a credito

Altri campi del body

CampoTipoDescrizione
lotterystringCodice lotteria scontrini
originalstringID scontrino originale (per return / refund)
providerstringOverride del provider fiscale

Response

{
"success": true,
"data": {
"id": "rec_xyz789",
"status": "completed",
"number": "2026-0042",
"amount": 19.00
}
}
CampoTipoDescrizione
idstringID del documento nel provider fiscale
statusstringpending · completed · failed · canceled
numberstringNumero progressivo del documento (se disponibile)
amountnumberImporto totale del documento
const response = await fetch('http://192.168.1.100:5200/receipts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'sale',
items: [
{ description: 'Pizza Margherita', quantity: 2, price: 8.50, vat: '22' },
{ description: 'Acqua naturale', quantity: 1, price: 2.00, vat: '22' },
],
payment: { cash: 19.00 }
})
});

const { success, data, error } = await response.json();

if (!success) {
console.error('Scontrino fallito:', error);
} else {
console.log('Scontrino n.', data.number, '— importo €', data.amount);
}

POST /invoices

Emette una fattura elettronica tramite il provider fiscale configurato.

Request body

{
"type": "TD01",
"regime": "RF01",
"items": [
{
"description": "Consulenza sviluppo software",
"quantity": 8,
"price": 120.00,
"vat": "22.00"
}
],
"customer": {
"vatId": "IT12345678901",
"name": "Acme S.r.l.",
"pec": "acme@pec.it",
"address": {
"street": "Via Roma",
"number": "1",
"postal": "20100",
"city": "Milano",
"state": "MI",
"country": "IT"
}
},
"payment": {
"electronic": 1171.20
}
}

Campi type — tipo documento SDI (principali)

ValoreDescrizione
TD01Fattura
TD04Nota di credito
TD05Nota di debito
TD06Parcella

Campi regime — regime fiscale (principali)

ValoreDescrizione
RF01Ordinario
RF19Forfettario (L. 190/2014)

Campi items

CampoTipoObbligatorioDescrizione
descriptionstringDescrizione
quantitynumberQuantità
pricenumberPrezzo unitario
vatstringAliquota IVA con due decimali: 22.00 · 10.00 · 4.00 · 0.00

Campi customer

CampoTipoObbligatorioDescrizione
vatIdstringPartita IVA o Codice Fiscale
namestringDenominazione (azienda)
firstNamestringNome (persona fisica)
lastNamestringCognome (persona fisica)
pecstringIndirizzo PEC
sdistringCodice SDI (se assente, viene usata la PEC)
addressobjectIndirizzo completo

Response

{
"success": true,
"data": {
"id": "inv_def456",
"status": "pending",
"number": "2026/0015",
"amount": 1171.20
}
}
Status fattura

Le fatture elettroniche passano per lo SDI e possono rimanere in stato pending per alcuni minuti prima di diventare completed. Implementa il polling su /v1/fiscal/:providerId/invoices/:id tramite API NoPos se hai bisogno di tracciare il completamento.


Gestione degli errori

Ogni risposta con success: false include un campo error leggibile:

{
"success": false,
"error": "Pagamento non completato dal terminale"
}

Errori HTTP

CodiceSituazione
400Campi obbligatori mancanti nel body
404Route non esistente
500Errore interno (provider non raggiungibile, timeout, ecc.)

Pattern consigliato

async function noposRequest(ip, path, body = null) {
const url = `http://${ip}:5200${path}`;
const options = {
method: body ? 'POST' : 'GET',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
...(body ? { body: JSON.stringify(body) } : {}),
};

const res = await fetch(url, options);
const envelope = await res.json();

if (!envelope.success) throw new Error(envelope.error);
return envelope.data;
}

// Utilizzo
const tx = await noposRequest('192.168.1.100', '/payments', { amount: 15.00 });
const rec = await noposRequest('192.168.1.100', '/receipts', {
type: 'sale',
items: [{ description: 'Caffè', quantity: 1, price: 1.50, vat: '22' }],
payment: { cash: 2.00 },
});