4invoices genel API'si faturalama verilerini sisteminizden 4invoices'a taşır ve faturayı ulusal e-fatura sisteminde (Romanya'da: ANAF SPV) sonuna kadar götürür. Tek bir üretim host'u, tek bir client_credentials akışı, idempotent mali yazma işlemleri ve her rotada aynı hata zarfı.
https://api.4invoices.net/v1 · OpenAPI şeması (anahtar gerekmez)
4invoices API'si nedir
- 4invoices genel API’si HTTPS üzerinden REST’tir; girdi de çıktı da JSON’dur.
- Tek bir üretim sunucusu vardır: https://api.4invoices.net/v1. Ayrı bir test sunucusu yoktur.
- OpenAPI 3.1 spesifikasyonu herkese açıktır ve anahtar gerektirmez — doğrudan Postman’e veya bir istemci üretecine aktarın.
- Her yanıt bir X-Request-Id başlığı taşır; destek isterken bunu belirtin.
- Her mali yazma işlemi idempotenttir: timeout sonrasında yapılan yeniden deneme asla ikinci bir belge düzenlemez.
- API üzerinden Romanya’daki ANAF e-Factura döngüsünün tamamı: ön kontrol, gönderim, takip, imzalı yanıt ve gelen kutusu. Hiçbir Romen rakip bunu sunmuyor.
- SmartBill’in ulusal e-fatura sistemine (Romanya’da ANAF) gönderim için hiç endpoint’i yoktur — Romanya’da SPV gönderimi yalnızca arayüzde yapılan bir hesap ayarıdır — ve hiç fatura listeleme endpoint’i de yoktur.
- Oblio müşteri ve ürünleri birinci sınıf kaynaklar olarak değil, yalnızca bir belge düzenlemenin yan etkisi olarak oluşturabilir.
- Gönderim yapmadan UBL XML (Romanya’da: CIUS-RO) üretimi: ulusal e-fatura sistemine dokunmadan yasal belgeyi dosya olarak alırsınız.
- Mali yazma işlemlerinde idempotency: timeout sonrasında yapılan yeniden deneme ikinci bir fatura üretmez ve ikinci bir numara yakmaz.
- Programatik olarak okunabilen tedarikçi faturaları gelen kutusu — otomatik mutabakatın temeli.
6 adımda ilk fatura
- Panelde Faturalama → Ayarlar → API erişimi bölümünden bir kimlik bilgisi oluşturun ve client_secret değerini kopyalayın — yalnızca bir kez gösterilir.
- Firma profilini tamamlayın ve fiscale türünde en az bir seri etkinleştirin; aksi hâlde kesim issuer_profile_incomplete veya no_series_configured döner.
- Panelde Faturalama → Ayarlar → API erişimi bölümünden bir kimlik bilgisi oluşturun ve client_secret değerini kopyalayın — yalnızca bir kez gösterilir.
- Firma profilini tamamlayın ve fiscale türünde en az bir seri etkinleştirin; aksi hâlde kesim issuer_profile_incomplete veya no_series_configured döner.
- Kimlik bilgisini token ile değişin: grant_type client_credentials ile POST /v1/auth/token. Token bir saat geçerlidir — önbelleğe alın, her istek için yenisini almayın.
- Faturayı kesin: Idempotency-Key başlığı ve yüzde olarak vat_rate (21, 0.21 değil) ile POST /v1/invoices.
- Ön kontrolü (Romanya'da: CIUS-RO) POST /v1/invoices/{id}/efactura/validate ile çalıştırın, ardından POST /v1/invoices/{id}/efactura/submit ile ulusal e-fatura sistemine (Romanya'da: ANAF) gönderin.
- Durumu GET /v1/efactura/submissions/{id} ile accepted veya rejected olana kadar izleyin.
bash
# 1 — token (1 saat, önbelleğe al)
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 — faturayı kes (Idempotency-Key ZORUNLUDUR)
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}",
# Her MANTIKSAL işlem için bir anahtar — yeniden denemede aynısını kullanın, asla yeniden üretmeyin.
"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}], # yüzde, 0.21 değil
"currency": "RON",
}, timeout=60).json()
print(invoice["number"], invoice["totals"])Kimlik doğrulama
- Akış client_credentials’tır: client_id + client_secret karşılığında bir Bearer access_token alırsınız.
- Token 3600 saniyede sona erer. Her çağrıda değil, süresi dolmadan önce yenileyin — POST /auth/token’ın IP başına kendi hız sınırı vardır.
- client_secret yalnızca hash olarak saklanır ve kurtarılamaz. Kaybederseniz yeni bir kimlik bilgisi oluşturur ve eskisini iptal edersiniz.
- Yalnızca server-to-server. CORS üzerinden hiçbir browser origin’e izin verilmez: sayfadaki JavaScript’ten gizli anahtar ziyaretçiye sızardı.
- Scopes her kimlik bilgisi için ayrı ayrı verilir. Her sistem için ayrı bir kimlik bilgisi oluşturun ve her birine yalnızca ihtiyaç duyduğu en az scopes’u verin.
Faturalama → Ayarlar → API erişimi
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
// Token'ı önbelleğe alın; her istekte yeni bir token üretmeyin.
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;
}KDV oranları yüzdedir
vat_rate: 21 ✓ · vat_rate: 0.19 ✗ · vat_rate: 1 ✗- vat_rate bir YÜZDEDİR: 21, %21 anlamına gelir.
- (0, 1] aralığındaki değerler reddedilir — 0.19 bir kesirdir, 1 ise %1 ile %100 arasında belirsizdir.
- 0 geçerlidir ve muafiyet ya da ters ibraz (reverse charge) anlamına gelir; yasal ibareyi notes alanına yazın.
- Düzenleyen KDV mükellefi olduğunda unit_price NET birim fiyattır.
- Kaydetmeden önce toplamlara mı ihtiyacınız var? POST /v1/invoices/preview-totals, mali numara tüketmeden aynı hesaplamayı yapar.
Mali yazmalarda idempotency
- Idempotency-Key başlığı POST /invoices, POST /invoices/{id}/storno ve POST /invoices/{id}/efactura/submit üzerinde ZORUNLUDUR.
- Anahtarlar 24 saat boyunca hatırlanır. Aynı anahtarı aynı gövdeyle yeniden göndermek orijinal sonucu döndürür ve Idempotency-Replayed: true ayarlar.
- Aynı anahtar farklı bir gövdeyle 409 idempotency_key_reuse döndürür — daha önce düzenlenmiş bir mali belgenin üzerine asla yazılmaz.
- HTTP denemesi başına değil, MANTIKSAL işlem başına bir anahtar: her yeniden denemede yeni bir UUID değil, order-10457-invoice.
- Sebep teknik değil, hukukidir: tüketilmiş bir mali numara ve ulusal e-fatura sistemine (Romanya’da: SPV) gönderilmiş bir fatura geri çekilemez.
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" }
}'Tüm uç noktalar
| Metot | Uç nokta | Scope | Idempotency-Key | İstek / dakika |
|---|---|---|---|---|
| POST | /auth/token Kimlik bilgilerini erişim token'ı ile değiştir | — | — | 120 |
| GET | /me Kiracı, scope'lar ve mevcut limitler | invoices:read | — | 120 |
| POST | /invoices Fatura veya proforma düzenle | invoices:write | zorunlu | 30 |
| GET | /invoices Faturaları listele (imleçle sayfalama) | invoices:read | — | 120 |
| POST | /invoices/preview-totals Hiçbir şey oluşturmadan toplamları hesapla | invoices:read | — | 120 |
| GET | /invoices/{invoice_id} Bir faturayı getir | invoices:read | — | 120 |
| GET | /invoices/{invoice_id}/pdf Faturanın PDF'ini indir | invoices:read | — | 120 |
| GET | /invoices/{invoice_id}/xml UBL XML'ini indir (Romanya'da: CIUS-RO) | invoices:read | — | 120 |
| POST | /invoices/{invoice_id}/storno Bu faturayı iptal eden bir iade faturası düzenle | invoices:write | zorunlu | 30 |
| POST | /invoices/{invoice_id}/payments Faturayı ödendi olarak işaretle | invoices:write | — | 30 |
| DELETE | /invoices/{invoice_id}/payments Faturayı ödenmedi olarak işaretle | invoices:write | — | 30 |
| GET | /clients Müşterileri listele | clients:read | — | 120 |
| POST | /clients Müşteri oluştur veya güncelle | clients:write | — | 30 |
| GET | /lookup/company/{tax_id} ANAF sicilinde CUI doğrula (Romanya) | clients:read | — | 120 |
| GET | /series Numaralandırma serilerini listele | invoices:read | — | 120 |
| POST | /invoices/{invoice_id}/efactura/validate Ön kontrol (Romanya'da: CIUS-RO) — göndermeden doğrula | efactura:read | — | 120 |
| POST | /invoices/{invoice_id}/efactura/submit Faturayı ulusal e-fatura sistemine gönder (Romanya'da: ANAF/SPV) | efactura:submit | zorunlu | 10 |
| GET | /efactura/submissions Ulusal e-fatura sistemine yapılan gönderimleri listele | efactura:read | — | 120 |
| GET | /efactura/submissions/{submission_id} Bir gönderimi getir | efactura:read | — | 120 |
| POST | /efactura/submissions/{submission_id}/refresh Ulusal e-fatura sistemine güncel durumu sor | efactura:read | — | 10 |
| GET | /efactura/submissions/{submission_id}/download İmzalı yanıt arşivini indir | efactura:read | — | 120 |
| GET | /efactura/inbox Ulusal e-fatura sistemi üzerinden alınan tedarikçi faturaları | efactura:read | — | 120 |
| GET | /efactura/inbox/{inbound_id} Bir gelen faturayı getir | efactura:read | — | 120 |
| GET | /efactura/inbox/{inbound_id}/download Gelen faturanın arşivini indir | efactura:read | — | 120 |
| POST | /efactura/inbox/sync Ulusal e-fatura sisteminden yeni mesajları gelen kutusuna çek | efactura:read | — | 10 |
25 endpoints · https://api.4invoices.net/v1/openapi.json
Scope'lar
- invoices:read
- invoices:write
- clients:read
- clients:write
- efactura:read
- efactura:submit
Ulusal e-fatura sistemi süreci
- Asıl fark: yalnızca belge üretimi değil, ulusal e-fatura sistemiyle (Romanya’da: ANAF e-Factura) döngünün tamamı API üzerinden yürür.
- POST /invoices/{id}/efactura/validate, ön kontrolü (Romanya’da: CIUS-RO) çalıştırır ve hiçbir şey göndermeden ulusal e-fatura sisteminin reddedeceği alanları tam olarak döndürür.
- GET /invoices/{id}/xml, gönderim yapmadan UBL XML’ini (Romanya’da: CIUS-RO) üretir — kendi arşiviniz veya iç denetim için kullanışlıdır.
- POST /invoices/{id}/efactura/submit faturayı ulusal e-fatura sistemine (Romanya’da: SPV) gönderir. Bu geri alınamaz: aynı faturanın ikinci bir kopyası sistemden geri çekilemez.
- Yaşam döngüsü normalleştirilmiştir: not_sent → validating → queued → sent → processing → accepted | rejected | error. accepted yasal olarak iletildi demektir; error bizim tarafımızdaki bir aktarım hatasıdır ve yeniden denemek güvenlidir.
- GET /efactura/submissions/{id}/download, ulusal sistemin (Romanya’da: ANAF) imzalı yanıtını içeren arşivi indirir.
- Gelen taraf da mevcuttur: POST /efactura/inbox/sync ulusal e-fatura sisteminden (Romanya’da: SPV) yeni mesajları çeker, GET /efactura/inbox ise tedarikçilerinizin size gönderdiği faturaları listeler.
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)Hatalar
- Her 4xx ve 5xx aynı zarfı kullanır: { "error": { type, code, message, param?, doc_url, request_id, errors? } }.
- type, dallanmayı üzerine kurduğunuz genel sınıftır (“yeniden deneyebilir miyim?”); code ise kendi sisteminize eşlediğiniz kararlı nedendir.
- param, sorunlu alanın noktalı yoludur; örneğin lines.0.vat_rate.
- errors[], tek bir istekte birden fazla alanda sorun olduğunda görünür.
- request_id bizim tarafımızda kayda alınır. Her destek talebinde belirtin — isteği tam olarak tespit eder.
- Başka bir tenant’a ait bir id için de 404 döndürülür: başkasına ait verilerin var olduğunu asla doğrulamayız.
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" }
]
}
}| Durum | Tip | Kod |
|---|---|---|
| 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 |
İstek limitleri
| Bucket | İstek / dakika | Anlamı |
|---|---|---|
| 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 |
- Sınırlar kimlik bilgisi başına, dakika başınadır: okuma için 120, yazma için 30, ulusal e-fatura sistemi işlemleri (submit, refresh, inbox/sync) için 10.
- X-RateLimit-Limit, X-RateLimit-Remaining ve X-RateLimit-Reset, 429 dahil HER yanıtta bulunur.
- 429 ayrıca saniye cinsinden Retry-After taşır. Buna uyun; sıkı bir döngüde yeniden denemeyin.
- 10/min kovası vardır, çünkü Romanya’da ANAF, CIF başına dakikada yaklaşık bir mesaj listesi çağrısına izin verir.
- /efactura/inbox/sync’i agresif polling ile değil, cron ile çalıştırın.
- Daha yüksek tavanlara mı ihtiyacınız var? Beklenen günlük hacminizle birlikte İletişim üzerinden talep edin.
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'a uyun; 429 dışındaki 4xx hatalarını asla yeniden denemeyin.
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;
}
// Bir yazma yeniden denemesi AYNI Idempotency-Key'i kullanmak ZORUNDADIR, aksi hâlde
// ikinci bir mali belge kesersiniz.Konuya göre kılavuzlar
Her konunun kendi sayfası var: ilgili uç noktalar, örnekler ve hatalar.
- 4invoices API'sinde kimlik doğrulamaclient_id ve client_secret'ı bir saat geçerli Bearer token ile değiştirirsiniz, yalnızca sunucudan sunucuya.
- API üzerinden fatura kesmekIdempotency-Key ile POST /invoices, yüzde olarak KDV, ayrıca listeleme, iade faturası ve ödendi işareti.
- Müşteriler ve şirket sicili sorgusutax_id üzerinden tekilleştirilmiş ekleme veya güncelleme (upsert) ve ANAF sicil sorgusu (Romanya), böylece e-fatura reddedilmez.
- API üzerinden ulusal e-fatura sistemiÖn kontrol (Romanya'da: CIUS-RO), ulusal sisteme gönderim (Romanya'da: SPV), normalleştirilmiş durum, imzalı yanıt ve gelen tedarikçi faturaları.
- API'de numaralandırma serilerifiscale türünde etkin bir seri yoksa fatura kesimi 409 no_series_configured döndürür.
- Hata kodları ve hata zarfıTüm rotalarda tek biçim: type, code, message, param, doc_url, request_id ve errors.
- İstek limitleri ve yeniden denemelerKimlik bilgisi başına dakikada 120 okuma, 30 yazma ve 10 ulusal e-fatura sistemi işlemi, X-RateLimit-* başlıklarıyla.
Sık yapılan hatalar
- KDV’yi kesir (0.19) ya da 1 olarak göndermek. İkisi de reddedilir; 19 veya 21 gönderin.
- Her istek için token oluşturmak. Token bir saat geçerlidir; önbelleğe alın, aksi takdirde token endpoint’inin IP başına sınırına takılırsınız.
- Her yeniden denemede yeni bir idempotency anahtarı üretmek — tam olarak mükerrer faturalar üreten senaryo.
- Tarayıcıdaki JavaScript’ten çağırmak. CORS her origin’i engeller ve gizli anahtar zaten açığa çıkardı.
- Ön kontrol (Romanya’da: CIUS-RO) olmadan ulusal e-fatura sistemine göndermek. Hatalı bir gönderim geri çekilemez.
- /efactura/submissions/{id}/refresh’i dakikada 10 defadan fazla polling yapmak — bu kova submit ile ortaktır.
- Şirket profili tamamlanmadan ve etkin bir mali seri oluşmadan düzenleme yapmak.
Geliştiriciler için soru ve cevaplar
4invoices API kimlik bilgilerini nasıl alırım?
Panelde Faturalama → Ayarlar → API erişimi bölümünden. client_id ve client_secret alırsınız; secret yalnızca bir kez gösterilir ve sadece hash olarak saklanır.
access_token ne kadar geçerli?
3600 saniye, yani bir saat. Önbelleğe alın ve süresi dolmadan yenileyin — token uç noktasının IP bazlı kendi limiti var.
KDV oranını nasıl gönderirim?
Yüzde olarak: 21 için 21. (0, 1] aralığındaki değerler reddedilir, yani 0.19 ve 1 doğrulamadan geçmez.
Hangi çağrılar Idempotency-Key gerektirir?
POST /invoices, POST /invoices/{id}/storno ve POST /invoices/{id}/efactura/submit. Anahtarlar 24 saat hatırlanır ve tekrar gönderim orijinal belgeyi Idempotency-Replayed: true ile döndürür.
Faturayı doğrudan API üzerinden ulusal e-fatura sistemine gönderebilir miyim?
Evet. /efactura/validate ile ön kontrol (Romanya'da: CIUS-RO), /efactura/submit ile gönderim, /efactura/submissions/{id} üzerinden normalleştirilmiş durum takibi ve sistemin (Romanya'da: ANAF) imzalı yanıtının indirilmesi.
İstek limitleri nedir?
Kimlik bilgisi başına, dakikada: 120 okuma, 30 yazma ve 10 ulusal e-fatura sistemi işlemi. Her yanıt X-RateLimit-* başlıkları taşır, 429 ayrıca Retry-After ekler.
API'yi frontend'den çağırabilir miyim?
Hayır. Yalnızca sunucudan sunucuyadır: hiçbir tarayıcı origin'i CORS'tan geçmez ve client_secret ziyaretçiye ulaşan kodda yer almamalıdır.
İlk faturada neden issuer_profile_incomplete alıyorum?
Şirket profili eksik ya da fiscale türünde etkin bir seri yok. İkisini de panelde tamamlayın; API geçersiz bir mali belge üretmeyi reddeder.