Paraşüt'te kestiğiniz satış faturası, siz resmileştirene kadar yalnızca ön muhasebe kaydıdır. Resmileştirme, bu kaydı alıcıya göre bir e-Fatura ya da e-Arşiv faturasına dönüştürme işlemidir. API tarafında bu iş tek bir istekle bitmez: önce alıcının e-Fatura gelen kutusu sorgulanır, sonra doğru e-belge oluşturulur, ardından arka planda çalışan işin sonucu beklenir ve en son PDF alınır.
Bu rehber, Paraşüt API v4 ile bu akışın her adımını istek gövdeleri, yanıt kodları ve tipik hatalarıyla anlatıyor. Satış faturasının nasıl oluşturulduğunu Paraşüt API ile fatura kesme rehberinde ele aldık; burada elinizde bir satış faturası id'si olduğunu varsayıyoruz. Hangi belgeyi kesmekle yükümlü olduğunuz ise API'nin değil mevzuatın konusudur; bunu mali müşavirinizle ve GİB mevzuatıyla belirleyin. Genel çerçeve için e-ticarette e-Arşiv ve e-Fatura zorunluluğu yazımıza bakabilirsiniz.
Resmileştirme Akışına Genel Bakış

- Gelen kutusu sorgusu:
GET /e_invoice_inboxes?filter[vkn]=...ile alıcının e-Fatura kullanıcısı olup olmadığını öğrenin. - e-belgeyi oluşturun: Gelen kutusu varsa
POST /e_invoices, yoksaPOST /e_archives. - İşi takip edin: İki istek de 202 ve bir trackable job döner.
GET /trackable_jobs/{id}iledoneya daerrorolana kadar sorgulayın. - e-belgenin kimliğini alın:
GET /sales_invoices/{id}?include=active_e_document. - e-Fatura sonucunu kontrol edin:
GET /e_invoices/{id}ilestatusalanını okuyun, gerekirse yeniden gönderin. - PDF'i alın:
GET /e_archives/{id}/pdfya daGET /e_invoices/{id}/pdf.
Serbest meslek makbuzu kesiyorsanız akış farklıdır: POST /e_smms eşzamanlı çalışır ve 201 ile kaydı doğrudan döner. Ayrıntılar için e-SMM rehberine bakın.
1. Adım: Alıcı e-Fatura Kullanıcısı mı?
Karar, alıcının vergi kimlik numarasıyla (VKN ya da TCKN) yapılan gelen kutusu sorgusuna dayanır. Paraşüt'ün rehberine göre boş liste dönerse alıcı e-Arşiv kapsamındadır, data dolu dönerse e-Fatura kullanıcısıdır. Rehber ayrıca ihracat faturalarının her zaman e-Fatura olarak kesildiğini belirtir.
curl -X GET "https://api.parasut.com/v4/{company_id}/e_invoice_inboxes?filter[vkn]=1234567890" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Accept: application/json"Yanıttaki her kayıt type: "e_invoice_inboxes" taşır ve şu salt okunur alanları içerir:
| Alan | Anlamı |
|---|---|
| vkn | Alıcının vergi kimlik numarası |
| e_invoice_address | Gelen kutusu adresi; e-Fatura isteğindeki to alanına bu yazılır |
| name | Gelen kutusu sahibinin adı |
| inbox_type | Gelen kutusu türü |
| address_registered_at / registered_at | Adresin ve kaydın oluşturulma zamanı |
Liste birden fazla kayıt içerebilir. Paraşüt'ün örnek uygulaması ilk kaydın e_invoice_address değerini kullanır. Liste sayfalıdır; page[size] en fazla 25'tir.
2a. Adım: e-Fatura Oluşturma
Alıcının gelen kutusu varsa POST /e_invoices çağrılır. Dikkat edilecek nokta ilişki adıdır: e-Fatura'da satış faturasına bağlanan ilişkinin adı invoice'dır.
curl -X POST "https://api.parasut.com/v4/{company_id}/e_invoices" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"data": {
"type": "e_invoices",
"attributes": {
"scenario": "commercial",
"to": "<GELEN_KUTUSU_e_invoice_address>"
},
"relationships": {
"invoice": { "data": { "type": "sales_invoices", "id": "<INVOICE_ID>" } }
}
}
}'
| Alan | Açıklama |
|---|---|
| scenario | Gönderim senaryosu: basic veya commercial |
| to | Alıcının gelen kutusu adresi (e_invoice_address) |
| vat_exemption_reason_code | KDV oranı yüzde 0 olan kalemler için KDV muafiyet sebebi kodu |
| vat_exemption_reason | Muafiyet kodu 250 veya 350 ise açıklama |
| vat_withholding_params[] | Tevkifatlı her kalem için detail_id ve vat_withholding_code |
| excise_duty_codes[] | ÖTV uygulanan her ürün için product ve sales_excise_duty_code |
| custom_requirement_params | Özel gereksinimli alıcılar için integration ve products anahtarları |
Hangi senaryonun (basic ya da commercial) kullanılacağı ticari ve mali bir karardır; API yalnızca iki değeri kabul eder. Tevkifat ve muafiyet kodlarının listesi için belge, GİB'in UBL-TR kılavuzlarını gösterir. Bazı alıcıların (rehberde SGK ve Amazon örnekleri var) beklediği ek alanlar satış faturasına değil, bu istekteki custom_requirement_params içine yazılır.
2b. Adım: e-Arşiv Oluşturma

