Fatura kesme akışı
Bu sayfa bir satış faturasını API ile baştan sona kesmenin yolunu anlatır: cari kartı hazırlayın, taslağı yazın, gönderin ve sonucu izleyin. Faturayı kendi yazılımından kesecek geliştiriciye yöneliktir; gönderim önkoşulları, numara kuralları, faturaları listeleme, XML ve PDF indirme, iptal ve gelen faturalar da burada.
Akış bir bakışta
Fatura kesmek beş istektir. Her adım aşağıda ayrıca anlatılır; imza ayrıntıları için İmzalama sayfasına bakın.
| Adım | Uç ve gereken kapsam | Yanıt |
|---|---|---|
| 1. Cari kartı oluşturun | POST /v1/contactsKart.MusteriTedarikciDuzenleyebilir | 201, cari kart |
| 2. Alıcı e-Fatura mükellefi mi, bakın | GET /v1/e-invoice-inboxes/{tax_number}Diger.EBelgeMukellefBilgileriIzleyebilir | 200, mükellefiyet kaydı |
| 3. Taslağı yazın | POST /v1/invoicesFatura.SatisFaturasiDuzenleyebilir | 201, taslak (id burada gelir) |
| 4. Gönderime alın | POST /v1/invoices/{id}/sendEFatura.TaslaktanGonderimYapabilir | 202, yalnız invoice_id |
| 5. Durumu izleyin | GET /v1/invoices/{id}EFatura.GidenKutusuIzleyebilir | 200, status alanı |
1. Cari kartı hazırlayın
Fatura bir cari karta kesilir: taslak gövdesinde contact_id zorunludur. Alıcınız için kart yoksa oluşturun. Tüzel kişide zorunlu alan yalnız title’dır, ama gönderim için aşağıdaki bilgiler de gerekir. Örnekteki değerler uydurmadır.
{
"title": "Örnek Ticaret Ltd. Şti.",
"type": "MUSTERI",
"person_type": "TUZEL",
"tax_number": "1234567890",
"tax_office": "Kadıköy",
"address": {
"line": "Örnek Mah. Deneme Sok. No: 1",
"district": "Kadıköy",
"city": "İstanbul"
}
}tax_number10 haneli VKN,national_id11 haneli TCKN olmalı ve kontrol basamağı tutmalıdır; tutmayan değer400 validation_failedalır. İstisnalar: nihai tüketici kimliği11111111111ve yurt dışındaki alıcının VKN’si2222222222.- Gerçek kişi (
person_type: GERCEKya da 11 hanelinational_id) karttafirst_namevelast_nameayrı ve zorunludur; biri eksikse400 validation_failed(details.fieldfirst_nameya dalast_name).titlebu ikisinden türer, gönderdiğiniztitlekullanılmaz. Faturada alıcının adı ve soyadı bu alanlardan yazılır; ikisi boş eski bir gerçek kişi kartına kesilen fatura gönderimde422 invalid_statealır. Nihai tüketici ve yurt dışı alıcı kimlikli kartta bu iki alan isteğe bağlıdır. - İl ve ilçe (
address.city,address.district) e-Fatura ve e-Arşiv gönderimi için gereklidir. Biri boşsa o karta kesilen fatura gönderimde400 validation_failedalır (details.field: contact_id). - Aynı firmada kayıtlı bir kartla çakışma
409 conflictalır (details.fieldçakışan alanı gösterir). Denetim cari tipine göre değişir:PERSONELdışındaki kartlardatax_number,PERSONELkartlarındanational_idtekil olmalıdır;codeher tipte tekildir. - Bu uç
Idempotency-Keyokumaz: isteği yeniden göndermek ikinci bir kart açar.
Yanıt 201 ve kartın kendisidir. Faturada kullanacağınız değer data.id’dir:
{
"data": {
"id": "0192e8a1-7c3f-7d2e-b5a4-3f6c9d8e1a20",
"code": "C-000123",
"title": "Örnek Ticaret Ltd. Şti.",
"type": "MUSTERI",
"person_type": "TUZEL",
"tax_number": "1234567890",
"tax_office": "Kadıköy",
"status": "active",
"address": {
"line": "Örnek Mah. Deneme Sok. No: 1",
"district": "Kadıköy",
"city": "İstanbul"
},
"created_at": "2026-10-04T09:12:41.482913Z",
"updated_at": "2026-10-04T09:12:41.482913Z"
}
}Mevcut bir cari kartı bulmak
Dış API cari kartları listelemez, tek tek okumaz ve VKN, TCKN ya da unvanla arama sunmaz. Bu yüzden kartı açarken dönen id’yi kendi müşteri kaydınızla eşleyip saklayın. VKN çakışmasındaki 409 yanıtı çakışan alanı söyler, mevcut kartın id’sini taşımaz. Ayrıntı: Müşteri (cari) bilgilerini okuma.
2. e-Fatura mı, e-Arşiv mi?
Belge türü alıcının durumuna bağlıdır: alıcı GİB’de e-Fatura mükellefiyse e-Fatura, değilse e-Arşiv kesilir. Alıcı e-Fatura mükellefiyken e-Arşiv kesmek belgeyi hukuken geçersiz kılar; gönderim bu durumu 422 invalid_state ile reddeder. Sorgu için alıcının VKN ya da TCKN’si yeter:
{
"data": {
"tax_number": "1234567890",
"title": "Örnek Ticaret Ltd. Şti.",
"e_invoice_user": true,
"e_despatch_user": false,
"addresses": [
{
"address": "urn:mail:defaultpk@ornek.com.tr",
"document_type": "FATURA",
"direction": "inbox"
}
]
}
}e_invoice_user: trueisedocument_type: E_FATURAkesin.recipient_mailboxolarakaddressesiçindeki, silinmemiş (deleted_atolmayan)direction: inboxetiketini verin; e-Fatura gönderiminde zorunludur.e_invoice_user: falseisedocument_type: E_ARSIVkesin.- Dizinde bulunmayan VKN
404döndürmez;e_invoice_user: falsetaşıyan geçerli bir yanıt verir.
3. Taslağı oluşturun
POST /v1/invoices yalnız taslak yazar; GİB’e hiçbir şey göndermez. Gönderim ayrı ve açık bir adımdır. Satır toplamları, KDV matrahı ve tevkifat sunucuda hesaplanır; gövdede gönderdiğiniz toplamlar yok sayılır.
{
"document_type": "E_ARSIV",
"invoice_type": "SATIS",
"scenario": "EARSIV_FATURA",
"issue_date": "2026-10-04",
"contact_id": "0192e8a1-7c3f-7d2e-b5a4-3f6c9d8e1a20",
"currency": "TRY",
"notes": ["Sipariş no: 1042"],
"items": [
{
"name": "Danışmanlık hizmeti",
"quantity": 2,
"unit": "ADET",
"unit_price": 500,
"vat_rate": 20
}
]
}Zorunlu alanlar: document_type, invoice_type, scenario, issue_date, contact_id ve her kalem için name, quantity, unit, unit_price, vat_rate. Örnek e-Arşiv içindir; e-Fatura için şunlar değişir:
quantity en çok 6 ondalık, unit_price en çok 4 ondalık alır; fazlası yuvarlanmadan kesilir ("quantity": 1.1234567 kaydedilince 1.123456 olur). Satır tutarı, matrah, vergi ve toplamlar sunucuda 2 haneye normal yuvarlamayla hesaplanır.
document_typeE_FATURA,scenarioTEMEL_FATURA(ya daTICARI_FATURA).recipient_mailbox: alıcının GİB posta kutusu etiketi (urn:mail:…), önceki adımdan.- e-Arşiv belgesinde (
E_ARSIV)recipient_email: faturanın PDF’inin gönderimden sonra iletileceği adres. Boş bırakılırsa carinin e-postası kullanılır.
İade faturasında (IADE, TEVKIFAT_IADE, YTB_IADE, YTB_TEVKIFAT_IADE) iade edilen faturanın numarasını return_invoice_number (boşluksuz 16 karakter, örneğin ABC2026000000001) ve tarihini return_invoice_date alanına yazın. Yatırım Teşvik senaryosunda (YATIRIM_TESVIK) ve e-Arşiv’in YTB tiplerinde teşvik belgesinin numarası incentive_certificate_number (6 haneli sayı), tarihi incentive_certificate_date alanıdır. Taslak bu alanlar olmadan da kaydedilir; gönderimde zorunludur.
Yanıt 201 ve taslaktır. Sonraki bütün isteklerde kullanacağınız kimlik id’dir; saklayın:
{
"data": {
"id": "0192e8b4-5a10-7e6b-8c21-9d4f0a7b3c55",
"document_type": "E_ARSIV",
"invoice_type": "SATIS",
"scenario": "EARSIV_FATURA",
"contact_title": "Örnek Ticaret Ltd. Şti.",
"tax_number": "1234567890",
"issue_date": "2026-10-04",
"total": "1200.00",
"currency": "TRY",
"status": "draft",
"created_at": "2026-10-04T09:14:02.118204Z",
"updated_at": "2026-10-04T09:14:02.118204Z"
}
}Doğrulama hatalarında details.field gövdedeki alan adıdır (items[0].vat_rate gibi). issue_date bugünden (Europe/Istanbul) ileri olamaz; TRY dışı belgede exchange_rate gerekir; ikisi de 422 invalid_state alır. contact_id bu firmada yoksa 404 döner. Bütün alanlar OpenAPI referansındadır.
Fatura id’si, fatura numarası ve ETTN farklıdır
Faturada üç ayrı kimlik vardır ve karıştırılmaları en sık yapılan hatadır:
| Alan | Nedir | Ne zaman gelir |
|---|---|---|
id | Sistemin ürettiği iç UUID. Fatura uçlarının yolunda kullanılır: /v1/invoices/{id}, /v1/invoices/{id}/send. | Taslak oluşturulunca, POST /v1/invoices yanıtında. |
invoice_no | Fatura numarası (seri ve sayaç). Müşteriye gösterilen numaradır. | Taslakta gelmez; numara gönderimde atanır: ön ek (varsayılan FAT) + belge yılı + 9 haneli sıra. Seri e-belge servisine bağlıysa alan, e-belge servisi numarayı bildirdiğinde dolar. |
uuid | ETTN: belgenin GİB’deki tekil kimliği. | Belge e-belge servisine gönderilene kadar gelmez. |
envelope_id | Zarf kimliği: e-Faturanın alıcıya gönderildiği zarfın ETTN’si. Değer e-belge servisinin bildirdiğidir. | Yalnız e-Fatura’da, belge alıcıya zarflanınca gelir; e-Arşiv’de ve taslakta yoktur. |
Seri ve numarayı API vermez, seri açmak da gerekmez
Taslak gövdesinde invoice_no ya da seri alanı yoktur: API’den seri seçilmez, numara verilmez. Numara gönderimde atanır.
Numaratör (seri) tanımlamak önkoşul değildir. Firmanın varsayılan numaratörü yoksa fatura yedek FAT serisiyle numara alır: numara ön ek + belge yılı (fatura tarihinin yılı) + 9 haneli sıradır, örneğin FAT2026000000001. FAT ilk kullanımda firmaya numaratör olarak kaydedilir.
Kendi ön ekini isteyen firma (örneğin ABC2026000000001) numaratörü kendi panelinde Firma Bilgileri → Belge Ayarları ekranındaki belge tipi sekmesinden Yeni Numaratör Ekle ile açar; bayi (iş ortağı) panelinin Belge Ayarları ekranından ya da YouSoft ekibi de açabilir. Müşteri panelinde bu işlem için firma bilgileri yetkisi gerekir. Ön ek tam 3 haneli olmalı ve yalnız A-Z ile 0-9 içermelidir. API ile seri yönetilmez.
Seri e-belge servisine bağlıysa numarayı gönderim sırasında e-belge servisi verir. Bu yüzden invoice_no taslakta ve e-belge servisi numarayı bildirene kadar gönderilmiş belgede de görünmez. Numarayı gönderimden sonra GET /v1/invoices/{id} ile okuyun; alanın o ana kadar yokluğu hata değildir.
4. Gönderim önkoşulları
send çağrıldığında önce taslağın gönderilebilir olduğu doğrulanır. Bir önkoşul eksikse yanıt hemen döner, message nedeni söyler ve taslak yerinde kalır: eksiği giderip aynı uca yeniden istek gönderebilirsiniz. Çoğu önkoşul 422 invalid_state verir; istisnalar tablolarda yazılıdır.
Firma ve hesap tarafı
Bunların çoğu firma tarafında bir kerelik panel işidir ve API ile yapılamaz; firma yetkilisinin panelden tamamlaması gerekir. Numaratör bunlardan biri değildir: tanımlı değilse FAT serisi kullanılır (Seri ve numara).
| Önkoşul | Eksikse |
|---|---|
| Firmanın e-Belge Tanımları’nda ilgili belge türü (e-Fatura ya da e-Arşiv) açık olmalı. | 422 invalid_state |
| Firmanın varsayılan GİB gönderici etiketi tanımlı olmalı. | 422 invalid_state |
Firma bilgilerinde vergi dairesi, il ve ilçe dolu olmalı. details.field boş gelir; mesaj Firma Bilgileri’nin tamamlanmasını söyler. | 422 invalid_state |
| Ödeme gecikmemiş (vade tarihinden 4 gün sonra kısıt başlar), kontör eşiği ve aşım tavanı dolmamış olmalı. | 422 invalid_state |
| Hesap belge kesmeye açık olmalı: firma pasif olmamalı, deneme süresi dolmamış olmalı. | 403 forbidden |
Belge tarafı
| Önkoşul | Eksikse |
|---|---|
| Fatura tarihi bugünden ileri olmamalı. | 422 invalid_state |
Fatura tarihi bugünden 7 günden fazla geride ise gövdede backdate_confirmed: true olmalı (VUK 231/5). | 422 invalid_state |
TRY dışındaki belgede exchange_rate olmalı. | 422 invalid_state |
| e-Arşiv alıcısı GİB e-Fatura kayıtlı kullanıcısı olmamalı. Alıcının kaydı doğrulanamazsa da aynı kod döner: sonra yeniden deneyin. | 422 invalid_state |
e-Fatura için recipient_mailbox verilmiş olmalı. | 400 validation_failed (details.field: recipient_mailbox) |
e-Arşiv için alıcı e-postası olmalı: recipient_email ya da boşsa carinin e-postası. | 400 validation_failed (details.field: recipient_email) |
| Cari kartta il ve ilçe dolu olmalı. | 400 validation_failed (details.field: contact_id) |
GİB’in belge kuralları sağlanmalı. Örnek: KDV oranı 0 olan satır exemption_code ister (satışta 351). | 400 validation_failed (details.field gövdedeki alan adı) |
| İade faturasında iade edilen faturanın numarası ve tarihi, Yatırım Teşvik senaryosunda ve e-Arşiv’in YTB tiplerinde teşvik belgesinin numarası ve tarihi dolu olmalı. | 400 validation_failed (details.field: return_invoice_number ya da incentive_certificate_number) |
| Belge türü API’den gönderilebilir olmalı. Bugün tevkifat tipleri (iadeleri dahil), e-Arşiv’in YTB tipleri ve Yatırım Teşvik senaryosu API’den gönderilemez: kalem tevkifat kodu ve kalemin teşvik harcama tipi API gövdesinde yok, bu taslaklar panelden tamamlanır. | 400 validation_failed (details.field boş, mesaj panelden tamamlanmasını söyler) |
5. Faturayı gönderin
POST /v1/invoices/{id}/send taslağı gönderim kuyruğuna alır. Gövde isteğe bağlıdır; yalnız fatura tarihi 7 günden fazla geride ise onay gerekir:
{ "backdate_confirmed": true }Başarılı yanıt 202 ve yalnız kabul edilen belgenin kimliğidir:
{
"data": { "invoice_id": "0192e8b4-5a10-7e6b-8c21-9d4f0a7b3c55" }
}202, belgenin GİB’e ulaştığı anlamına gelmez. İmzalama ve iletim arka planda olur; sonucu bir sonraki adımdaki gibi siz sorarsınız. Her gönderim niyeti için Idempotency-Key başlığı gönderin: aynı anahtarla gelen ikinci istek saklanan 202 yanıtını döndürür ve GİB’e ikinci bir gönderim olmaz. Anahtar en çok 255 karakter olabilir ve 24 saat saklanır; ayrıntı Sorgu sözleşmesinde.
6. Sonucu izleyin
Gönderim eşzamansız çalışır ve sonuç için bildirim çağrısı (webhook) yoktur: sonucu GET /v1/invoices/{id} ile status alanından sorarsınız (poll). Bu uç taslağı da gönderilmiş faturayı da okur. Başarılı gönderimde invoice_no ve uuid da dolar:
{
"data": {
"id": "0192e8b4-5a10-7e6b-8c21-9d4f0a7b3c55",
"document_type": "E_ARSIV",
"invoice_type": "SATIS",
"scenario": "EARSIV_FATURA",
"invoice_no": "FAT2026000000001",
"uuid": "5f0c2d7e-3a1b-4c8d-9e6f-1a2b3c4d5e6f",
"contact_title": "Örnek Ticaret Ltd. Şti.",
"tax_number": "1234567890",
"issue_date": "2026-10-04",
"total": "1200.00",
"currency": "TRY",
"status": "sent",
"status_detail": "GIBE_GONDERILDI",
"payment_status": "not_due",
"created_at": "2026-10-04T09:14:02.118204Z",
"updated_at": "2026-10-04T09:15:11.640371Z"
}
}status yedi değerden biridir; status_detail aynı durumun daha ayrıntılı halini taşır (taslakta gelmez). Kodunuz status ile dallansın, status_detail izleme ve destek içindir.
| status | Anlamı | status_detail değerleri |
|---|---|---|
draft | Taslak, henüz gönderilmedi. | yok |
sending | Kuyrukta ya da GİB’e iletiliyor. Beklemeye devam edin. | GONDERIM_IZNI_BEKLIYOR, ARSIV_FATURA_KAYIT_KUYRUGUNDA, RAPOR_OLUSTURULACAK, GIBE_GONDERILECEK, TEKRAR_GONDERIM_KUYRUGUNDA, GONDERIM_BELIRSIZ |
sent | GİB’e iletildi. Alıcının yanıtı bekleniyorsa durum burada kalır; yanıt gelince accepted ya da rejected olur. | GIBE_GONDERILDI, ALICIYA_ULASTI, YANIT_BEKLENIYOR |
accepted | Kabul edildi. Alıcı yanıt süresinde yanıt vermezse belge zımnen kabul edilir ve o da accepted olur. | ONAYLANDI, KABUL, OTOMATIK_KABUL |
rejected | Alıcı reddetti. | RED |
failed | Gönderim başarısız oldu. Yanıt hatanın nedenini taşımaz; ne yapacağınız aşağıda. | HATA |
cancelled | İptal edildi ya da yeniden düzenlendi. | IPTAL_EDILECEK, IPTAL_EDILDI, YENIDEN_DUZENLENDI |
Ne sıklıkla sorulur
Sık sormak sonucu hızlandırmaz, yalnız oran sınırınızı tüketir: anahtar başına dakikada 120 istek, firmanın bütün anahtarları için toplam dakikada 300 istek ve bütün uçlar aynı genel kotayı paylaşır (Oran sınırı). İlk sorguyu birkaç saniye sonra atın, sonra 30 saniye gibi aralıklarla sorun. Çok sayıda bekleyen fatura varsa her birini ayrı ayrı sormak yerine listeyi durumla süzün (filter[status][eq]=sending) ya da kayan pencereyle okuyun.
Gönderim başarısız olursa
failed gördüğünüzde önce önkoşulları ve e-belge entegrasyonunu kontrol edin, sonra yeniden gönderin. Yeniden deneme yeni bir gönderim niyetidir: aynı Idempotency-Key yalnız ilk yanıtı yineler, yeni deneme başlatmaz; bu yüzden yeni bir anahtar kullanın ya da anahtarsız gönderin. Sonuç belgenin o anki durumuna bağlıdır:
failed, belge e-belge servisine hiç ulaşmamışsa: yeniden kuyruğa alınır,202. ETTN değişmez; numara çakışması nedeniyle düşmüşse fatura numarası yenilenir.failed, belge e-belge servisine ulaşmışsa:409 conflict, yeniden gönderim yoktur.sent,accepted,rejected,cancelled:409 conflict.sending: 5 dakikadan uzun süredir takılı kalmış belge (GIBE_GONDERILECEK) yeniden kuyruğa alınır,202. Sonucu belirsiz belgede (GONDERIM_BELIRSIZ) belge yeniden yüklenmez;202döner ve sonuç e-belge servisinden sorgulanarak netleşir. Diğersendingdurumları409alır. Tam listesendInvoiceaçıklamasındadır.
Zaman aşımı ya da 5xx aldıysanız istek işlenmiş olabilir: yeniden göndermeden önce status alanını okuyun. Ağ hatasında yeniden denerken aynı Idempotency-Key’i kullanın; 24 saatten eski bir anahtar yeni istek sayılır.
Gönderimden sonra
Faturayı kestikten sonra ihtiyaç duyulan uçlar ve gereken kapsamları:
| İş | Uç ve gereken kapsam |
|---|---|
| Giden faturaları listeleyin ve bulun | GET /v1/invoicesEFatura.GidenKutusuIzleyebilir |
| Giden faturanın XML’ini indirin | GET /v1/invoices/{id}/xmlEFatura.GidenKutusuIzleyebilir |
| Giden faturanın PDF’ini indirin | GET /v1/invoices/{id}/pdfEFatura.GidenKutusuIzleyebilir |
| Gönderilmiş faturayı iptal edin | POST /v1/invoices/{id}/cancelEFatura.IptalEdebilir |
| Gelen faturaları listeleyin | GET /v1/inbox-invoicesEFatura.GelenKutusuIzleyebilir |
| Gelen faturayı okuyun | GET /v1/inbox-invoices/{id}EFatura.GelenKutusuIzleyebilir |
| Gelen faturanın XML’ini indirin | GET /v1/inbox-invoices/{id}/xmlEFatura.GelenKutusuIzleyebilir |
| Gelen faturanın PDF’ini indirin | GET /v1/inbox-invoices/{id}/pdfEFatura.GelenKutusuIzleyebilir |
Faturaları listeleme ve bulma
GET /v1/invoices taslakları ve gönderilmiş faturaları tek listede döndürür; taslak status: draft taşır. Liste e-Fatura, e-Arşiv, ihracat, ilaç ve tıbbi cihaz, kamu, SGK, proforma ve iade belgelerini kapsar (document_type: E_FATURA, E_ARSIV, E_IHRACAT, E_ILAC_TIBBI, E_KAMU, E_SGK, PROFORMA, IADE); makbuz, irsaliye ve e-Döviz belgeleri bu listede yoktur. Arşivlenen belge listeden düşer, ama GET /v1/invoices/{id} onu da okur.
Liste belge tarihine göre sıralanır (varsayılan -issue_date, en yeni önce). Süzgeçler: filter[issue_date][gte] ve [lte] (gün, YYYY-MM-DD), filter[status][eq], filter[document_type][eq], filter[invoice_no][eq], filter[uuid][eq] (ETTN) ve filter[envelope_id][eq] (zarf kimliği). Kurallar Sorgu sözleşmesinde. include=contact her satıra seçilen cari kartı ekler ve cari okuma kapsamını ister.
# Fatura numarasıyla
imzali GET "/v1/invoices?filter[invoice_no][eq]=YSF2026000000012" ''
# ETTN ile
imzali GET "/v1/invoices?filter[uuid][eq]=0191e541-1685-7953-a18b-075029fefd2c" ''
# Zarf kimliğiyle (yalnız e-Fatura)
imzali GET "/v1/invoices?filter[envelope_id][eq]=0191e5c2-7b10-7d4e-9a51-2f6e8c1d3b70" ''Numara ya da kimlikle arama tam eşleşmedir; bulunamazsa liste boştur (404 değil). Genellikle tek satır döner ama birden çok satır gelebilir: aynı numara farklı belge tiplerinde bulunabilir, bir zarfta birden çok belge olabilir. Eşlerken document_type alanına da bakın. Zarf kimliği yalnız e-Fatura satırlarında doludur ve e-belge servisinin bildirdiği değerdir.
Kendi kaydınızla eşitlemek: kayan pencere
“Son okuduğumdan beri değişenler” süzgeci yoktur: liste belge tarihine göre sıralanır ve durumu değişen belge listede yer değiştirmez. Bir faturanın durumu belge tarihinden sonra da değişir: ticari e-Faturada alıcı belge tarihinden sonraki 7 gün içinde yanıt verir, e-Arşiv faturası GİB’e iletildiği günden itibaren 8 gün içinde iptal edilebilir. Önerilen yol, her turda son 30 günün faturalarını baştan sona okumaktır.
Pencere bir üst sınır garantisi değildir: geriye tarihli bir belge iletildikten sonra iptal edilebilir, e-Faturanın dış kanalda yapılmış iptali de herhangi bir gün kaydedilebilir. Bunları kaçırmamak için dönemi kapatmadan önce o dönemin tamamını bir kez daha okuyun (filter[issue_date][gte] ve [lte] ile); tek bir belgeyi doğrulamak için GET /v1/invoices/{id} yeterlidir.
# Her turda son 30 günün faturalarını baştan sona okuyun ve kendi kaydınızla eşleyin
BASLANGIC=$(date -v-30d +%Y-%m-%d) # GNU date: date -d '30 days ago' +%Y-%m-%d
imzali GET "/v1/invoices?filter[issue_date][gte]=$BASLANGIC&page_size=100" ''
# meta.next_cursor null olana kadar aynı süzgeçle cursor ekleyerek devam edin
# Gelen faturalarda pencere 45 gündür
BASLANGIC=$(date -v-45d +%Y-%m-%d) # GNU date: date -d '45 days ago' +%Y-%m-%d
imzali GET "/v1/inbox-invoices?filter[issue_date][gte]=$BASLANGIC&page_size=100" ''XML ve PDF indirme
Gönderilmiş bir faturanın UBL XML’i GET /v1/invoices/{id}/xml, PDF’i GET /v1/invoices/{id}/pdf ile indirilir; gelen faturalar için aynı uçlar /v1/inbox-invoices/{id} altındadır. Biçim yalnız XML ve PDF’tir.
imzali GET "/v1/invoices/$FATURA_ID/xml" '' -o fatura.xml
imzali GET "/v1/invoices/$FATURA_ID/pdf" '' -o fatura.pdf- Yanıt
200ve dosyanın kendisidir:Content-Typeapplication/xml; charset=utf-8ya daapplication/pdf,Content-Disposition: attachmentve fatura numarası (yoksa ETTN) adlı dosya. - XML bayt bayt e-belge servisindeki hâliyle gelir ve imzalıdır. Saklarken yeniden biçimlendirmeyin, girintilemeyin ya da kodlamasını değiştirmeyin: imza bozulur. Simülasyon ortamında kesilen belgenin XML’i imzasızdır ve yerelde üretilir.
- Taslak indirilemez:
422 invalid_state, önce gönderin. Henüz e-belge servisine ulaşmamış belge, elle kaydedilmiş gelen belge ve e-belge entegrasyonu tamamlanmamış firma da422alır. - Belge bu firmada yoksa ya da bu uçların kapsamında değilse (makbuz, irsaliye)
404döner. - e-belge servisi hata verirse yanıt
500 internal_errorolur; indirme salt okumadır, yeniden denenebilir. Destek kaydındadetails.request_iddeğerini paylaşın. - İndirme uçlarının ayrı ve daha dar bir kotası ve firma başına aynı anda 4 indirme sınırı vardır (Oran sınırı). Toplu indirmede 4’ten fazla paralel istek açmayın; fazlası
429alır.
İptal
POST /v1/invoices/{id}/cancel gönderilmiş bir faturayı iptal eder ve geri alınamaz. Taslak bu uçtan iptal edilmez. Gereken kapsam EFatura.IptalEdebilir varsayılan kümededir; anahtar üretilirken panelde Fatura iptaline izin ver kutusu kaldırıldıysa anahtar bu kapsamı taşımaz ve istek 403 alır (Kapsamlar).
{
"objection_type": "GIB",
"reason": "Hatalı tutar"
}- e-Arşiv: GİB’e ulaşmış e-Arşiv faturası e-belge servisinde iptal edilir ve iptal GİB’e iptal raporuyla bildirilir; kayıt yalnız bu işlem başarılıysa iptal olur. Yalnız
objection_type: GIBkabul edilir. İptal tarihi işlem günüdür:cancel_dateverilmezse bugündür, başka bir gün verilirse reddedilir. İptal, belgenin GİB’e iletildiği günden itibaren 8 gün içinde (son gün dahil) yapılabilir; sonrası422 invalid_state. Geriye tarihli belgede süre belge tarihinden değil iletim gününden işler. - e-Fatura: bu uç GİB’e talep göndermez. e-Faturanın iptali alıcıyla dış kanalda (GİB, KEP, noter ya da taahhütlü mektup) yapılır; bu istek o itirazın ya da iptalin kaydıdır ve kanal
objection_typeile yazılır. - Zaten iptal edilmiş, yeniden düzenlenmiş ya da gönderimi süren belge
409 conflictalır. - e-belge servisi hata verirse yanıt
500 internal_errorolur ve fatura değişmemiştir; istek tekrarlanabilir.
Gelen faturalar
GET /v1/inbox-invoices karşı tarafın firmaya gönderdiği faturaları listeler, GET /v1/inbox-invoices/{id} tek birini okur. Taslak aşaması yoktur: status hiçbir zaman draft ya da sending olmaz. Sıralama ve süzgeç adları giden listeyle aynıdır, değer kümeleri farklıdır: status yalnız sent, accepted, rejected ve cancelled; document_type yalnız E_FATURA (iade, kamu, ihracat gibi ayrımlar invoice_type ve scenario alanlarındadır). envelope_id süzgeci ve alanı gelen faturada yoktur. e-İrsaliye bu listede değildir.
- Fatura numarası gelen faturada benzersiz değildir: iki farklı tedarikçi aynı numarayla fatura gönderebilir.
filter[invoice_no][eq]birden çok satır döndürebilir; gönderenlerisender_tax_numberile ayırın. - Gelen belge bize belge tarihinden günler sonra ulaşabilir (
received_at) ve listedeissue_date’ine göre eski bir yere düşer. Bu yüzden gelende kayan pencereyi daha geniş tutun (son 45 gün) ve dönemi kapatmadan önce o dönemi bir kez tam okuyun. - Bize ulaşırken işlenemeyen belge (alımında hata oluşmuş belge) listede görünmez; tekil okuması ve indirmesi
404döner. Hata giderilince belge gerçek durumuyla listeye girer. Bu yüzden gelen listedefailedsüzgeci yoktur. Düzeltilen belgenin tarihi kayan pencerenizin dışında kalmışsa onu yalnız daha geniş bir tarih aralığıyla görürsünüz. - Panelden elle kaydedilmiş (GİB üzerinden gelmemiş) belgede
uuid,received_atveanswer_due_datenulldöner; bu belgenin XML’i ve PDF’i yoktur (422). answer_due_dateticari faturada kabul ya da red için son gündür: belge tarihinden sonraki 7. gün (belge günü sayılmaz). Yanıt dış API’den verilmez, panelden verilir.
Tam akış örneği
Önce her isteği imzalayan küçük bir işlev tanımlayın. İmzanın ne yaptığı İmzalama sayfasında anlatılır; Postman kullanıyorsanız Postman sayfası aynı işi koleksiyon betiğiyle yapar.
# İmzalı istek: imzali METOT YOL GÖVDE [ek curl bağımsız değişkenleri]
# API_KEY ve API_SECRET tanımlı olmalı (Hızlı başlangıç); yanıtları ayrıştırmak için jq gerekir.
TABAN='https://api.yousoft.com.tr'
imzali() {
local METOT=$1 YOL=$2 GOVDE=$3
shift 3
local TS OZET IMZA
TS=$(date +%s)
OZET=$(printf '%s' "$GOVDE" | openssl dgst -sha256 -hex | awk '{print $NF}')
IMZA=$(printf '%s\n%s\n%s\n%s' "$TS" "$METOT" "$YOL" "$OZET" \
| openssl dgst -sha256 -hmac "$API_SECRET" -hex | awk '{print $NF}')
if [ -n "$GOVDE" ]; then set -- --data-binary "$GOVDE" "$@"; fi
curl -sS -g -X "$METOT" "$TABAN$YOL" \
-H "X-Api-Key: $API_KEY" \
-H "X-Api-Timestamp: $TS" \
-H "X-Api-Signature: $IMZA" \
-H 'Content-Type: application/json' "$@"
}Ardından beş adım, sırayla:
# 1. Cari kartı oluşturun ve id'sini alın
CARI=$(imzali POST /v1/contacts '{
"title": "Örnek Ticaret Ltd. Şti.",
"type": "MUSTERI",
"person_type": "TUZEL",
"tax_number": "1234567890",
"tax_office": "Kadıköy",
"address": { "district": "Kadıköy", "city": "İstanbul" }
}')
CARI_ID=$(printf '%s' "$CARI" | jq -r '.data.id')
# 2. Alıcı e-Fatura mükellefi mi? false ise e-Arşiv, true ise e-Fatura keseceksiniz
imzali GET /v1/e-invoice-inboxes/1234567890 '' | jq '.data.e_invoice_user'
# 3. Taslağı oluşturun (e-Arşiv örneği) ve id'sini alın
GOVDE=$(cat <<TASLAK
{
"document_type": "E_ARSIV",
"invoice_type": "SATIS",
"scenario": "EARSIV_FATURA",
"issue_date": "$(TZ=Europe/Istanbul date +%F)",
"contact_id": "$CARI_ID",
"items": [
{ "name": "Danışmanlık hizmeti", "quantity": 2, "unit": "ADET", "unit_price": 500, "vat_rate": 20 }
]
}
TASLAK
)
FATURA=$(imzali POST /v1/invoices "$GOVDE")
FATURA_ID=$(printf '%s' "$FATURA" | jq -r '.data.id')
# 4. Gönderime alın. Anahtarı saklayın: aynı gönderimi yeniden denerken aynısını verin
ANAHTAR=$(uuidgen)
imzali POST "/v1/invoices/$FATURA_ID/send" '{}' -H "Idempotency-Key: $ANAHTAR"
# 5. Sonucu izleyin: sending sürüyor demektir, gerisi sonuçtur
while :; do
DURUM=$(imzali GET "/v1/invoices/$FATURA_ID" '' | jq -r '.data.status')
echo "durum: $DURUM"
case "$DURUM" in draft|sending) sleep 30 ;; *) break ;; esac
doneMüşteri (cari) bilgilerini okuma
Dış API cari kartları listelemez ve tek bir kartı da okumaz; carinin ekstresi, bakiyesi ve iletişim kişileri de dış API’de yoktur, panelden bakılır. Cari kart uçları yazma içindir: POST /v1/contacts kart açar, PATCH /v1/contacts/{id} günceller, POST /v1/contacts/{id}/people iletişim kişisi ekler. Kartı açarken dönen id’yi saklayın (Mevcut bir cari kartı bulmak).
Faturayı cari bilgisiyle birlikte okuma
Bir faturanın alıcı kartını faturayla birlikte okuyabilirsiniz: GET /v1/invoices/{id} isteğine include=contact verin.
imzali GET "/v1/invoices/$FATURA_ID?include=contact" ''- Kart, faturanın
contactalanında gelir ve belge düzenlenirken seçilen karttır. include=contactayrıcaKart.MusteriTedarikciIzleyebilirkapsamını ister; anahtar bunu taşımıyorsa istek403 forbiddenalır,includevermeyen istek etkilenmez.- Kart belirlenemeyen belgede
contactalanı hiç gelmez; bu hata değildir. Belgenin kendicontact_titlevetax_numberalanları her zaman bulunur (Genişletme).
