> Source: https://fiscallink.ro/documentation/api
> Referință API FiscalLink pentru fiscalizare programatică: endpoint-uri, parametri și exemple pentru emiterea bonurilor fiscale din orice aplicație.

# Documentație API

FiscalLink expune un API REST local pentru controlul imprimantei fiscale, tipărirea bonurilor și integrarea cu Shopify sau cu aplicații POS proprii.

## URL-uri de bază

API-ul este servit local de aplicația FiscalLink, iar toate endpoint-urile sunt prefixate cu `/api`. Porturile implicite: **65401** (HTTPS), **65400** (HTTP).

| Mediu | Adresă | Utilizare |
| --- | --- | --- |
| Securizat (HTTPS) | `https://localhost.fiscallink.ro:65401/api` | Recomandat pentru integrare normală |
| Local (HTTP) | `http://{ip-local}:65400/api` | Util în rețeaua locală, fără TLS |

## Format răspuns (API standard)

Majoritatea endpoint-urilor returnează un format standard:

Succes

```
{
  "StatusCode": 200,
  "Data": "<payload>"
}
```

Eroare

```
{
  "StatusCode": 400,
  "Message": "Descrierea erorii"
}
```

**Excepție:** Controller-ul Legacy (`POST /Receipt`) folosește un format diferit — vezi secțiunea dedicată.

## Coduri HTTP frecvente

-   `200` — Cererea a fost procesată cu succes.
-   `400` — Parametri invalizi, date lipsă sau validare respinsă de dispozitiv.
-   `404` — Resursa nu a fost găsită (ex: comandă Shopify inexistentă).
-   `424` — Dispozitivul nu răspunde sau nu este conectat.
-   `500` — Eroare internă neașteptată.

## Compatibilitate FiscalNet și Fisco

FiscalLink este compatibil cu API-urile FiscalNet și Fisco. Dacă aplicația ta folosește deja una dintre aceste integrări, poți migra fără schimbări majore de cod.

### FiscalNet

