Satış süreci çoğu zaman faturayla değil, bir teklifle başlar. Müşteriye fiyat verirsiniz, müşteri kabul eder, sonra fatura kesilir. Bu adımları CRM'inizden ya da kendi sipariş panelinizden Paraşüt'e aktarmak istiyorsanız API'de iki ayrı yapı bulunduğunu bilmeniz gerekir: sales_offers kaynağı (teklif) ve sales_invoices içinde item_type: estimate ile tutulan proforma.

Bu yazıda teklif oluşturma, durum güncelleme, PDF ve e-posta paylaşımı, yorum ekleme, tekliften fatura üretme ve proformayı faturaya çevirme adımlarını Paraşüt'ün belgelediği alanlarla anlatıyoruz. Genel kurulum için Paraşüt entegrasyonu genel rehberine, fatura kesmenin kendisi için Paraşüt API ile fatura kesme yazısına bakabilirsiniz.

Teklif mi, proforma mı?

Teklif mi, proforma mı? Teklif, Proforma, Proformayı faturaya çevirme

Paraşüt'ün resmi sözlüğü iki kavramı ayrı satırlarda tanımlar:

KavramUç noktaTanım
Teklif/{company_id}/sales_offersAyrı bir kaynak; kendi durumu (accepted, rejected, waiting), PDF ve e-posta paylaşımı var
Proforma/{company_id}/sales_invoicesSatış faturası kaydı, item_type değeri estimate
Proformayı faturaya çevirmePATCH /sales_invoices/{id}/convert_to_invoiceStok hareketleri varsayılan depodan oluşur

Pratikte müşteriyle pazarlık ve onay süreci yürütüyorsanız sales_offers, faturaya çok yakın bir ön belge istiyorsanız proforma daha uygundur. Bu bir iş tercihidir; API iki yolu da destekler.

Teklif oluşturma: POST /sales_offers

Teklif oluşturma gövdesinde data.type sales_offers'tır. Alan tablosunda zorunlu işaretli tek nitelik issue_date'dir. Not: OpenAPI şemasının zorunlu alan listesinde item_type da geçer ama teklif niteliklerinde böyle bir alan tanımlı değildir. Bu tutarsızlık yüzünden ilk denemenizi staging hesabında yapın ve 422 dönerse errors[].source.pointer değerine bakın.

AlanAçıklama
issue_dateDüzenleme tarihi, YYYY-AA-GG (zorunlu)
due_dateSon tahsilat tarihi
descriptionAçıklama
contentTeklif içeriği (serbest metin)
currencyTRL, USD, EUR veya GBP
exchange_rateDöviz kuru
display_exchange_rate_in_pdfKurun PDF'te gösterilmesi
withholding_rateStopaj oranı
invoice_discount_type / invoice_discountpercentage veya amount ve indirim değeri
billing_address, billing_phone, billing_faxAdres ve iletişim bilgileri
tax_office, tax_number, city, district, is_abroadMüşteri vergi ve konum bilgileri
order_noSipariş numarası

status, archived, sharings_count ve tüm toplam alanları (net_total, gross_total, total_vat, total_discount vb.) salt okunurdur; göndermeyin. Müşteri relationships.contact ile, kalemler relationships.details altında sales_offer_details tipiyle bağlanır. Kalem niteliklerinden en sık kullanılanlar quantity, unit_price, vat_rate, description, discount_type ve discount_value'dur; ürün relationships.product ile bağlanır.

bash
curl -X POST "https://api.parasut.com/v4/$COMPANY_ID/sales_offers" \
  -H "Authorization: Bearer $PARASUT_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/json" \
  -d '{
    "data": {
      "type": "sales_offers",
      "attributes": {
        "issue_date": "2026-11-03",
        "due_date": "2026-11-17",
        "description": "Kurumsal web sitesi bakım teklifi",
        "currency": "TRL"
      },
      "relationships": {
        "contact": { "data": { "type": "contacts", "id": "CONTACT_ID" } },
        "details": {
          "data": [
            {
              "type": "sales_offer_details",
              "attributes": { "quantity": 12, "unit_price": 2500, "vat_rate": 20, "description": "Aylık bakım" },
              "relationships": { "product": { "data": { "type": "products", "id": "PRODUCT_ID" } } }
            }
          ]
        }
      }
    }
  }'

Başarılı istek 201 ile SalesOffers kaydını döner. Müşteri carisini ve ürünü önceden oluşturmak için cari hesap ve ürün yönetimi yazılarına bakabilirsiniz.

Teklifleri listeleme ve okuma

GET /{company_id}/sales_offers şu filtreleri kabul eder: filter[archived], filter[query], filter[invoice_status] ve filter[status]. Sıralama alanları id, issue_date, description, net_total_in_trl ve sales_invoice_id'dir. Liste ucunda geçerli include değerleri yalnızca contact ve sales_invoice'dır. Paraşüt'ün kurallarına göre bu listede belgede yalnızca page[number] tanımlıdır; page[size] belgelenmemiştir.

