WebhookAPI v4

Webhook Kullanım Rehberi

Webhook'lar, firmanızda bir kayıt oluşturulduğunda, güncellendiğinde veya silindiğinde Paraşüt'ün belirlediğiniz adrese POST isteği göndermesini sağlar. Bu rehber uç noktanızı hazırlamaktan client_key üretmeye, webhook oluşturmaktan gelen isteği doğrulamaya ve verilerinizi API ile eşitlemeye kadar tüm adımları anlatır. Webhook uçları aynı access_token ile çağrılır; eğer henüz yoksa OAuth rehberine bakın.

Bu rehber Paraşüt API v4 webhook uçlarını temel alır (base URL https://api.parasut.com/v4). Her alanın tam şeması API dokümantasyonunun WEBHOOK ve WEBHOOK İSTEKLERİ bölümlerindedir.

Başlamadan Önce

ACCESS_TOKENGeliştirici Portalı'ndan alınmış ve API paketi webhook içeren bir API istemcisiyle, OAuth Authorization Code akışında alınan Bearer token. Detay.
company_idWebhook'un dinleyeceği firmanın kimliği. GET /me?include=companies ile bulunur.
Ayarlar yetkisiListelemek ve görüntülemek için Ayarlar okuma yetkisi, oluşturmak, güncellemek ve silmek için Ayarlar tam yetkisi gerekir.
Base URLhttps://api.parasut.com/v4

Tüm istekler Authorization: Bearer ACCESS_TOKEN header'ı ile gönderilir; gövde taşıyan POST ve PATCH istekleri Content-Type: application/vnd.api+json kullanır. Token'ın ait olduğu kullanıcının firmada üçüncü taraf entegrasyon yetkisi de olmalıdır.

Erişim: Webhook uçlarını yalnızca Geliştirici Portalı'ndan alınmış ve API paketi webhook içeren bir API istemcisinin access token'ı ile çağırabilirsiniz. Paketiniz webhook içermiyorsa istekler 403 döner ve hatanın title değeri API client's package does not include webhooks olur. Geliştirici Portalı'ndaki bir API istemcisine ait olmayan bir access token ile yapılan istekler de 403 (Webhooks are only available to Developer Portal API clients) döner.

Mutlaka Bilmeniz Gerekenler

  • Gövdedeki data.type tekil webhook olmalıdır; webhooks gönderirseniz 422 alırsınız (3. adım).
  • uri internetten erişilebilen bir HTTPS adresi olmalıdır: http adresler kabul edilmez; özel ağ, localhost ve link-local adresler reddedilebilir; yönlendirmeler takip edilmez (1. adım).
  • client_key tam 64 karakterlik [A-Za-z0-9] bir değerdir ve API yanıtlarında hiçbir zaman dönmez; kendi tarafınızda güvenle saklayın (2. adım).
  • Her istekteki X-Client-Key header'ını sakladığınız client_key ile sabit zamanlı karşılaştırın, eşleşmeyen istekleri reddedin (4. adım).
  • Bağlantı 10 saniyede kurulmalı, yanıt 30 saniyede dönmelidir: isteği alır almaz 2xx dönün, uzun işleri arka planda yapın (5. adım).
  • Aynı event birden fazla kez gelebilir; tekrarları event_id ile ayıklayın ve event_id değerini yalnızca eşitlik için karşılaştırın (6. adım).
  • Sıra garanti edilmez: aynı kaydın isteklerini data.updated_at ile karşılaştırın, delete sonrasında gelenleri işlemeyin, event_date ile sıralamayın (6. adım).
  • Teslimat garanti edilmez: webhook isteklerini değişiklik bildirimi olarak kullanın ve verileri düzenli aralıklarla API'den eşitleyin (7. adım).
  • Tanımadığınız alanları, enum değerlerini ve header'ları yok sayın; gövdeye katı bir şema doğrulaması uygulamayın (4. adım).
  • Bazı event'ler her kayıt için gönderilmez: sales_invoice update, purchase_bill ve stock_movement istisnalarını Desteklenen Event'ler bölümünde okuyun.

Akışa Genel Bakış

1
HTTPS uç nokta
2
client_key
3
Webhook oluştur
4
Doğrula
5
2xx dön
6
Tekrar ve sıra
7
API ile eşitle
8
Yönet

1–3 kurulumdur ve bir kez yapılır; 4–6 gelen her istekte uygulanır; 7–8 sürekli bakım içindir.

Adım Adım Akış

1

HTTPS Uç Noktanızı Hazırlayın

Abone olduğunuz event gerçekleştiğinde webhook'un uri adresine Content-Type: application/json ile bir POST isteği gönderilir: bu isteği karşılayacak, internetten erişilebilen bir HTTPS uç noktası hazırlayın. Uç nokta aynı adreste yanıt vermeli; başka bir adrese yönlendirmemelidir.

curl — uç noktanızı dışarıdan deneyin
# Uç noktanız yönlendirme (3xx) dönmemeli; Paraşüt yönlendirmeleri takip etmez.
curl -sS -o /dev/null -w "%{http_code}\n" -X POST https://website.com/webhooks \
  -H "Content-Type: application/json" \
  -d '{}'
# Beklenen: 3xx dışında bir kod (X-Client-Key olmadığı için ör. 401)
HTTPS ve erişilebilir adres: uri HTTPS olmalıdır; http adresler kabul edilmez. uri internetten erişilebilen bir adres olmalıdır: özel ağ, yerel (localhost) ya da bağlantı-yerel (link-local) adreslere işaret eden bir uri oluşturma ve güncellemede 422 ile reddedilebilir ve bu adreslere webhook isteği gönderilmeyebilir.
Yönlendirmeler: Diğer 4xx ve 3xx durumları: teslim edilemedi ve yeniden denenmez; yönlendirmeler takip edilmez. Örneğin https://website.com/webhooks adresinden https://www.website.com/webhooks adresine ya da sondaki / için yapılan bir yönlendirme, event'in teslim edilmemesine yol açar.
İstekleri kaynak IP'ye göre de kısıtlamak isterseniz Paraşüt'ün çıkış IP adreslerini destek ekibinden talep edebilirsiniz.
2

client_key Üretin

Her webhook isteği bu değeri X-Client-Key header'ında taşır; isteğin Paraşüt'ten geldiğini bu değerle doğrularsınız (4. adım). Örneğin openssl rand -hex 32 komutuyla üretebilirsiniz.

Terminal — client_key üretme
openssl rand -hex 32
# Örnek çıktı (64 karakter):
# 3f9a1c27b84e4d6a9e0f5b2c7d18a4e6f0b3c9d2e5a7184b6c0d2f4e8a1b3c5d

# Node.js ile:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Biçim: Webhook oluştururken bir client_key belirlersiniz: A-Z, a-z ve 0-9 karakterlerinden oluşan, tam 64 karakterlik gizli bir değer. -, _, +, / ya da = gibi karakterler içeren değerler (ör. UUID) bu biçime uymaz ve 422 döner.
Saklama: client_key API yanıtlarında hiçbir zaman dönmez; değeri kendi tarafınızda güvenli biçimde saklayın. client_key silinemez, yalnızca değiştirilebilir. Değeri kaybederseniz ya da sızdığından şüphelenirseniz webhook'u 8. adımdaki gibi yeni bir client_key ile güncelleyin.
3

Webhook Oluşturun

Dinlemek istediğiniz model + action ikilisi için POST /{company_id}/webhooks isteği gönderin. Başarılı istek 201 ile oluşturulan webhook'u döner. Desteklenen ikililer için Desteklenen Event'ler bölümüne bakın.

curl — POST /webhooks
curl -X POST https://api.parasut.com/v4/{company_id}/webhooks \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
    "data": {
      "type": "webhook",
      "attributes": {
        "model": "contact",
        "action": "update",
        "uri": "https://website.com/webhooks",
        "client_key": "3f9a1c27b84e4d6a9e0f5b2c7d18a4e6f0b3c9d2e5a7184b6c0d2f4e8a1b3c5d"
      }
    }
  }'