[Documentație FiscalNet →](https://driverfiscal.ro/wp-content/uploads/2024/04/Documentatie-FiscalNet.pdf)

### Fisco

[Documentație Fisco →](https://fisco.ro/manual-fisco/)

Comportamentul dispozitivului diferă între DATECS, Daisy și Tremol. Vezi [diferențele dintre tipurile de case de marcat](https://fiscallink.ro/documentation/cash-registers).

## Network Controller

Returnează adresele API la runtime. Util când integrarea trebuie să descopere unde ascultă FiscalLink.

GET

`/get-secure-api-address`

#### Obține adresa API securizată

Returnează adresa HTTPS completă a API-ului FiscalLink (inclusiv /api).

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "https://localhost.fiscallink.ro:65401/api"
}
```

Eroare

```
{
  "StatusCode": 500,
  "Message": "Eroare internă"
}
```

GET

`/get-local-api-address`

#### Obține adresa API locală

Returnează adresa HTTP completă a API-ului din rețeaua locală (inclusiv /api).

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "http://192.168.1.100:65400/api"
}
```

Eroare

```
{
  "StatusCode": 500,
  "Message": "Eroare internă"
}
```

## Device Communication — Bon nefiscal

Flux: deschide bon → tipărește text/elemente → închide sau anulează.

POST

`/open-non-fiscal-receipt`

#### Deschide un bon nefiscal

Deschide un bon nefiscal. După deschidere folosește print-non-fiscal-text pentru conținut, apoi close-non-fiscal-receipt sau cancel-non-fiscal-receipt.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Eroare

```
{
  "StatusCode": 424,
  "Message": "Dispozitivul nu răspunde"
}
```

Observații

-   • Nu necesită corp de cerere pe DATECS/Daisy.
-   • Pe Tremol sunt obligatorii OperatorCode și OperatorPassword (max 4 caractere, padded/truncate).
-   • Trebuie să existe un bon nefiscal deschis pentru print/close/cancel.

POST

`/print-non-fiscal-text`

#### Tipărește text pe bon nefiscal

Tipărește o linie de text pe bonul nefiscal deschis. DATECS folosește toate opțiunile de formatare; Daisy și Tremol folosesc doar message.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| Message | String | Da | Text de tipărit |
| Bold | Bool? | Nu | Text îngroșat (DATECS) |
| Italic | Bool? | Nu | Text italic (DATECS) |
| Height | Int? | Nu | 0=Normal, 1=Dublu, 2=Jumătate (DATECS) |
| Underline | Bool? | Nu | Subliniat (DATECS) |
| Alignment | Int? | Nu | 0=Stânga, 1=Centru, 2=Dreapta (DATECS) |

Minimal (Daisy / Tremol-compatibil)

```
{
  "Message": "Text exemplu"
}
```

Complet (DATECS)

```
{
  "Message": "Text formatat",
  "Bold": true,
  "Italic": false,
  "Height": 0,
  "Underline": true,
  "Alignment": 1
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • alignment: 0=stânga, 1=centru, 2=dreapta.

POST

`/close-non-fiscal-receipt`

#### Închide bonul nefiscal

Închide bonul nefiscal deschis și finalizează tipărirea.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Nu necesită corp de cerere.

POST

`/cancel-non-fiscal-receipt`

#### Anulează bonul nefiscal

Anulează bonul nefiscal deschis fără a-l finaliza.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Nu necesită corp de cerere.

## Device Communication — Bon fiscal

Flux: deschide bon → înregistrează vânzări → subtotal → plată → închide. Vezi [diferențele DATECS vs Daisy vs Tremol](https://fiscallink.ro/documentation/cash-registers).

POST

`/open-fiscal-receipt`

#### Deschide un bon fiscal

Deschide un bon fiscal sau factură. Pe DATECS și Tremol, invoice=true deschide factură (pe Tremol câmpul este folosit ca FiscalRcpPrintType); pe Daisy câmpul invoice este ignorat. Pe Tremol, OperatorPassword este truncat/padded la exact 4 caractere.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| OperatorCode | Int | Da | 1–30 |
| OperatorPassword | String | Da | Parola operatorului |
| PointOfSaleNumber | Int | Da | 1–99999 |
| Invoice | Bool | Da | true=factură (DATECS și Tremol; ignorat pe Daisy) |

Bon fiscal (implicit)

```
{
  "OperatorCode": 1,
  "OperatorPassword": "0001",
  "PointOfSaleNumber": 1,
  "Invoice": false
}
```

Factură fiscală (DATECS / Tremol)

```
{
  "OperatorCode": 1,
  "OperatorPassword": "0001",
  "PointOfSaleNumber": 1,
  "Invoice": true
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

POST

`/print-fiscal-text`

#### Tipărește text pe bon fiscal

Tipărește o linie de text pe bonul fiscal deschis. Același corp de cerere ca print-non-fiscal-text: DATECS folosește toate opțiunile de formatare; Daisy și Tremol folosesc doar Message.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| Message | String | Da | Text de tipărit |
| Bold | Bool? | Nu | Text îngroșat (DATECS) |
| Italic | Bool? | Nu | Text italic (DATECS) |
| Height | Int? | Nu | 0=Normal, 1=Dublu, 2=Jumătate (DATECS) |
| Underline | Bool? | Nu | Subliniat (DATECS) |
| Alignment | Int? | Nu | 0=Stânga, 1=Centru, 2=Dreapta (DATECS) |

Minimal

```
{
  "Message": "CIF Client: RO12345678"
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Necesită un bon fiscal deschis.

POST

`/register-free-sale`

#### Înregistrează o vânzare liberă

Adaugă un articol pe bon fără PLU predefinit. Suportat pe DATECS și Tremol; Daisy returnează 400 — folosește register-plu-sale.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| ProductName | String | Da | Max 72 caractere |
| TaxCode | Int | Da | 1–8 (VatA–VatH) |
| Price | Decimal | Da | Preț unitar (0–9.999.999,99) |
| Department | Int | Da | 0–99 |
| Unit | String | Da | Max 6 caractere (ex: buc, kg) |
| Void | Bool | Nu | true = storno ultimă vânzare |
| Quantity | Decimal? | Nu | Implicit 1; 0,01–999.999,999 |
| DiscountType | Int? | Nu | 0=None, 1=Majorare Procentuală, 2=Reducere Procentuală, 3=Majorare Fixă, 4=Reducere Fixă |
| DiscountValue | Decimal? | Nu | Obligatoriu cu DiscountType ≠ 0 |

Vânzare simplă

```
{
  "ProductName": "Produs",
  "TaxCode": 1,
  "Price": 19.99,
  "Department": 1,
  "Unit": "buc"
}
```

Cu cantitate și reducere

```
{
  "ProductName": "Cafea",
  "TaxCode": 1,
  "Price": 8.50,
  "Quantity": 2,
  "Department": 1,
  "Unit": "buc",
  "DiscountType": 2,
  "DiscountValue": 10
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Eroare

```
{
  "StatusCode": 400,
  "Message": "Daisy nu suportă vânzări libere; folosește register-plu-sale"
}
```

POST

`/register-plu-sale`

#### Înregistrează o vânzare prin PLU

Adaugă pe bon un articol existent în memoria dispozitivului (PLU). Funcționează pe ambele tipuri de case.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| PluNumber | Int | Da | PLU trebuie să existe în dispozitiv |
| Void | Bool | Nu | true = storno |
| Quantity | Decimal? | Nu | Implicit 1 |
| DiscountType | Int? | Nu | 0=None, 1=Majorare Procentuală, 2=Reducere Procentuală, 3=Majorare Fixă, 4=Reducere Fixă |
| DiscountValue | Decimal? | Nu | Cu DiscountType ≠ 0 |

Minimal

```
{
  "PluNumber": 1,
  "Quantity": 2
}
```

Cu reducere

```
{
  "PluNumber": 5,
  "Quantity": 1,
  "Void": false,
  "DiscountType": 2,
  "DiscountValue": 15
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • PLU trebuie programat în dispozitiv înainte.

POST

`/subtotal`

#### Trimite subtotalul

Calculează și trimite subtotalul pe dispozitiv. Opțional: tipărire, afișaj, discount/majorare.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| Print | Bool? | Nu | Tipărește subtotalul |
| Display | Bool? | Nu | Afișează pe ecran client |
| DiscountType | Int? | Nu | 0=None, 1=Majorare Procentuală, 2=Reducere Procentuală, 3=Majorare Fixă, 4=Reducere Fixă |
| DiscountValue | Decimal? | Nu | Cu DiscountType ≠ 0 |

Minimal (fără corp sau {} )

```
{}
```

Cu opțiuni

```
{
  "Print": true,
  "Display": true,
  "DiscountType": 2,
  "DiscountValue": 5
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

POST

`/payment`

#### Înregistrează plata

Înregistrează o plată pe bon. Pentru plăți non-cash suma trebuie să acopere exact totalul; restul este permis doar pentru cash.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| PaymentMode | Int | Da | Mod plată (definit de dispozitiv) |
| Amount | Decimal | Da | Suma |

Plată cash

```
{
  "PaymentMode": 0,
  "Amount": 100.00
}
```

Plată card (suma exactă)

```
{
  "PaymentMode": 1,
  "Amount": 47.50
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

POST

`/close-fiscal-receipt`

#### Închide bonul fiscal

Finalizează bonul fiscal după înregistrarea articolelor și plăților.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Nu necesită corp de cerere.

POST

`/cancel-fiscal-receipt`

#### Anulează bonul fiscal

Anulează bonul fiscal deschis fără a-l finaliza.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Nu necesită corp de cerere.

POST

`/status-of-the-fiscal-transaction`

#### Statusul tranzacției fiscale

Returnează starea curentă a tranzacției fiscale de pe dispozitiv (bon deschis, sumă acumulată etc.).

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": { "<câmpuri răspuns dispozitiv>": "..." }
}
```

Observații

-   • Nu necesită corp de cerere.
-   • Data este un obiect structurat, nu string.

POST

`/copy-of-last-fiscal-receipt`

#### Copia ultimului bon fiscal

Tipărește o copie a ultimului bon fiscal emis.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": { "<câmpuri răspuns dispozitiv>": "..." }
}
```

Observații

-   • Nu necesită corp de cerere.
-   • Pe Tremol funcționează doar cu parametrul FD activat în firmware (service autorizat).

POST

`/report-z`

#### Tipărește raportul Z

Generează raportul fiscal Z, folosit pentru închiderea zilnică. Resetare date.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Nu necesită corp de cerere.

POST

`/report-x`

#### Tipărește raportul X

Generează raportul X, fără închidere fiscală.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Nu necesită corp de cerere.

GET

`/ask-for-z-report-structured-information/{number}`

#### Informații structurate raport Z

Returnează datele unui raport Z arhivat, în format structurat, după numărul raportului.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": { "<câmpuri raport Z>": "..." }
}
```

Observații

-   • {number} = numărul raportului Z cerut.

## Device Communication — Coduri de bare, linii și afișaj client

Comenzi pentru elemente individuale de tipărire și pentru afișajul de client al casei de marcat.

POST

`/print-bar-code`

#### Tipărește un cod de bare

Tipărește un cod de bare pe bonul deschis. Tipurile suportate diferă între DATECS și Daisy; Tremol nu suportă coduri de bare.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| Type | Int | Da | 1=EAN8, 2=EAN13, 3=Code128, 4=QRCode (DATECS), 5=Standard2Of5 (Daisy), 6=Interleaved2Of5, 7–16 = alte tipuri (vezi diferențele pe case) |
| Data | String | Da | Conținutul codului de bare |
| QrSize | Int? | Nu | Dimensiune QR (DATECS) |
| Position | Int? | Nu | Poziția codului |
| Scale | Int? | Nu | Scalare |
| Height | Int? | Nu | Înălțime |
| PrintText | Bool? | Nu | Tipărește și textul codului |

EAN13

```
{
  "Type": 2,
  "Data": "5940000000820"
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Pe Tremol returnează NotSupportedException.
-   • Vezi tabelul de tipuri suportate per casă în diferențele dintre case de marcat.

POST

`/print-separating-line/{type}`

#### Tipărește o linie de separare

Tipărește o linie de separare pe bonul deschis. {type} acceptă valorile 1–4 (stiluri diferite: -, =, \*, - -); alte valori returnează 400.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Eroare

```
{
  "StatusCode": 400,
  "Message": "Tip de linie de separare invalid"
}
```

Observații

-   • Nu necesită corp de cerere — tipul se transmite în URL.

POST

`/display-line-one`

#### Afișează text pe linia 1 a afișajului client

Trimite text pe prima linie a afișajului de client al casei de marcat.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| Text | String | Da | Textul afișat (pe Tremol exact 20 caractere — padded/truncat) |

Exemplu

```
{
  "Text": "Bun venit!"
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

POST

`/display-line-two`

#### Afișează text pe linia 2 a afișajului client

Trimite text pe a doua linie a afișajului de client.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| Text | String | Da | Textul afișat (pe Tremol exact 20 caractere — padded/truncat) |

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

POST

`/clear-display`

#### Golește afișajul client

Șterge conținutul afișajului de client.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Nu necesită corp de cerere.

## Printare bon complet (o singură cerere)

Trimite întregul bon într-un singur apel. FiscalLink execută intern: deschidere, articole, subtotal, plăți, închidere.

POST

`/print-fiscal-receipt`

#### Tipărește un bon fiscal complet

Primește toate datele bonului și execută fluxul complet. openFiscalReceipt, subtotal și payments sunt opționale; dacă payments lipsește, se folosește plata automată.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| OpenFiscalReceipt | Object? | Nu | Parametri deschidere (opțional) |
| ReceiptItems | ReceiptItem\[\] | Da | Articole: Type 0=FreeSale, 1=PluSale, 2=Text, 3=BarCode, 4=SeparatingLine |
| Subtotal | Object? | Nu | Subtotal cu opțiuni |
| Payments | RegisterPayment\[\]? | Nu | Listă plăți; dacă lipsește = plată automată |

Bon simplu (articole + plată automată)

```
{
  "ReceiptItems": [
    {
      "Type": 0,
      "FreeSale": {
        "ProductName": "Cafea",
        "TaxCode": 1,
        "Price": 5.00,
        "Department": 1,
        "Unit": "buc"
      }
    },
    {
      "Type": 0,
      "FreeSale": {
        "ProductName": "Pâine",
        "TaxCode": 1,
        "Price": 2.50,
        "Quantity": 2,
        "Department": 1,
        "Unit": "buc"
      }
    }
  ]
}
```

Bon complet cu toate tipurile de articole

```
{
  "OpenFiscalReceipt": {
    "OperatorCode": 1,
    "OperatorPassword": "0001",
    "PointOfSaleNumber": 1,
    "Invoice": false
  },
  "ReceiptItems": [
    {
      "Type": 2,
      "Text": {
        "Message": "CIF Client: RO12345678",
        "Alignment": 1
      }
    },
    {
      "Type": 0,
      "FreeSale": {
        "ProductName": "Produs",
        "TaxCode": 1,
        "Price": 10.00,
        "Department": 1,
        "Unit": "buc"
      }
    },
    {
      "Type": 4,
      "SeparatingLineType": 2
    }
  ],
  "Subtotal": { "Print": true },
  "Payments": [
    { "PaymentMode": 0, "Amount": 10.00 }
  ]
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • ReceiptItem: type 0=FreeSale (freeSale), 1=PluSale (pluSale), 2=Text (text), 3=BarCode (barCode), 4=SeparatingLine (separatingLineType 1–4).
-   • Pe Daisy, FreeSale nu este suportat în receiptItems.
-   • Pe Tremol, BarCode nu este suportat în receiptItems (returnează NotSupportedException).

POST

`/print-non-fiscal-receipt`

#### Tipărește un bon nefiscal complet

Primește toate elementele unui bon nefiscal și le tipărește într-un singur apel. receiptItems: type 0=Text, 1=BarCode, 2=SeparatingLine.

Corp cerere

| Câmp | Tip | Obligatoriu | Descriere |
| --- | --- | --- | --- |
| ReceiptItems | NonFiscalReceiptItem\[\] | Da | Type 0=Text, 1=BarCode, 2=SeparatingLine |

Text + linie + cod de bare

```
{
  "ReceiptItems": [
    {
      "Type": 0,
      "Text": {
        "Message": "BON NEFISCAL",
        "Bold": true,
        "Alignment": 1
      }
    },
    {
      "Type": 2,
      "SeparatingLineType": 1
    },
    {
      "Type": 1,
      "BarCode": {
        "Type": 2,
        "Data": "5940000000820"
      }
    }
  ]
}
```

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Observații

-   • Pe Tremol, BarCode nu este suportat (returnează NotSupportedException).

## Shopify Controller

Endpoint-urile Shopify sunt apelate de componentele FiscalLink din Shopify POS, care trimit automat un token de sesiune Shopify în antetul `Authorization: Bearer`. Nu este necesară nicio configurare de credențiale. Vezi [ghidul Shopify](https://fiscallink.ro/documentation/shopify).

GET

`/get-shopify-order/{orderId}`

#### Preia o comandă Shopify

Returnează detaliile complete ale unei comenzi Shopify (line items, discounturi, transport, tranzacții). orderId este numeric (ex: 123456789), fără prefixe gid://.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": {
    "id": "gid://shopify/Order/123456789",
    "legacyResourceId": "123456789",
    "name": "#1001",
    "totalPriceSet": { "shopMoney": { "amount": "99.99", "currencyCode": "RON" } },
    "totalDiscountsSet": { "shopMoney": { "amount": "0.00", "currencyCode": "RON" } },
    "note": null,
    "lineItems": {
      "edges": [
        {
          "node": {
            "id": "gid://shopify/LineItem/123",
            "title": "Produs exemplu",
            "quantity": 2,
            "originalUnitPriceSet": { "shopMoney": { "amount": "25.00", "currencyCode": "RON" } },
            "discountedUnitPriceSet": { "shopMoney": { "amount": "22.50", "currencyCode": "RON" } },
            "taxLines": [],
            "discountAllocations": []
          }
        }
      ]
    },
    "transactions": [
      { "gateway": "manual", "amount": "45.00", "kind": "SALE" }
    ],
    "discountApplications": { "edges": [] },
    "shippingLines": {
      "edges": [
        {
          "node": {
            "id": "gid://shopify/ShippingLine/1",
            "title": "Standard",
            "originalPriceSet": { "shopMoney": { "amount": "15.00", "currencyCode": "RON" } },
            "discountedPriceSet": { "shopMoney": { "amount": "0.00", "currencyCode": "RON" } },
            "discountAllocations": []
          }
        }
      ]
    }
  }
}
```

Eroare 401 — Token de sesiune lipsă

```
{
  "StatusCode": 401,
  "Message": "Token-ul de sesiune Shopify lipsește. Actualizați aplicația FiscalLink în Shopify POS și încercați din nou."
}
```

Eroare 401/403 — Cerere respinsă de Shopify

```
{
  "StatusCode": 401,
  "Message": "Shopify a respins cererea. Asigurați-vă că aplicația FiscalLink este instalată pe magazinul dvs."
}
```

Eroare 404 — Comandă inexistentă

```
{
  "StatusCode": 404,
  "Message": "Order not found"
}
```

POST

`/print-shopify-order/{orderId}`

#### Tipărește o comandă Shopify

Preia comanda din Shopify și o tipărește automat ca bon fiscal pe dispozitivul conectat.

Răspuns

Succes

```
{
  "StatusCode": 200,
  "Data": "<răspuns dispozitiv>"
}
```

Eroare 400 — Configurare sau date invalide

```
{
  "StatusCode": 400,
  "Message": "Invalid order data"
}
```

Eroare 404 — Comandă inexistentă

```
{
  "StatusCode": 404,
  "Message": "Order not found"
}
```

Eroare 424 — Dispozitiv deconectat

```
{
  "StatusCode": 424,
  "Message": "Device communication failure"
}
```

## Legacy Controller (POST /Receipt)

Endpoint compatibil FiscalNet/Fisco. Acceptă array de stringuri în format FiscalNet (^) sau INP (;,). Formatul este detectat automat. Returnează un format diferit de restul API-ului.

POST

`/Receipt`

#### Tipărește bon în format FiscalNet sau INP

Primește un array de comenzi în format legacy. FiscalNet folosește ^ ca delimitator; INP folosește , și ;. Vezi documentația FiscalNet/Fisco pentru comenzi.

Corp cerere

FiscalNet (exemplu)

```
[
  "CF^RO12345678",
  "S^Produs^1000^1000^pcs^1^1",
  "ST^",
  "P^1^1000"
]
```

INP (exemplu)

```
[
  "S,1,______,_,__;Produs;10.00;1.000;1;1;2;0;0;pcs",
  "T,1,______,_,__;0;10.00;;;;"
]
```

Răspuns

Succes

```
{
  "ReceiptStatus": "true",
  "ReceiptNumber": "12345",
  "ErrorCode": "",
  "ErrorInfo": ""
}
```

Eroare

```
{
  "ReceiptStatus": "false",
  "ReceiptNumber": "",
  "ErrorCode": "123",
  "ErrorInfo": "Descrierea erorii"
}
```

Observații

-   • Răspuns diferit de API standard: receiptStatus, receiptNumber, errorCode, errorInfo.
-   • HTTP 200 chiar și la eroare; succes/eroare se citesc din receiptStatus.
-   • Comenzi comune: CF (CIF), S (Sale), ST (Subtotal), P (Payment), X^ (Report X), Z^ (Report Z).

## Fluxuri uzuale

#### Bon nefiscal

1.  POST /open-non-fiscal-receipt
2.  POST /print-non-fiscal-text (repetat)
3.  POST /close-non-fiscal-receipt (sau /cancel-non-fiscal-receipt pentru anulare)

#### Bon fiscal

1.  POST /open-fiscal-receipt
2.  POST /register-free-sale sau /register-plu-sale
3.  POST /subtotal
4.  POST /payment
5.  POST /close-fiscal-receipt (sau /cancel-fiscal-receipt pentru anulare)

## Securitate

-   Folosește endpoint-ul HTTPS pentru integrarea standard, atunci când este posibil.
-   API-ul local HTTP este accesibil doar în rețeaua locală și nu folosește TLS.
-   Datele de intrare sunt validate înainte de comunicarea cu dispozitivul.

Pentru asistență: [support@fiscallink.ro](mailto:support@fiscallink.ro)