Alıcının gelen kutusu yoksa POST /e_archives çağrılır. Burada ilişkinin adı sales_invoice'dır; e-Fatura'daki invoice ile karıştırmak en sık yapılan hatalardan biridir.
curl -X POST "https://api.parasut.com/v4/{company_id}/e_archives" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"data": {
"type": "e_archives",
"attributes": {
"internet_sale": {
"url": "https://magaza.example.com",
"payment_type": "KREDIKARTI/BANKAKARTI",
"payment_platform": "<ODEME_KURULUSU>",
"payment_date": "2026-11-03"
},
"shipment": {
"title": "<KARGO_FIRMASI_UNVANI>",
"vkn": "<KARGO_FIRMASI_VKN>",
"date": "2026-11-04"
}
},
"relationships": {
"sales_invoice": { "data": { "type": "sales_invoices", "id": "<INVOICE_ID>" } }
}
}
}'
OpenAPI belgesi iki nesne için açık bir not düşer: internet_sale internet üzerinden satış yapıyorsanız, shipment ise kargo ya da kurye ile gönderim varsa doldurulmalıdır. Hizmet satışında gönderilen bir şey olmadığı için shipment zorunlu değildir.
| Alan | Açıklama |
|---|---|
| internet_sale.url | Satışın yapıldığı internet adresi |
| internet_sale.payment_type | KREDIKARTI/BANKAKARTI, EFT/HAVALE, KAPIDAODEME, ODEMEARACISI |
| internet_sale.payment_platform | Ödeme platformu (ör. ödeme kuruluşunun adı) |
| internet_sale.payment_date | Ödeme tarihi, YYYY-MM-DD |
| shipment.title / shipment.vkn | Kargo ile gönderimde kargo şirketinin adı ve VKN'si |
| shipment.name / shipment.tckn | Kurye ile gönderimde kuryenin adı ve TCKN'si |
| shipment.date | Gönderi tarihi |
e-Fatura'daki tevkifat, muafiyet ve ÖTV alanları (vat_withholding_params, vat_exemption_reason_code, vat_exemption_reason, excise_duty_codes) e-Arşiv isteğinde de aynı biçimde kullanılır.
3. Adım: 202 Yanıtı ve Trackable Job Takibi
POST /e_invoices ve POST /e_archives belgeyi hemen oluşturmaz. 202 Accepted ile bir trackable job döner; trackable job, Paraşüt'ün arka planda yürüttüğü ve durumunu sonradan sorgulayabildiğiniz bir iştir. İşin kimliği data.id alanındadır.
{
"data": {
"id": "<JOB_ID>",
"type": "trackable_jobs",
"attributes": { "status": "running", "errors": [] }
}
}| status | Anlamı | Ne yapmalı |
|---|---|---|
| running | İş sürüyor | Bir süre bekleyip tekrar sorgulayın |
| done | e-belge oluştu | 4. adıma geçin |
| error | Belge oluşmadı | attributes.errors dizisindeki metinleri kullanıcıya gösterin |
Paraşüt rehberine göre işin durumu, son güncellemesinden sonra 15 dakika boyunca sorgulanabilir; bu süre geçince sorgu 404 döner. Önerilen bir sorgulama aralığı belgede yoktur. Aşağıdaki fonksiyon artan bekleme ile sorgular ve 15 dakikalık pencerenin içinde kalır:
import { parasut, sleep } from './parasut.js';
// Sorgulama aralığı belgede belirtilmez; aşağıdaki değerler örnektir.
export async function waitForJob(jobId, timeoutMs = 10 * 60_000) {
const started = Date.now();
let delay = 2000;
while (Date.now() - started < timeoutMs) {
const res = await parasut(`/trackable_jobs/${jobId}`);
if (res.status === 404) throw new Error('İş bulunamadı: sorgu süresi geçmiş olabilir');
if (res.status !== 200) throw new Error(`HTTP ${res.status}`);
const { status, errors } = res.body.data.attributes;
if (status === 'done') return;
if (status === 'error') throw new Error('Resmileştirme hatası: ' + (errors ?? []).join('; '));
await sleep(delay); // status === 'running'
delay = Math.min(delay * 2, 30_000);
}
throw new Error('İş zamanında tamamlanmadı; durumu daha sonra tekrar sorgulayın');
}İlk iki adımı birleştiren resmileştirme fonksiyonu ise şöyle görünebilir. Örnekteki parasut() yardımcısı fatura kesme rehberindeki küçük istemcidir.
import { parasut } from './parasut.js';
export async function formalize(invoiceId, taxNumber, { scenario, eArchiveAttrs }) {
// 1) Alıcının e-Fatura gelen kutusu var mı?
const inbox = await parasut(`/e_invoice_inboxes?filter[vkn]=${encodeURIComponent(taxNumber)}`);
if (inbox.status !== 200) {
// Sorgu başarısızsa e-Arşiv'e düşmeyin; işi sonra tekrar deneyin
throw new Error(`Gelen kutusu sorgusu başarısız: HTTP ${inbox.status}`);
}
const to = inbox.body.data?.[0]?.attributes?.e_invoice_address;
const ref = { data: { type: 'sales_invoices', id: String(invoiceId) } };
// 2) İlişki adı e-Fatura'da "invoice", e-Arşiv'de "sales_invoice"
const body = to
? { data: { type: 'e_invoices', attributes: { scenario, to }, relationships: { invoice: ref } } }
: { data: { type: 'e_archives', attributes: eArchiveAttrs, relationships: { sales_invoice: ref } } };
const res = await parasut(`/${body.data.type}`, { method: 'POST', body: JSON.stringify(body) });
if (res.status !== 202) throw new Error(`Resmileştirme reddedildi: HTTP ${res.status}`);
return { type: body.data.type, jobId: res.body.data.id }; // 202 = iş kuyrukta, belge değil
}4. Adım: Resmileşen Belgenin Kimliğini Alma
İş done olduktan sonra satış faturasını active_e_document ilişkisiyle okuyun. İlişkinin type alanı e_archives, e_invoices ya da e-SMM için e_smms olur; id alanı da PDF ve durum sorguları için kullanacağınız e-belge kimliğidir.
curl -X GET "https://api.parasut.com/v4/{company_id}/sales_invoices/{invoice_id}?include=active_e_document" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Accept: application/json"
# Yanıtta: data.relationships.active_e_document.data = { "type": "e_archives", "id": "..." }5. Adım: e-Fatura Sonucunu Kontrol Etme ve Yeniden Gönderme
e-Fatura oluştuktan sonra GİB ve entegratör tarafındaki sonuç e-Fatura kaydına yazılır. GET /e_invoices/{id} yanıtında üç alana bakın:
| Alan | Açıklama |
|---|---|
| status | waiting (bekliyor), failed (başarısız), successful (başarılı) |
| status_code | GİB/entegratör durum kodu; status bu koddan türetilir, henüz belli değilse boş olabilir |
| status_message | Durum kodunun açıklaması; hata durumunda nedeni içerir, boş olabilir |
Durum failed ise PATCH /e_invoices/{id}/resend ile yeniden gönderebilirsiniz. Yanıt yine 202 ve bir trackable job'dır.
# Önce durumu okuyun
curl -X GET "https://api.parasut.com/v4/{company_id}/e_invoices/{e_invoice_id}" \
-H "Authorization: Bearer <ACCESS_TOKEN>" -H "Accept: application/json"
# status "failed" ise yeniden gönderin (yine 202 + trackable job)
curl -X PATCH "https://api.parasut.com/v4/{company_id}/e_invoices/{e_invoice_id}/resend" \
-H "Authorization: Bearer <ACCESS_TOKEN>" -H "Accept: application/json"- Durumu
failedolmayan e-Faturalar için, firmanın aktif e-Fatura entegrasyonu yoksa ya da aynı satış faturası için gönderim zaten sürüyorsa 422 döner. status_codeyeniden gönderime uygun değilse istek yine 202 ile kabul edilir, ancak işE-faturanız yeniden gönderime uygun değilhatasıylaerrorolarak biter. Uygun kodların listesi API belgesinde resendEInvoice işleminin açıklamasında yer alır.
6. Adım: PDF ve İmzalı UBL Alma
PDF ucu dosyanın kendisini değil, type: "e_document_pdfs" taşıyan bir JSON döner. İçinde url ve expires_at alanları bulunur. Bağlantı yalnızca expires_at zamanına kadar geçerlidir; süresi dolunca uca yeniden istek atın. Paraşüt rehberi bu linkin doğrudan müşteriyle paylaşılmamasını, PDF'in indirilip kendi sisteminizden iletilmesini ister.
curl -X GET "https://api.parasut.com/v4/{company_id}/e_archives/{e_archive_id}/pdf" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Accept: application/json"
# 200 yanıtı: data.type "e_document_pdfs", data.attributes.url ve data.attributes.expires_atİmzalı UBL (XML) için GET /e_archives/{id}/signed_ubl ve GET /e_invoices/{id}/signed_ubl uçları vardır. Dosya hazırsa 200 ile iner ya da sağlayıcıdaki dosyaya 302 ile yönlendirilir. Hazır değilse JSON:API değil düz metin signed ubl is not ready ile 404 döner ve dosya arka planda hazırlanır.
Polling Yerine Webhook Kullanmak
Paraşüt'ün sales_invoice modeli için update webhook'u yalnızca e-Fatura ya da e-Arşiv belgesi olan faturalar için gönderilir; e-SMM'si olanlar için gönderilmez. PDF oluştuğunda bu event'in verisine pdf_url alanı eklenir ve bu bağlantı 2 saat geçerlidir. Ancak webhook teslimatı garanti edilmez; resmî kurallar işin sonucunu her zaman GET /trackable_jobs/{id} ile doğrulamanızı ister. Kurulum ve alıcı tasarımı için Paraşüt webhook kurulum rehberine bakın.
Staging Ortamında Hata Senaryolarını Test Etme