AlanTip / ÖrnekAçıklama
data.typeenum (zorunlu)Tekil webhook
attributes.modelenum (zorunlu)Event'leri dinlenecek kaynak: shipment_document, stock_movement, product, contact, sales_invoice, stock_update, company, purchase_bill, inbound_e_invoice
attributes.actionenum (zorunlu)Dinlenecek işlem: create | update | delete
attributes.uristring (zorunlu)Event'lerin gönderileceği adres; HTTPS olmalıdır (^https://), en fazla 2048 karakter
attributes.client_keystring (zorunlu)Tam 64 karakter [A-Za-z0-9]; webhook isteklerinde X-Client-Key header'ı olarak gönderilir, yanıtlarda dönmez

Örnekteki client_key yalnızca biçimi gösterir; 2. adımda kendi ürettiğiniz değeri gönderin.

Yanıt — 201 Created (örnek)
{
  "data": {
    "id": "42",
    "type": "webhook",
    "attributes": {
      "model": "contact",
      "action": "update",
      "uri": "https://website.com/webhooks",
      "company_id": 123,
      "created_at": "2025-01-10T10:00:00.000Z",
      "updated_at": "2025-01-10T10:00:00.000Z"
    }
  }
}
data.type: İstek gövdesindeki data.type tekil webhook olmalıdır, webhooks değil.
Her event için tek webhook: Webhook kayıtları API istemcisine (client_id) aittir: aynı firmada her istemci yalnızca kendi webhook'larını görür ve yönetir. Bir istemci, bir firma için her model + action ikilisinden yalnızca bir webhook tanımlayabilir. model ve action webhook oluşturulduktan sonra değiştirilemez.
500 ve 503: 500 veya 503 aldığınızda webhook yine de oluşmuş olabilir; isteği tekrarlamadan önce webhook'ları listeleyip kontrol edin (aynı model + action için ikinci istek 422 döner).
4