Kalemleri görmek için iki yol vardır: GET /sales_offers/{id}?include=details.product ya da GET /sales_offers/{id}/details?include=product. Tekil okumada ayrıca contact.contact_people.contact, contact.category, sales_invoice, activities.item, activities.done_by ve sharings.collaborator include edilebilir. Teklifi güncellemek için PUT /sales_offers/{id}, silmek için DELETE /sales_offers/{id} (204), arşiv için PATCH .../archive ve PATCH .../unarchive kullanılır.

bash
curl "https://api.parasut.com/v4/$COMPANY_ID/sales_offers?filter[archived]=false&sort=-issue_date&include=contact,sales_invoice" \
  -H "Authorization: Bearer $PARASUT_TOKEN" -H "Accept: application/json"

Teklif durumunu güncellemek

Teklif durumunu güncellemek: waiting, accepted, rejected

Teklifin status alanı oluşturma ve düzenleme gövdesinde salt okunurdur. Durumu değiştirmek için ayrı bir uç vardır: PATCH /{company_id}/sales_offers/{id}/update_status. Gövdede zorunlu tek alan status'tür ve şu değerlerden birini alır:

DeğerAnlamı
waitingBeklemede
acceptedKabul edildi
rejectedReddedildi
bash
curl -X PATCH "https://api.parasut.com/v4/$COMPANY_ID/sales_offers/$OFFER_ID/update_status" \
  -H "Authorization: Bearer $PARASUT_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{"data":{"type":"sales_offers","attributes":{"status":"accepted"}}}'

Müşteri kendi portalınızda "Kabul ediyorum" düğmesine bastığında bu isteği atmak, Paraşüt'teki teklif listesini güncel tutmanın en kısa yoludur.

Teklif PDF'i ve e-posta ile paylaşım

POST /{company_id}/sales_offers/{id}/pdf hemen PDF dönmez; 202 ile bir trackable job döner. Trackable job, Paraşüt'ün arka planda yürüttüğü işin durumunu sorguladığınız kayıttır. Belgeye göre oluşan PDF'in adresine trackable job yanıtındaki data.attributes.url alanından erişilir. İşin durumunu GET /{company_id}/trackable_jobs/{id} ile running değeri done ya da error olana kadar sorgularsınız.

bash
# 1) PDF işini başlat
curl -X POST "https://api.parasut.com/v4/$COMPANY_ID/sales_offers/$OFFER_ID/pdf" \
  -H "Authorization: Bearer $PARASUT_TOKEN" -H "Accept: application/json"
# yanıt: {"data":{"id":"JOB_ID","type":"trackable_jobs","attributes":{...}}}

# 2) İşi sorgula
curl "https://api.parasut.com/v4/$COMPANY_ID/trackable_jobs/JOB_ID" \
  -H "Authorization: Bearer $PARASUT_TOKEN" -H "Accept: application/json"

Teklifi Paraşüt üzerinden e-postayla göndermek için POST /{company_id}/sharings kullanılır. Bu uçta data.type sharing_forms'tur; e-posta bilgileri attributes.email altında (addresses, subject, body), paylaşılan teklif relationships.shareable altında sales_offers tipiyle verilir. Portal seçenekleri (has_online_collection, has_online_payment_reminder, has_referral_link) varsayılan olarak false'tur.

json
{
  "data": {
    "type": "sharing_forms",
    "attributes": {
      "email": {
        "addresses": "musteri@example.com",
        "subject": "Teklifimiz",
        "body": "Merhaba, teklifimizi ekte bulabilirsiniz."
      }
    },
    "relationships": {
      "shareable": { "data": { "type": "sales_offers", "id": "OFFER_ID" } }
    }
  }
}

Gönderimin durumunu öğrenmek için belgede tarif edilen yol şudur: teklifi GET ile okuyun, yanıttaki included içinde sharings tipindeki nesneyi bulun ve attributes.email_status alanına bakın.

Teklife yorum eklemek

Satış ekibinizin notlarını teklife yorum olarak düşebilirsiniz. POST /{company_id}/comments gövdesinde data.type comments, zorunlu alan comment'tir; ilişki relationships.commentable altında sales_offers tipiyle verilir. is_public: true gönderirseniz paylaşım iş birlikçilerine de bildirim gider.

json
{
  "data": {
    "type": "comments",
    "attributes": { "comment": "Müşteri 12 ay yerine 6 ay istedi, revize edilecek." },
    "relationships": {
      "commentable": { "data": { "type": "sales_offers", "id": "OFFER_ID" } }
    }
  }
}

Yorumları okurken bir tuzak var: GET /comments filter[...] kullanmaz. commentable_type ve commentable_id düz sorgu parametresidir ve tür CamelCase sınıf adıyla yazılır: ?commentable_type=SalesOffer&commentable_id=123. Gövdedeki tip ise çoğul snake_case'tir (sales_offers). Bir kayıtta en fazla 120 yorum olabilir, dosya eki API ile gönderilemez ve yorum güncelleme PATCH /comments/{id} ile yapılır.

Tekliften satış faturası oluşturmak