Rehbere göre staging hesaplarında e-belge entegrasyonu varsayılan olarak "Dummy Integration" olarak ayarlıdır: faturalar resmileşir ama GİB'e gönderilmez, sonuçlar taklit edilir, belge doğrulaması ise gerçek ortamdaki gibi yapılır. Hata senaryolarını denemek için resmileştirmeden önce satış faturasının invoice_note alanına anahtar= değer; biçiminde direktif yazabilirsiniz. Değerlerde yalnızca İngilizce harf, rakam, boşluk, nokta ve virgül kullanılmalıdır; Türkçe karakter içeren direktifler dikkate alınmaz.
gib_status_code= 1195; gib_status_description= Beklenmedik bir hata olustu;
response_type= RED; response_description= Urunler eksik oldugu icin reddedildi;| Direktif | Etkisi |
|---|---|
| gib_status_code | e-Fatura için GİB durum kodu; 1300 başarılı, 1000, 1100, 1200, 1210, 1220 bekliyor, diğerleri hata |
| response_type / response_description | Ticari e-Fatura için alıcıdan red yanıtı ve gerekçesi |
| report_id + report_gib_status_code | e-Arşiv için GİB rapor kimliği ve durum kodu |
| e_archive_sms / e_archive_confirm | SMS onaylı e-Arşiv akışında onay hatası |
Sık Karşılaşılan Hatalar
| Belirti | Muhtemel neden | Çözüm |
|---|---|---|
| e-Arşiv isteğinde ilişki tanınmıyor | relationships.invoice kullanılmış | e-Arşiv'de sales_invoice, e-Fatura'da invoice |
| Belge "oluştu" sanıldı ama yok | 202 başarı sayıldı | Trackable job done olana kadar bekleyin |
| Trackable job sorgusu 404 | 15 dakikalık pencere geçti | Sonucu active_e_document ile faturadan okuyun |
| Resmileştirmede sipariş alanı hatası | order_no ya da order_date tek başına dolu | İkisini birlikte gönderin |
| Tarih hatası | Düzenleme tarihi aktivasyondan önce | issue_date değerini kontrol edin |
| resend 422 | status failed değil ya da gönderim sürüyor | Önce GET /e_invoices/{id} ile durumu okuyun |
| 403 | Yetki, paket ya da firma erişimi sorunu | Tekrar denemeyin, title alanını loglayın |
Genel hata ayıklama, 429 ve token yenileme kuralları için hata kodları ve rate limit rehberine bakın.
Sık Sorulan Sorular
Paraşüt API'de e-Fatura mı e-Arşiv mi keseceğimi nasıl anlarım?
Teknik karar GET /e_invoice_inboxes?filter[vkn]=... sorgusuyla verilir: sonuç doluysa e-Fatura, boşsa e-Arşiv. Sizin hangi belgeleri kullanmakla yükümlü olduğunuz ise API'de değil mevzuatta tanımlıdır; bunu mali müşavirinizle netleştirin.
202 yanıtı aldım, fatura resmileşti mi?
Hayır. 202, işin kuyruğa alındığını gösterir. data.id ile trackable job'ı sorgulayın; yalnızca status: "done" olduğunda e-belge oluşmuştur.
Trackable job'ı ne sıklıkla sorgulamalıyım?
Belge bir aralık önermez. Kısa bir bekleme ile başlayıp süreyi artıran bir sorgulama makul bir yaklaşımdır; önemli olan işin durumunu 15 dakikalık pencere dolmadan okumak ve rate limitinizi zorlamamaktır.
PDF linkini müşteriye e-postayla gönderebilir miyim?
Rehber bunu önermez. Bağlantının süresi expires_at ile sınırlıdır; PDF'i indirip kendi sisteminizden iletin, linki kalıcı olarak saklamayın.
Resmileşmiş bir e-Arşiv faturasını API ile iptal edebilir miyim?
e-Arşiv için belgelenen uçlar oluşturma, görüntüleme, PDF ve imzalı UBL'dir; e-Arşiv kaydına özel bir iptal ucu bu listede yoktur. Satış faturası tarafındaki iptal ucu ve resmileşmiş belgeler için izlenecek süreç konusunda mali müşavirinize danışın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Paraşüt entegrasyonu genel rehberi · Paraşüt API ile fatura kesme · e-SMM serbest meslek makbuzu · Paraşüt webhook kurulumu · E-ticaret siparişini Paraşüt'e aktarma · İrsaliye ve e-İrsaliye · e-Arşiv ve e-Fatura zorunluluğu