Gelen İsteği Doğrulayın

İsteğin Paraşüt'ten geldiğini doğrulamak için header'daki değeri sakladığınız client_key ile karşılaştırın. Gövdenin alanları Webhook İsteğinin Gövdesi bölümünde açıklanır.

Gelen istek — POST {uri}
POST /webhooks HTTP/1.1
Host: website.com
Content-Type: application/json
X-Client-Key: <client_key>

{
  "event_id": "9f2c4e7a1b3d5f60718293a4b5c6d7e8",
  "company_id": 123,
  "resource": "contact",
  "action": "update",
  "event_date": "2025-01-10T10:55:00Z",
  "data": {
    "id": 456,
    "company_id": 123,
    "created_at": "2025-01-09T08:00:00.000Z",
    "updated_at": "2025-01-10T10:54:59.123Z",
    "data": { "id": "456", "type": "contacts", "attributes": { "name": "..." } }
  }
}
Node.js — X-Client-Key doğrulama
const crypto = require('crypto');
const express = require('express');

const app = express();
// Webhook'u oluştururken gönderdiğiniz client_key; güvenli bir yerden okuyun.
const CLIENT_KEY = Buffer.from(process.env.WEBHOOK_CLIENT_KEY || '');

function hasValidClientKey(req) {
  const received = Buffer.from(req.get('X-Client-Key') || '');
  // timingSafeEqual farklı uzunluklarda hata fırlatır; önce uzunlukları karşılaştırın.
  if (CLIENT_KEY.length !== 64 || received.length !== CLIENT_KEY.length) return false;
  return crypto.timingSafeEqual(received, CLIENT_KEY);
}

