Публічне API 4invoices передає дані про рахунки з вашої системи до 4invoices і проводить рахунок до кінця в національну систему електронного виставлення рахунків (у Румунії — SPV ANAF). Один продакшн-хост, один потік client_credentials, ідемпотентні фіскальні записи та однаковий конверт помилки на всіх маршрутах.
https://api.4invoices.net/v1 · Специфікація OpenAPI (без ключа)
Що таке API 4invoices
- Публічний API 4invoices — це REST через HTTPS, з JSON на вході та JSON на виході.
- Один продакшн-хост: https://api.4invoices.net/v1. Окремого тестового хоста немає.
- Специфікація OpenAPI 3.1 публічна й не потребує ключа — імпортуйте її безпосередньо в Postman або в генератор клієнтів.
- Кожна відповідь містить заголовок X-Request-Id; вказуйте його, коли звертаєтеся до підтримки.
- Кожен фіскальний запис ідемпотентний: повторна спроба після таймаут ніколи не створює другого документа.
- Повний румунський цикл обміну з ANAF e-Factura через API: попередня перевірка, подання, відстеження, підписана відповідь і вхідна скринька. Жоден румунський конкурент цього не пропонує.
- SmartBill не має жодного ендпоінта для подання в національну систему електронного виставлення рахунків (ANAF, у Румунії) — надсилання в SPV є налаштуванням акаунта лише в інтерфейсі — і взагалі не має ендпоінта для списку рахунків.
- Oblio може створювати клієнтів і товари лише як побічний ефект випуску документа, а не як самостійні ресурси.
- Генерація XML UBL (у Румунії — CIUS-RO) без подання: ви отримуєте юридичний документ як файл, не торкаючись національної системи електронного виставлення рахунків.
- Ідемпотентність фіскальних записів: повторна спроба після таймаут не створює другого рахунку й не витрачає другого номера.
- Вхідна скринька рахунків від постачальників, доступна для програмного читання, — основа для автоматичної звірки.
Перший рахунок за 6 кроків
- Згенеруйте облікові дані в панелі, у Виставлення рахунків → Налаштування → Доступ до API, і скопіюйте client_secret — його показують лише один раз.
- Заповніть профіль компанії та активуйте щонайменше одну серію типу fiscale, інакше виставлення поверне issuer_profile_incomplete або no_series_configured.
- Згенеруйте облікові дані в панелі, у Виставлення рахунків → Налаштування → Доступ до API, і скопіюйте client_secret — його показують лише один раз.
- Заповніть профіль компанії та активуйте щонайменше одну серію типу fiscale, інакше виставлення поверне issuer_profile_incomplete або no_series_configured.
- Обміняйте облікові дані на токен: POST /v1/auth/token із grant_type client_credentials. Токен живе одну годину — кешуйте його, не беріть новий на кожен запит.
- Виставте рахунок: POST /v1/invoices із заголовком Idempotency-Key і vat_rate у відсотках (21, а не 0.21).
- Виконайте передперевірку (у Румунії — CIUS-RO) через POST /v1/invoices/{id}/efactura/validate, а потім надішліть рахунок до національної системи електронного виставлення рахунків (у Румунії — ANAF) через POST /v1/invoices/{id}/efactura/submit.
- Стежте за станом через GET /v1/efactura/submissions/{id}, доки він не стане accepted або rejected.
bash
# 1 — токен (1 година, зберігайте в кеші)
ACCESS_TOKEN=$(curl -sS -X POST https://api.4invoices.net/v1/auth/token \
-H 'Content-Type: application/json' \
-d '{"grant_type":"client_credentials","client_id":"cli_XXX","client_secret":"sec_XXX"}' \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')
# 2 — виставте рахунок (Idempotency-Key ОБОВ'ЯЗКОВИЙ)
curl -sS -X POST https://api.4invoices.net/v1/invoices \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-10457-invoice' \
-d '{"buyer":{"name":"Exemplu Comert SRL","tax_id":"RO12345678","county":"Cluj","city":"Cluj-Napoca","country":"RO"},
"lines":[{"description":"Abonament SaaS","quantity":1,"unit_price":400,"vat_rate":21}]}'
# 3 — preflight CIUS-RO, then send to ANAF
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/validate \
-H "Authorization: Bearer $ACCESS_TOKEN"
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/submit \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Idempotency-Key: efactura-inv_01J7ABC-1'javascript
const BASE = "https://api.4invoices.net/v1";
const token = await fetch(`${BASE}/auth/token`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "client_credentials",
client_id: process.env.FOURINVOICES_CLIENT_ID,
client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
}),
}).then((r) => r.json()).then((d) => d.access_token);
const invoice = await fetch(`${BASE}/invoices`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
"Idempotency-Key": `order-${orderId}-invoice`,
},
body: JSON.stringify({
buyer: { name: "Exemplu Comert SRL", tax_id: "RO12345678", county: "Cluj", city: "Cluj-Napoca", country: "RO" },
lines: [{ description: "Abonament SaaS", quantity: 1, unit_price: 400, vat_rate: 21 }],
currency: "RON",
metadata: { order_id: String(orderId) },
}),
}).then((r) => r.json());
console.log(invoice.number, invoice.totals); // "FCT-000123" { net, vat, gross }python
import os, uuid, requests
BASE = "https://api.4invoices.net/v1"
token = requests.post(f"{BASE}/auth/token", json={
"grant_type": "client_credentials",
"client_id": os.environ["FOURINVOICES_CLIENT_ID"],
"client_secret": os.environ["FOURINVOICES_CLIENT_SECRET"],
}, timeout=30).json()["access_token"]
headers = {
"Authorization": f"Bearer {token}",
# Один ключ на ЛОГІЧНУ операцію — повторно використовуйте його при спробі, ніколи не генеруйте заново.
"Idempotency-Key": f"order-{order_id}-invoice",
}
invoice = requests.post(f"{BASE}/invoices", headers=headers, json={
"buyer": {"name": "Exemplu Comert SRL", "tax_id": "RO12345678",
"county": "Cluj", "city": "Cluj-Napoca", "country": "RO"},
"lines": [{"description": "Abonament SaaS", "quantity": 1,
"unit_price": 400, "vat_rate": 21}], # відсоток, а не 0.21
"currency": "RON",
}, timeout=60).json()
print(invoice["number"], invoice["totals"])Автентифікація
- Потік — client_credentials: ви обмінюєте client_id + client_secret на Bearer access_token.
- Токен спливає через 3600 секунд. Оновлюйте його до завершення строку дії, а не під час кожного виклику — POST /auth/token має власний ліміт на IP.
- client_secret зберігається лише як хеш і не може бути відновлений. Якщо ви його втратите, створіть нові облікові дані й відкличте старі.
- Лише сервер-до-сервер. Через CORS не допускається жоден браузер origin: із JavaScript на сторінці секрет потрапив би до відвідувача.
- Області надаються для кожного набору облікових даних окремо. Створюйте окремі облікові дані для кожної системи й давайте кожній лише мінімально потрібні області.
Виставлення рахунків → Налаштування → Доступ до API
bash
curl -sS -X POST https://api.4invoices.net/v1/auth/token \
-H 'Content-Type: application/json' \
-d '{
"grant_type": "client_credentials",
"client_id": "cli_XXXXXXXXXXXX",
"client_secret": "sec_XXXXXXXXXXXXXXXXXXXX"
}'
# → {"access_token":"eyJ...","token_type":"Bearer","expires_in":3600,
# "scope":"invoices:read invoices:write efactura:submit"}javascript
// Зберігайте токен у кеші; не запитуйте новий на кожен запит.
let cached = { token: "", expiresAt: 0 };
async function getToken() {
if (cached.token && Date.now() < cached.expiresAt - 60_000) return cached.token;
const res = await fetch("https://api.4invoices.net/v1/auth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "client_credentials",
client_id: process.env.FOURINVOICES_CLIENT_ID,
client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
}),
});
if (!res.ok) throw new Error(`token ${res.status}`);
const data = await res.json();
cached = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
return cached.token;
}Ставки ПДВ — це відсотки
vat_rate: 21 ✓ · vat_rate: 0.19 ✗ · vat_rate: 1 ✗- vat_rate — це ВІДСОТОК: 21 означає 21%.
- Значення в (0, 1] відхиляються — 0.19 є дробом, а 1 неоднозначне між 1% і 100%.
- 0 є допустимим і означає звільнення або зворотне оподаткування; зазначте юридичну підставу в нотатки.
- unit_price — це ЧИСТА ціна за одиницю, коли емітент є платником ПДВ.
- Потрібні підсумки до фіксації? POST /v1/invoices/preview-totals виконує ті самі розрахунки, не витрачаючи фіскальний номер.
Ідемпотентність фіскальних записів
- Заголовок Idempotency-Key є ОБОВ’ЯЗКОВИМ для POST /invoices, POST /invoices/{id}/storno і POST /invoices/{id}/efactura/submit.
- Ключі зберігаються 24 години. Повторне надсилання того самого ключа з тим самим тілом повертає початковий результат і встановлює Idempotency-Replayed: true.
- Той самий ключ з іншим тілом повертає 409 idempotency_key_reuse — уже випущений фіскальний документ ніколи не перезаписується.
- Один ключ на ЛОГІЧНУ операцію, а не на HTTP-спробу: order-10457-invoice, а не новий UUID під час кожної повторної спроби.
- Причина юридична, а не технічна: використаний фіскальний номер і рахунок, поданий у національну систему електронного виставлення рахунків (у Румунії — SPV), не можна відкликати.
bash
curl -sS -X POST https://api.4invoices.net/v1/invoices \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-10457-invoice' \
-d '{
"buyer": {
"name": "Exemplu Comert SRL",
"tax_id": "RO12345678",
"address": "Str. Fabricii 12",
"city": "Cluj-Napoca",
"county": "Cluj",
"country": "RO",
"email": "[email protected]"
},
"lines": [
{ "description": "Abonament SaaS, iulie", "quantity": 1, "unit_price": 400, "vat_rate": 21, "unit": "buc" },
{ "description": "Implementare", "quantity": 6, "unit_price": 250, "vat_rate": 21, "unit": "ora" }
],
"currency": "RON",
"document_kind": "factura",
"due_date": "2026-08-15",
"metadata": { "order_id": "10457" }
}'Усі ендпоїнти
| Метод | Ендпоїнт | Scope | Idempotency-Key | Запитів / хвилину |
|---|---|---|---|---|
| POST | /auth/token Обміняти облікові дані на токен доступу | — | — | 120 |
| GET | /me Тенант, scope-и та поточні ліміти | invoices:read | — | 120 |
| POST | /invoices Виписати рахунок або проформу | invoices:write | обов'язково | 30 |
| GET | /invoices Список рахунків (пагінація курсором) | invoices:read | — | 120 |
| POST | /invoices/preview-totals Розрахувати підсумки, нічого не створюючи | invoices:read | — | 120 |
| GET | /invoices/{invoice_id} Отримати один рахунок | invoices:read | — | 120 |
| GET | /invoices/{invoice_id}/pdf Завантажити PDF рахунку | invoices:read | — | 120 |
| GET | /invoices/{invoice_id}/xml Завантажити XML UBL (у Румунії — CIUS-RO) | invoices:read | — | 120 |
| POST | /invoices/{invoice_id}/storno Виписати кредитове авізо, що сторнує цей рахунок | invoices:write | обов'язково | 30 |
| POST | /invoices/{invoice_id}/payments Позначити рахунок як оплачений | invoices:write | — | 30 |
| DELETE | /invoices/{invoice_id}/payments Позначити рахунок як неоплачений | invoices:write | — | 30 |
| GET | /clients Список клієнтів | clients:read | — | 120 |
| POST | /clients Створити або оновити клієнта | clients:write | — | 30 |
| GET | /lookup/company/{tax_id} Перевірити CUI у реєстрі ANAF (Румунія) | clients:read | — | 120 |
| GET | /series Список серій нумерації | invoices:read | — | 120 |
| POST | /invoices/{invoice_id}/efactura/validate Передперевірка (у Румунії — CIUS-RO) — валідація без надсилання | efactura:read | — | 120 |
| POST | /invoices/{invoice_id}/efactura/submit Надіслати рахунок до національної системи електронного виставлення рахунків (у Румунії — ANAF/SPV) | efactura:submit | обов'язково | 10 |
| GET | /efactura/submissions Список подань до національної системи електронного виставлення рахунків | efactura:read | — | 120 |
| GET | /efactura/submissions/{submission_id} Отримати одне подання | efactura:read | — | 120 |
| POST | /efactura/submissions/{submission_id}/refresh Запит до національної системи електронного виставлення рахунків про поточний стан | efactura:read | — | 10 |
| GET | /efactura/submissions/{submission_id}/download Завантажити архів підписаної відповіді | efactura:read | — | 120 |
| GET | /efactura/inbox Вхідні рахунки постачальників, отримані через національну систему електронного виставлення рахунків | efactura:read | — | 120 |
| GET | /efactura/inbox/{inbound_id} Отримати один вхідний рахунок | efactura:read | — | 120 |
| GET | /efactura/inbox/{inbound_id}/download Завантажити архів вхідного рахунку | efactura:read | — | 120 |
| POST | /efactura/inbox/sync Отримати нові повідомлення національної системи електронного виставлення рахунків у вхідні | efactura:read | — | 10 |
25 endpoints · https://api.4invoices.net/v1/openapi.json
Scope-и
- invoices:read
- invoices:write
- clients:read
- clients:write
- efactura:read
- efactura:submit
Шлях до національної системи електронного виставлення рахунків
- Справжня відмінність: увесь цикл обміну з національною системою електронного виставлення рахунків (у Румунії — ANAF e-Factura) проходить через API, а не лише генерація документа.
- POST /invoices/{id}/efactura/validate виконує попередню перевірку (у Румунії — CIUS-RO) і повертає саме ті поля, які відхилила б національна система електронного виставлення рахунків, нічого не надсилаючи.
- GET /invoices/{id}/xml генерує XML у форматі UBL (у Румунії — CIUS-RO) без подання — корисно для власного архіву або внутрішнього аудиту.
- POST /invoices/{id}/efactura/submit подає рахунок у національну систему електронного виставлення рахунків (у Румунії — SPV). Це незворотно: другу копію того самого рахунку неможливо відкликати із системи.
- Життєвий цикл нормалізований: not_sent → валідація → у черзі → надіслано → обробка → accepted | rejected | помилка. accepted означає юридично передано; помилка — це збій транспорту на нашому боці, і повторна спроба безпечна.
- GET /efactura/submissions/{id}/download завантажує архів із підписаною відповіддю національної системи (у Румунії — ANAF).
- Є й вхідна сторона: POST /efactura/inbox/sync отримує нові повідомлення з національної системи електронного виставлення рахунків (у Румунії — SPV), а GET /efactura/inbox показує рахунки, які вам надіслали постачальники.
bash
# CIUS-RO preflight. Sends NOTHING to ANAF.
curl -sS -X POST "https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/validate?include_xml=true" \
-H "Authorization: Bearer $ACCESS_TOKEN"
# → {"invoice_id":"inv_01J7ABC","valid":false,
# "errors":["buyer.county is required for RO buyers"],
# "xml_base64":"PD94bWwg..."}bash
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/submit \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Idempotency-Key: efactura-inv_01J7ABC-1'
# → {"submission_id":"sub_01J7XYZ","status":"queued"}python
import time, requests
BASE = "https://api.4invoices.net/v1"
TERMINAL = {"accepted", "rejected"}
H = {"Authorization": f"Bearer {token}"}
def wait_for_anaf(submission_id, timeout=900):
deadline = time.time() + timeout
delay = 15
while time.time() < deadline:
r = requests.get(f"{BASE}/efactura/submissions/{submission_id}", headers=H, timeout=30)
r.raise_for_status()
status = r.json()["status"]
if status in TERMINAL:
return r.json()
# /refresh asks ANAF directly and shares the 10/min submit bucket.
requests.post(f"{BASE}/efactura/submissions/{submission_id}/refresh", headers=H, timeout=30)
time.sleep(delay)
delay = min(delay * 2, 120)
raise TimeoutError(submission_id)Помилки
- Кожна 4xx і 5xx використовує той самий конверт: { "error": { type, code, message, param?, doc_url, request_id, помилки? } }.
- type — це загальний клас, за яким ви розгалужуєте логіку («чи можна повторити?»), а code — стабільна причина, яку ви зіставляєте у своїй системі.
- param — це шлях через крапки до проблемного поля, наприклад lines.0.vat_rate.
- помилки[] з’являється, коли один запит має проблеми в кількох полях.
- request_id записується в журнали на нашому боці. Вказуйте його в кожному зверненні до підтримки — він точно ідентифікує запит.
- 404 також повертається для id, що належить іншому tenant: ми ніколи не підтверджуємо, що чужі дані існують.
json
{
"error": {
"type": "invalid_request_error",
"code": "validation_failed",
"message": "Datele trimise nu sunt valide.",
"param": "lines.0.vat_rate",
"doc_url": "https://4invoices.net/ro/api-dezvoltatori#errors",
"request_id": "req_8a893f2f33d4472da8d6e144",
"errors": [
{ "param": "lines.0.vat_rate", "message": "VAT rate must be a percent (21), not a fraction", "type": "value_error" }
]
}
}| Статус | Тип | Код |
|---|---|---|
| 401 | authentication_error | missing_bearer_token |
| 401 | authentication_error | invalid_client |
| 401 | authentication_error | token_expired |
| 401 | authentication_error | invalid_token |
| 401 | authentication_error | unauthorized |
| 403 | permission_error | insufficient_scope |
| 403 | permission_error | forbidden |
| 404 | not_found_error | not_found |
| 409 | conflict_error | idempotency_key_reuse |
| 409 | conflict_error | idempotency_in_progress |
| 409 | conflict_error | no_series_configured |
| 422 | invalid_request_error | validation_failed |
| 422 | invalid_request_error | issuer_profile_incomplete |
| 422 | invalid_request_error | cius_ro_incomplete |
| 422 | invalid_request_error | cannot_storno_draft |
| 422 | invalid_request_error | nothing_to_storno |
| 422 | invalid_request_error | invalid_json_number |
| 429 | rate_limit_error | rate_limit_exceeded |
| 502 | upstream_error | upstream_error |
| 503 | service_unavailable_error | service_unavailable |
Ліміти запитів
| Bucket | Запитів / хвилину | Що означає |
|---|---|---|
| read | 120 | GET *, POST /invoices/preview-totals, POST /invoices/{id}/efactura/validate |
| write | 30 | POST /invoices, POST /invoices/{id}/storno, POST|DELETE /invoices/{id}/payments, POST /clients |
| submit | 10 | POST /invoices/{id}/efactura/submit, POST /efactura/submissions/{id}/refresh, POST /efactura/inbox/sync |
- Ліміти діють на набір облікових даних, за хвилину: 120 для читання, 30 для запису, 10 для операцій з національною системою електронного виставлення рахунків (submit, refresh, inbox/sync).
- X-RateLimit-Limit, X-RateLimit-Remaining і X-RateLimit-Reset присутні в КОЖНІЙ відповіді, включно з 429.
- 429 також містить Retry-After у секундах. Дотримуйтеся його; не повторюйте запити в щільному циклі.
- Кошик 10/min існує тому, що в Румунії ANAF дозволяє приблизно один виклик списку повідомлень на хвилину для одного CIF.
- Запускайте /efactura/inbox/sync за cron, а не агресивним полинг.
- Потрібні вищі стелі? Напишіть нам через Контакти, вказавши очікуваний добовий обсяг.
X-RateLimit-Limit · X-RateLimit-Remaining · X-RateLimit-Reset · Retry-After
http
HTTP/2 429
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1785312000
Retry-After: 17
Content-Type: application/json
{"error":{"type":"rate_limit_error","code":"rate_limit_exceeded",
"message":"...","doc_url":"https://4invoices.net/ro/api-dezvoltatori#errors",
"request_id":"req_..."}}javascript
// Дотримуйтеся Retry-After; ніколи не повторюйте 4xx, крім 429.
async function call(url, init, attempt = 0) {
const res = await fetch(url, init);
if (res.status === 429 || res.status >= 500) {
if (attempt >= 5) return res;
const retryAfter = Number(res.headers.get("Retry-After")) || 2 ** attempt;
await new Promise((r) => setTimeout(r, retryAfter * 1000));
return call(url, init, attempt + 1);
}
return res;
}
// Повторна спроба запису МАЄ використати ТОЙ САМИЙ Idempotency-Key, інакше ви виставите
// другий фіскальний документ.Посібники за темами
Кожна тема має власну сторінку з відповідними ендпоїнтами, прикладами та помилками.
- Автентифікація в API 4invoicesОбмінюєте client_id і client_secret на Bearer-токен на одну годину, лише сервер-до-сервер.
- Виставлення рахунків через APIPOST /invoices з Idempotency-Key, ПДВ у відсотках, а також список, сторно та позначка «оплачено».
- Клієнти та перевірка в реєстрі компанійВставка або оновлення з дедуплікацією за tax_id і запит до реєстру ANAF (Румунія), щоб електронний рахунок не було відхилено.
- Національна система електронного виставлення рахунків через APIПередперевірка (у Румунії — CIUS-RO), подання до національної системи (у Румунії — SPV), нормалізований статус, підписана відповідь і вхідні рахунки постачальників.
- Серії нумерації в APIБез активної серії типу fiscale виставлення повертає 409 no_series_configured.
- Коди помилок і конверт помилкиОдин формат на всіх маршрутах: type, code, message, param, doc_url, request_id та помилки.
- Ліміти запитів і повторні спроби120 читань, 30 записів і 10 операцій з національною системою електронного виставлення рахунків на хвилину для кожного набору облікових даних, із заголовками X-RateLimit-*.
Типові помилки
- Надсилання ПДВ як дробу (0.19) або як 1. Обидва варіанти відхиляються; надсилайте 19 або 21.
- Створення токена на кожен запит. Токен діє годину; кешуйте його, інакше ви впретеся в ліміт на IP для токен ендпоінт.
- Генерування нового idempotency-ключа під час кожної повторної спроби — саме той сценарій, що призводить до дублікатів рахунків.
- Виклики з JavaScript у браузері. CORS блокує будь-який джерело, а секрет однаково був би розкритий.
- Подання в національну систему електронного виставлення рахунків без попередньої перевірки (у Румунії — CIUS-RO). Помилкове подання неможливо відкликати.
- Полінг /efactura/submissions/{id}/refresh частіше ніж 10 разів на хвилину — цей кошик спільний із надсилати.
- Випуск до того, як заповнено профіль компанії й існує активна фіскальна серія.
Питання та відповіді для розробників
Як отримати доступи до API 4invoices?
У панелі, у Виставлення рахунків → Налаштування → Доступ до API. Ви отримуєте client_id і client_secret; секрет показується один раз і зберігається лише як хеш.
Скільки діє access_token?
3600 секунд, тобто одну годину. Кешуйте його й оновлюйте до завершення — ендпоїнт токена має власний ліміт за IP.
Як надсилати ставку ПДВ?
Як відсоток: 21 для 21%. Значення в (0, 1] відкидаються, тож 0.19 і 1 не проходять валідацію.
Які виклики вимагають Idempotency-Key?
POST /invoices, POST /invoices/{id}/storno і POST /invoices/{id}/efactura/submit. Ключі пам'ятаються 24 години, а повтор повертає оригінальний документ із Idempotency-Replayed: true.
Чи можу я подати рахунок до національної системи електронного виставлення рахунків просто з API?
Так. Передперевірка через /efactura/validate (у Румунії — CIUS-RO), подання через /efactura/submit, відстеження нормалізованого статусу на /efactura/submissions/{id} і завантаження підписаної відповіді системи (у Румунії — ANAF).
Які ліміти запитів?
На набір облікових даних, за хвилину: 120 читань, 30 записів і 10 операцій з національною системою електронного виставлення рахунків. Кожна відповідь містить заголовки X-RateLimit-*, а 429 додає Retry-After.
Чи можна викликати API з фронтенду?
Ні. Це виключно server-to-server: жоден браузерний джерело не проходить CORS, а client_secret не має бути в коді, який доходить до відвідувача.
Чому я отримую issuer_profile_incomplete на першому рахунку?
Профіль компанії неповний або немає активної серії типу fiscale. Заповніть обидва в панелі; API відмовляється створювати недійсний фіскальний документ.