Tekliften satış faturası oluşturmak: Teklifi kalemleri ve müşterisiyle okuyun, Yanıttaki included dizisinden müşteri, kalemler ve ürünleri POST..., Yeni faturanın...

Belgede sales_offers için doğrudan "faturaya çevir" uç noktası yoktur. Paraşüt'ün Satış Faturası ve İrsaliye Rehberi bunun yerine şu akışı tarif eder:

  • Teklifi kalemleri ve müşterisiyle okuyun: GET /sales_offers/{id}?include=details.product,contact.
  • Yanıttaki included dizisinden müşteri, kalemler ve ürünleri POST /sales_invoices gövdesinin relationships alanına taşıyın.
  • Yeni faturanın relationships.sales_offer.data alanına teklifin id'sini ve type: "sales_offers" değerini ekleyin.
json
{
  "data": {
    "type": "sales_invoices",
    "attributes": { "item_type": "invoice", "issue_date": "2026-11-20", "currency": "TRL" },
    "relationships": {
      "contact": { "data": { "type": "contacts", "id": "CONTACT_ID" } },
      "sales_offer": { "data": { "type": "sales_offers", "id": "OFFER_ID" } },
      "details": {
        "data": [
          {
            "type": "sales_invoice_details",
            "attributes": { "quantity": 12, "unit_price": 2500, "vat_rate": 20 },
            "relationships": { "product": { "data": { "type": "products", "id": "PRODUCT_ID" } } }
          }
        ]
      }
    }
  }
}

Teklif listesinde filter[invoice_status] ve sales_invoice include değeri bulunur; böylece hangi tekliflerin faturaya bağlandığını takip edebilirsiniz. invoice_status filtresinin alabileceği değerler belgede listelenmemiştir.

Proforma: item_type estimate ve convert_to_invoice

Proforma, normal satış faturası uç noktasıyla oluşturulur; tek fark item_type değerinin estimate olmasıdır. Satış faturası listesinde filter[item_type] varsayılan olarak invoice, refund, estimate değerlerini kapsar, yani filtre vermezseniz proformalar da listede gelir.

json
{
  "data": {
    "type": "sales_invoices",
    "attributes": { "item_type": "estimate", "issue_date": "2026-11-03", "currency": "TRL" },
    "relationships": {
      "contact": { "data": { "type": "contacts", "id": "CONTACT_ID" } },
      "details": { "data": [ { "type": "sales_invoice_details",
        "attributes": { "quantity": 1, "unit_price": 10000, "vat_rate": 20 } } ] }
    }
  }
}

Proformayı faturaya çevirmek için PATCH /{company_id}/sales_invoices/{id}/convert_to_invoice kullanılır. Belgeye göre ürünlerin stok hareketleri varsayılan deponuz üzerinden oluşur. Bu ucun gövdesi satış faturası şemasını kullanır ve şemada item_type ile issue_date zorunludur. Hangi alanların dönüştürmede dikkate alındığı ayrıca açıklanmadığından gövdeyi aşağıdaki gibi en sade hâliyle gönderip sonucu staging'de kontrol edin.

bash
curl -X PATCH "https://api.parasut.com/v4/$COMPANY_ID/sales_invoices/$ESTIMATE_ID/convert_to_invoice" \
  -H "Authorization: Bearer $PARASUT_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{"data":{"type":"sales_invoices","attributes":{"item_type":"invoice","issue_date":"2026-11-20"}}}'

Dönüşen fatura artık normal bir satış faturasıdır; e-Fatura veya e-Arşiv ile resmileştirme adımı için e-Fatura ve e-Arşiv gönderme yazısına geçebilirsiniz.

Sık Sorulan Sorular

Teklifi tek istekle faturaya çevirebilir miyim?

Belgede sales_offers için böyle bir uç nokta yoktur. Teklifi okuyup yeni bir satış faturası oluşturur ve relationships.sales_offer ile bağlarsınız. Tek istekle dönüşüm yalnızca proforma (item_type: estimate) için convert_to_invoice ile yapılır.

Teklif durumunu oluştururken gönderebilir miyim?

Hayır. status oluşturma ve düzenleme gövdesinde salt okunurdur. Durumu PATCH /sales_offers/{id}/update_status ile waiting, accepted ya da rejected olarak değiştirin.

Teklif PDF'i neden hemen gelmiyor?

PDF ucu 202 ve bir trackable job döner. PDF adresi, iş tamamlandığında trackable job yanıtındaki data.attributes.url alanında yer alır. 202 yanıtı PDF'in hazır olduğu anlamına gelmez.

Yorum listesinde neden 422 alıyorum?

Büyük olasılıkla commentable_type eksik ya da yanlış yazılmıştır. Değer SalesOffer gibi CamelCase olmalıdır. Ayrıca page[size] 25'ten büyükse de 422 döner.

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 · Paraşüt e-Fatura ve e-Arşiv · Paraşüt API cari hesap · E-ticaret siparişini Paraşüt'e aktarma · İşletme entegrasyonları rehberi