// jobs: kendi kalıcı kuyruğunuz (ör. bir veritabanı tablosu ya da mesaj kuyruğu)
// Varsayılan 100kb sınırı büyük gövdelerde 413 döner; 413 yeniden denenmez.
app.post('/webhooks', express.json({ limit: '5mb' }), async (req, res) => {
  if (!hasValidClientKey(req)) {
    return res.sendStatus(401); // Önerimizdir; durum kodu belirtilmemiştir.
  }
  await jobs.enqueue(req.body); // Kısa sürmeli: event'i yalnızca kuyruğa yazın.
  res.sendStatus(200);          // Hemen 2xx dönün (5. adım).
});
Sabit zamanlı karşılaştırma: Zamanlama saldırılarına karşı sabit zamanlı bir karşılaştırma kullanın (ör. Ruby'de Rack::Utils.secure_compare, Node.js'te crypto.timingSafeEqual) ve eşleşmeyen istekleri reddedin.
Eşleşmeyen istek için hangi durum kodunun dönüleceği belirtilmemiştir; isteği reddetmeniz yeterlidir. Önerimiz 401 dönmenizdir. 408 ve 429 dışındaki 4xx yanıtlar yeniden denenmez: reddettiğiniz istek bu event için tekrar gönderilmez.
Bilinmeyen değerler: API yanıtlarına ve webhook isteklerine yeni alanlar, enum alanlarına yeni değerler, webhook isteklerine yeni header'lar eklenebilir. API yanıtlarında ve webhook isteklerinde tanımadığınız model, action ya da başka bir enum değeri gelirse hata vermeyin, yok sayın; tanımadığınız alanları ve header'ları da yok sayın.
5

Hemen 2xx Dönün

İsteği doğruladıktan sonra event'i kalıcı bir kuyruğa yazın ve yanıtı bekletmeden 2xx dönün. Event'i işleme, API'den veri okuma gibi uzun işleri kuyruktan ayrı bir süreçte yapın.

Node.js — kuyruktaki event'leri işleme
// Kuyruktaki event'leri HTTP isteğinden bağımsız, ayrı bir süreçte işleyin.
jobs.process(async (event) => {
  await handleEvent(event); // Tekrar ve sıra kontrolü: 6. adım
});
Zaman aşımı: Endpoint'iniz 2xx döndüğünde istek teslim edilmiş sayılır. Bağlantı 10 saniyede kurulamazsa ya da yanıt 30 saniyede gelmezse istek başarısız sayılır. Uzun süren işleri isteği aldıktan sonra arka planda yapın ve hemen 2xx dönün.

Teslimat ve yeniden deneme

DurumNe olur
2xxTeslim edildi
5xx, 408, 429, zaman aşımı, bağlantı ya da SSL hatasıArtan aralıklarla 10 kereye kadar, yaklaşık 4–5 saat boyunca yeniden denenir; sonra bu event için istek gönderilmez
Diğer 4xx, 3xxYeniden denenmez; yönlendirmeler takip edilmez
Değişebilir değerler: Zaman aşımı süreleri, deneme sayısı ve deneme aralıkları zamanla değişebilir.
Devre dışı bırakma: Sürekli başarısız olan webhook'lar devre dışı bırakılabilir.
6

Tekrarları ve Sırayı Yönetin

Kuyruktan aldığınız her event'i işlemeden önce daha önce işlenip işlenmediğini ve aynı kayıt için daha yeni bir veri olup olmadığını kontrol edin.

