Croatia (FINA)
Full support for Croatian B2C fiscalization requirements (FINA).
Prerequisites
| Requirement | Description |
|---|---|
| OIB | Entity with Croatian OIB (tax number) |
| Certificate | Digital certificate (.p12) from FINA |
Scope
| Transaction | Status |
|---|---|
| B2C domestic | Fiscalized via FINA |
| B2B foreign | Allowed, no fiscalization |
| B2B domestic, paid in cash or by card | Fiscalized via FINA with the buyer’s OIB |
| B2B domestic, other payment methods | Not supported (requires an eRačun under Fiskalizacija 2.0) |
Setup
1. Upload Certificate
import fs from "node:fs";
import SpaceInvoices from "@spaceinvoices/js-sdk/sdk";
const sdk = new SpaceInvoices("YOUR_API_KEY");
const file = new File([new Uint8Array(fs.readFileSync("certificate.p12"))], "certificate.p12", {
type: "application/x-pkcs12",
});
await sdk.finaCertificate.uploadFinaCertificate({
file,
passphrase: "cert-password",
});2. Register Business Premise
Register your business location with a unique premise ID. This creates the premise and registers it with FINA.
const _premise = await sdk.finaPremises.create({
business_premise_name: "OFFICE1",
});If your FINA numbering sequence is per premise (P), you can pass starting_number when creating the premise. The first fiscal invoice for that premise sequence uses that value.
3. Register Electronic Device
Register a device for the premise. Device IDs are numeric (e.g., 1, 2, 3).
await sdk.finaDevices.registerFinaDevice("prm_123", { electronic_device_name: "1" });If your FINA numbering sequence is per device (N), you can pass starting_number when registering the device.
You can change or clear a premise or device starting number with the PATCH endpoints until a fiscal document counter exists for that sequence. With unified numbering, invoices for foreign customers share the same sequence, so the starting number applies to them too.
4. Enable FINA
await sdk.finaSettings.update({ enabled: true });Fiscalized Invoices
Invoices are automatically fiscalized when FINA is enabled:
const _invoice = await sdk.invoices.create({
items: [{ name: "Service", quantity: 1, price: 100 }],
fina: {
business_premise_name: "OFFICE1",
electronic_device_name: "1",
},
});FINA returns confirmation data on the invoice:
jirzkiDomestic B2B
A domestic B2B invoice (a Croatian customer with a tax_number, and is_end_consumer not set to true) is fiscalized like any other invoice when it is paid in cash or by card. Space Invoices sends the customer’s OIB to FINA with the invoice, so the customer’s tax_number must be a valid Croatian OIB (11 digits, with or without the HR prefix).
A domestic B2B invoice is fiscalized only when the create or finalize request carries exactly one payment, of type cash or card, that covers the full document total. For a draft, the payments saved on the draft are checked when it is finalized. If you also send fina.payment_type, it must name the same method as that payment.
A paid order from an order integration is fiscalized the same way when its payment is a single cash or card transaction for the full order total that matches the integration’s payment type; the payment is recorded together with the invoice. An invoice can also be settled by linked advance invoices. Every linked advance invoice must be fiscalized with the same customer OIB and paid with the same method, cash or card. The invoice is then fiscalized with that method, and the advances can be completed by one more payment of that method so that together they cover the full total.
These cases are rejected with a 422 error, because they require an eRačun, which is not supported yet:
- Bank transfer, another method, several payments, or a payment that does not cover the whole total.
fina.payment_typewithout a payment row or linked advance invoices.- Unpaid orders, orders paid with several transactions, partially, or by bank transfer, and invoices whose linked advance invoices are not fiscalized, were issued to another OIB or to a consumer, or were paid with a different method than the rest of the invoice.
Set is_end_consumer to true if the customer is a consumer; the invoice is then fiscalized as B2C and no customer OIB is sent.
Once an invoice, credit note or advance invoice has been fiscalized with the customer’s OIB, its payment is fixed. Adding another payment or advance invoice, deleting the payment, changing the amount of the payment, or changing the payment method of any of its payments is rejected with a 422 error; issue a credit note instead. The error’s cause.code is fina_b2b_payment_type_not_allowed.
Changing the buyer OIB
If a fiscalized invoice went out with the wrong buyer OIB, with an OIB it should not have had, or without one it needed, correct it with POST /invoices/{id}/change-buyer-oib. This reports the change to CIS (promijeniPodatkeRacuna) and updates the tax_number on the invoice’s customer snapshot. The saved customer is not changed.
curl -X POST "https://eu.spaceinvoices.com/invoices/$INVOICE_ID/change-buyer-oib" \ -H "Authorization: Bearer $API_KEY" \ -H "x-entity-id: $ENTITY_ID" \ -H "Content-Type: application/json" \ -d '{ "fina": { "buyer_oib": "12345678903" } }'fina.buyer_oib is required. Send an OIB (11 digits, the HR prefix is accepted) to set it, or null to remove it; omitting the key (or fina) is a validation error, not a removal. The response is the updated invoice. The OIB CIS currently holds is always returned in fina.data.buyer_oib (a string, or null when the invoice has none) for an invoice with a retained CIS record; the originally fiscalized record in fina.data.cis_record is never rewritten.
CIS accepts this only on the day the invoice was issued, before midnight in Europe/Zagreb. After that, issue a credit note and a corrected invoice. The last accepted change wins, and sending the OIB the invoice already carries answers 200 without contacting CIS.
A buyer OIB is only valid on a business invoice settled by exactly one cash or card payment covering the full total; once set, the invoice is protected like any other buyer-OIB invoice. Removing the OIB turns it back into a consumer invoice.
These cases are rejected with a 422 error and a cause.code:
fina_buyer_oib_invalid: the OIB is not 11 digits with a valid check digit.fina_payment_change_window_expired: the issue day has passed.fina_b2b_payment_type_not_allowed: the invoice is not settled by exactly one full cash or card payment that matches the payment method reported to CIS.fina_buyer_oib_not_allowed: the customer is a consumer (is_end_consumer) or not Croatian.fina_buyer_oib_change_unavailable: the entity is not Croatian or FINA is off, or the document is a draft, voided, or not accepted by CIS.fina_cis_record_unavailable: the invoice was fiscalized before its CIS record was retained.fiscalization_provider_error: CIS refused the change; nothing was changed.
If CIS cannot be reached the request returns 503 with cause.code fina_unreachable. CIS may still have received the change, so repeat the same request; until it is confirmed, any other change to the invoice’s payment data (including a payment-method change) is refused with 409 fina_payment_change_unconfirmed. A 500 with fina_payment_change_unrecorded means CIS accepted the change but it could not be saved; repeat the same request.
QR Code
Fiscalized invoices include a verification QR code linking to the Croatian tax authority, embedded automatically in the PDF:
const _pdf = await sdk.invoices.renderPdf(invoice.id);