Node.js — tekrar ve sıra kontrolü
async function handleEvent(event) {
  // event_id webhook başınadır; firma + model + action ile birlikte saklayın.
  const eventKey = [event.company_id, event.resource, event.action, event.event_id].join(':');

  // 1) Tekrar: aynı event_id daha önce işlendiyse atlayın.
  if (await db.processedEvents.has(eventKey)) return;

  // 2) Sıra: aynı kaydı resource + data.id ile bulun.
  const key = event.resource + ':' + event.data.id;
  const record = await db.records.get(key);

  if (record && record.deleted) {
    // Silinmiş kayıt için sonradan gelen create/update işlenmez.
  } else if (event.action === 'delete') {
    await db.records.set(key, { deleted: true });
  } else if (!record || Date.parse(event.data.updated_at) >= Date.parse(record.updated_at)) {
    // updated_at değeri daha eski olan isteği uygulamayın.
    await db.records.set(key, { updated_at: event.data.updated_at, data: event.data });
  }

  await db.processedEvents.add(eventKey);
}
Tekrar gelen istekler: Aynı event size birden fazla kez ulaşabilir; tekrarları event_id ile ayıklayın. event_id: Event'in bu webhook için kimliği; aynı event'in tekrar gönderimlerinde değişmez. Tekrar gelen istekleri ayıklamak için kullanın; biçimine güvenmeyin, yalnızca eşitlik için karşılaştırın.

Sıralama garantisi yoktur

Sıra: Webhook istekleri, işlemlerin Paraşüt'te gerçekleştiği sırayla gelmeyebilir; sıra garanti edilmez. Örneğin bir kayıt art arda iki kez güncellendiyse ikinci güncellemenin isteği ilkinden önce gelebilir; bir kaydın update isteği create isteğinden önce gelebilir. event_date sıralama için uygun değildir.
Sıralama kuralları: Gelen istekleri şu kurallarla değerlendirin:
  • Aynı kayda (resource + data.id) ait istekleri data.updated_at değerine göre karşılaştırın; updated_at değeri daha eski olan bir isteği daha yenisinin üzerine işlemeyin.
  • Bir kayıt için delete isteği aldıktan sonra aynı kayda ait gelen create ve update isteklerini işlemeyin. Kaydın son güncellemesine ait istek, silme isteğinden sonra ulaşabilir; silinmiş bir kaydı bu istekle yeniden oluşturmayın.
  • Kaydın güncel hâline ihtiyacınız olduğunda onu API'den okuyun.
7

Verileri API ile Eşitleyin

Webhook isteğini bir değişiklik bildirimi olarak kullanın: kaydın güncel hâlini gerektiğinde API'den okuyun ve verilerinizi düzenli aralıklarla API'den eşitleyin. Endpoint'iniz yeniden deneme süresinden uzun süre erişilemez kalırsa o event'ler için istek gönderilmez; bu boşluğu da eşitleme kapatır.

curl — kaydın güncel hâlini okuma (GET /contacts/{id})
curl -X GET https://api.parasut.com/v4/{company_id}/contacts/{id} \
  -H "Authorization: Bearer ACCESS_TOKEN"

Teslimat garantisi yoktur

Teslimat: Webhook istekleri en iyi çaba ilkesiyle gönderilir; her değişiklik için bir istek gönderileceği garanti edilmez. Kısa sürede art arda değişen bir kayıt için yalnızca son hâli gönderilebilir: örneğin bir kayıt için create isteği hiç gelmeden update ya da delete isteği gelebilir. Kayıtların eksiksiz bir kopyasını tutmanız gerekiyorsa webhook isteklerini bir değişiklik bildirimi olarak kullanın ve verileri düzenli aralıklarla API'den eşitleyin.
8

Webhook'larınızı Yönetin

Webhook'larınızı listeleyin, görüntüleyin, uri veya client_key değerini güncelleyin ve artık ihtiyacınız olmayanları silin. Listelemek ve görüntülemek için Ayarlar okuma, diğer işlemler için Ayarlar tam yetkisi gerekir.

Listeleme

curl — GET /webhooks
curl -X GET https://api.parasut.com/v4/{company_id}/webhooks \
  -H "Authorization: Bearer ACCESS_TOKEN"
API istemcisinin bu firmadaki webhook'larını listeler; başka istemcilerin webhook'ları görünmez. Sayfalama yoktur; liste, istemcinin bu firmadaki model + action ikilileriyle sınırlıdır. client_key yanıtta dönmez.

Görüntüleme

curl — GET /webhooks/{id}
curl -X GET https://api.parasut.com/v4/{company_id}/webhooks/{id} \
  -H "Authorization: Bearer ACCESS_TOKEN"
Webhook bulunamazsa ya da başka bir istemciye aitse 404 döner.

Güncelleme ve client_key değiştirme

curl — PATCH /webhooks/{id}
curl -X PATCH https://api.parasut.com/v4/{company_id}/webhooks/{id} \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
    "data": {
      "type": "webhook",
      "attributes": {
        "client_key": "72dd4f0ed26ed1e46303a06fb37b856e4df9276490fe18ac97ad3268229c9e38"
      }
    }
  }'

Webhook'un uri veya client_key değerini günceller; yalnızca gönderdiğiniz alanlar değişir. Başarılı istek 200 ile güncellenen webhook'u döner.

model ve action değişmez: model ve action webhook oluşturulduktan sonra değiştirilemez. Başka bir event'i dinlemek için yeni bir webhook oluşturun, artık ihtiyacınız olmayanı silin. İstekte model ve action göndermeyin; webhook'un mevcut değerinden farklı bir değer 422 döner.
client_key değiştirme: client_key gönderilmezse mevcut değer korunur; yeni bir değer gönderildiğinde sonraki webhook istekleri bu değerle yapılır. client_key boş ya da null gönderilerek silinemez. uri değiştiriliyorsa HTTPS olmalıdır.
Önerimiz: client_key değiştirirken doğrulamanızın kısa bir süre hem eski hem yeni değeri kabul etmesini sağlayın; böylece geçiş sırasında gelen istekleri reddetmezsiniz.

Silme

curl — DELETE /webhooks/{id}
curl -X DELETE https://api.parasut.com/v4/{company_id}/webhooks/{id} \
  -H "Authorization: Bearer ACCESS_TOKEN"
# Başarılı yanıt: 204 No Content (gövde yok)

Webhook'u siler; bu webhook için artık istek gönderilmez. Başarılı istek 204 ve boş gövde döner.

Desteklenen Event'ler

Her webhook tek bir model + action ikilisini dinler. data.data kaydın JSON:API gösterimidir, data.included kayıtla birlikte gönderilen ilişkili kaynaklardır. Her modelin gövde şeması API dokümantasyonunun WEBHOOK İSTEKLERİ bölümündedir.

modelcreateupdatedeletedata.datadata.included
shipment_document (İrsaliye)✓✓✓shipment_documentsstock_movements
stock_movement (Stok hareketi)✓✓✓stock_movementsproduct
product (Ürün)✓✓✓productsYok
contact (Müşteri / Tedarikçi)✓✓✓contactscontact_people (delete event'inde yer almaz)
sales_invoice (Satış faturası)✓✓–sales_invoicesdetails, details.product, contact, active_e_document, failed_e_invoice
stock_update (Stok güncelleme)✓––stock_updatesdetails, details.product, details.warehouse
company (Firma)–✓––Yok; data düz gövdedir
purchase_bill (Fiş / Fatura)✓✓–purchase_billsdetails, details.product, supplier
inbound_e_invoice (Gelen e-Fatura)✓––e_invoicesYok
Bu tabloya zamanla yeni model ve action değerleri eklenebilir.

Her kayıt için gönderilmeyen event'ler

Bazı event'ler her kayıt için gönderilmez:

sales_invoice update: yalnızca e-Fatura ya da e-Arşiv belgesi olan (relationships.active_e_document tipi e_invoices ya da e_archives) faturalar için gönderilir; e-SMM'si olan faturalar için gönderilmez. Teklifler ve tekrarlayan fatura şablonları (item_type: estimate, recurring_invoice, recurring_estimate, recurring_export) için gönderilmez. create bu türler için de gönderilir; gerekiyorsa item_type ile ayıklayın.
purchase_bill create ve update: gelen bir e-Faturaya bağlı (relationships.active_e_document dolu) fiş/faturalar ve tekrarlayan fiş/fatura şablonları (item_type: recurring_purchase_bill) için gönderilmez. Gelen e-Faturaları inbound_e_invoice event'iyle izleyin.
stock_movement: stok güncellemesinden ve depo transferinden doğan stok hareketleri için create, update ve delete gönderilmez. Stok güncellemelerini stock_update event'iyle izleyin; depo transferleri için webhook yoktur.

Silme event'leri

delete event'inin verisi: delete event'inde data, kaydın silinmeden hemen önceki hâlidir ve diğer event'lerle aynı yapıdadır; kayıtla birlikte silinen ilişkili kayıtlar data.included içinde yer almayabilir.

Tabloda delete için – işaretli modellerde silme event'i gönderilmez; bu kayıtların silindiğini verileri API'den eşitleyerek fark edin (7. adım).

Satış faturası PDF'i (pdf_url)

2 saat: Satış faturasının PDF'i oluştuğunda gönderilen sales_invoice update event'inin verisine pdf_url alanı eklenir. Bu bağlantı 2 saat geçerlidir. Alan data.data.attributes.pdf_url konumundadır.

company event'i

Düz gövde: Diğer event'lerden farklı olarak data JSON:API biçiminde değildir; firmanın alanlarını düz olarak içerir.

company event'inde ise data firmanın şu alanlarını düz olarak içerir: id, name, legal_name, tax_number, tax_office, mersis_no, city, district, occupation_field, category, owner_email, contact_person, contact_phone_number, e_invoice_vkn, e_invoicing_enabled, e_invoice_inbox, e_invoice_outbox, e_invoice_trade_registry, trial_status, trial_end_date, new_subscription_status, subscription_renewal_date, accessible_until, tmp_access_end_date, subscription_tmp_access_end_date, credit_balance, credit_service_balance, logo_url, created_at, updated_at.

Webhook İsteğinin Gövdesi

Gövdenin zarfı (event_id, company_id, resource, action, event_date, data) hepsinde aynıdır; data modele göre değişir.

Zarf alanları

AlanTip / ÖrnekAçıklama
event_idstringEvent'in bu webhook için kimliği; aynı event'in tekrar gönderimlerinde değişmez. Tekrar gelen istekleri ayıklamak için kullanın; biçimine güvenmeyin, yalnızca eşitlik için karşılaştırın
company_idintegerFirma ID
resourceenumWebhook'un model değeri
actionenumcreate, update veya delete
event_datedate-timeParaşüt'ün event'i işlediği zaman (ISO 8601, UTC). Kaydın değiştiği an değildir; sıralama için kullanmayın
dataobjectKaydın verisi (nesne)

data alanları

data, kaydın API v4'teki JSON:API gösterimini (data.data, varsa data.included) ve en üst seviyede id, company_id, created_at, updated_at alanlarını içerir. company event'i bu yapıda değildir (Desteklenen Event'ler bölümüne bakın).

AlanTip / ÖrnekAçıklama
data.idintegerKayıt ID; data.data.id ile aynı kaydı gösterir
data.company_idintegerFirma ID
data.created_atdate-timeKaydın oluşturulduğu zaman
data.updated_atdate-timeKaydın son değiştiği zaman; event'leri sıralamak için bunu kullanın
data.dataobjectKaydın JSON:API kaynak nesnesi (id, type, attributes, relationships)
data.includedarrayKayıtla birlikte gönderilen ilişkili kaynaklar; modele göre değişir
Örnekte görüldüğü gibi en üst seviyedeki data.id sayıdır (456), JSON:API nesnesindeki data.data.id ise metindir ("456").
Katı şema doğrulaması yapmayın: data'ya zamanla yeni alanlar, enum alanlarına yeni değerler eklenebilir. Bilinmeyen alanları ve değerleri yok sayın ve gövdeye katı bir şema doğrulaması uygulamayın; garanti edilen alanlar yukarıda listelenenlerdir.

Hata Yanıtları

Hata yanıtları JSON:API biçimindedir (Content-Type: application/vnd.api+json). Gövde, bir veya daha fazla hata nesnesi içeren bir errors dizisidir: title hatanın kısa açıklaması, detail alan adıyla birlikte tam açıklamasıdır; doğrulama hatalarında source.pointer hatalı alanı gösterir.

Hata yanıtı — 422 örneği
{
  "errors": [
    {
      "title": "must be https",
      "detail": "Uri must be https",
      "source": { "pointer": "/data/attributes/uri" }
    }
  ]
}
DurumNe zaman döner
400İstek gövdesinde data yok ya da data / data.attributes bir nesne değil; gövde geçerli bir JSON değil
401Access token geçersiz ya da süresi dolmuş veya kullanıcının bu company_id için erişimi yok
402Firmanın Paraşüt kullanım süresi sona ermiş
403API paketiniz webhook içermiyor, access token Geliştirici Portalı'ndaki bir API istemcisine ait değil, kullanıcının bu firmada gerekli Ayarlar yetkisi ya da üçüncü taraf entegrasyon yetkisi yok veya API istemcinizin bu firmaya erişimi yok
404Webhook (id) bulunamadı ya da başka bir API istemcisine ait
422Doğrulama hatası: data.type webhook değil; client_key biçimi geçersiz; uri geçersiz, HTTPS değil ya da kabul edilmeyen bir adres; model veya action geçersiz ya da bu model + action ikilisi desteklenmiyor; aynı model + action için zaten bir webhook var; mevcut bir webhook'un model veya action değeri değiştirilmek istendi
500, 503Paraşüt tarafında geçici bir sorun; isteği daha sonra yeniden deneyin
İki istisna: Bu biçimin iki istisnası vardır:
  • 402 yanıtında errors dizisi hata nesneleri değil, metinler içerir: {"errors": ["Paraşüt kullanım süreniz sona ermiş."]}.
  • Geçerli bir JSON olmayan istek gövdesi uca ulaşmadan 400 ile reddedilir; yanıt JSON:API değildir (Content-Type: application/json, {"error": "Invalid JSON"}).
Hata mesajları: Hata mesajları İngilizcedir ve zamanla değişebilir; hatayı programatik olarak ayırt etmek için HTTP durum kodunu ve source.pointer değerini kullanın.

Doğrulama kuralları istek şemalarında yer alır; isteği göndermeden önce bunları kendi tarafınızda kontrol etmenizi öneririz.

403 yanıtının sebepleri

Hatanın title değeri sebebi belirtir:

titleSebep
API client's package does not include webhooksAPI paketi webhook içermiyor
Webhooks are only available to Developer Portal API clientsAccess token bir API istemcisine ait değil
ForbiddenKullanıcının gerekli Ayarlar yetkisi yok
User has no 3rd party integration permission for company: 123Kullanıcının üçüncü taraf entegrasyon yetkisi yok
API client has no access to company: 123API istemcisinin bu firmaya erişimi yok

Hızlı Referans

Bu Rehberde Geçen Tüm Uç Noktalar

WEBHOOK İSTEĞİ

Paraşüt → POST {uri} (sizin uç noktanız), Content-Type: application/json, X-Client-Key header'ı. Beklenen yanıt: 30 saniye içinde 2xx.

Her uç noktanın tam parametre şeması için API dokümantasyonuna bakın.