Geliştirici rehberi
Talepleri, teklifleri ve anlaşmaları kendi uygulamanızdan yönetebilmeniz için REST API ve webhook desteği sunuyoruz.
Başlarken
Tüm istekler JSON konuşur ve aşağıdaki taban adrese gider. Yanıt alanları camelCase, tutarlar TL cinsinden sayıdır.
https://pazaryeri.kalfagen.com/api/v1- Hesabınıza girin, Hesabım → Geliştirici bölümünden bir API anahtarı oluşturun. Anahtarın tamamı yalnızca bir kez gösterilir.
- İhtiyacınız olan kapsamları (scope) seçin, anahtarı sunucu tarafında saklayın. Mobil uygulama veya tarayıcı koduna gömmeyin.
- İsteklerde
Authorization: Bearer pzk_...veyaX-API-Keybaşlığını gönderin.
Kimlik doğrulama
API anahtarı: sunucudan sunucuya erişim için. Yalnızca seçtiğiniz kapsamlara izin verir; anahtar yönetimi ve yönetici uçları anahtarla çağrılamaz. Varsayılan sınır dakikada 120 istektir, aşılırsa 429 döner.
Kullanıcı jetonu (JWT): kendi mobil uygulamanızda kullanıcıyı giriş yaptırmak için. POST /auth/login ile access (15 dk) ve refresh jetonu alırsınız; süre dolunca POST /auth/refresh ile yenilersiniz. Refresh jetonu her yenilemede değişir.
# Herkese açık: açık talepleri listele
curl "https://pazaryeri.kalfagen.com/api/v1/demands?status=COLLECTING&pageSize=5"
# API anahtarıyla: kendi profilim ve aboneliğim
curl -H "Authorization: Bearer pzk_xxxxxxxxxxxx" https://pazaryeri.kalfagen.com/api/v1/me
# Alıcı olarak talebe katıl (demands:write kapsamı gerekir)
curl -X POST https://pazaryeri.kalfagen.com/api/v1/demands/DEMAND_ID/join \
-H "Authorization: Bearer pzk_xxxxxxxxxxxx" -H "Content-Type: application/json" \
-d '{"quantity": 300, "deliveryCity": "Ankara", "paymentPref": "CHEQUE"}'API anahtarı kapsamları
| Kapsam | İzin verdiği işlem |
|---|---|
catalog:read | Sektörleri, kategorileri ve ürünleri okur (anahtarsız da açıktır). |
demands:read | Talepleri ve kendi katılım/teklif durumunuzu okur. |
demands:write | Alıcı: talep başlatır, talebe katılır veya katılımı geri çeker. |
bids:read | Tedarikçi: verdiği teklifleri okur. |
bids:write | Tedarikçi: teklif verir, düşürür, geri çeker; kazanılan ihaleyi onaylar veya reddeder. |
deals:read | Anlaşmaları ve (abonelik aktifse) karşı tarafın iletişim bilgilerini okur. |
deals:write | Anlaşma durumunu günceller, puan verir. |
profile:read | Profil, abonelik ve kullanım bilgisini okur. |
notifications:read | Bildirimleri okur. |
Hata biçimi ve sayfalama
Başarısız isteklerde HTTP durum kodu ile birlikte makinece okunabilir bir code ve Türkçe message döner.
{ "statusCode": 402, "code": "SUBSCRIPTION_REQUIRED",
"message": "Bu işlem için aktif bir aboneliğiniz olmalı. ..." }Sık görülen kodlar: VALIDATION_ERROR (400), UNAUTHORIZED (401), SUBSCRIPTION_REQUIRED ve PLAN_LIMIT (402), MISSING_SCOPE (403), RATE_LIMITED (429). Liste uçları page ve pageSize (en fazla 100) alır, { items, total, page, pageSize } döner.
Webhook'lar
Olayları sürekli sorgulamak yerine adresinize POST olarak alın. Adresi Hesabım → Geliştirici bölümünden ekleyin; imza sırrı yalnızca bir kez gösterilir. Adres https:// olmalı ve herkese açık bir sunucuya çıkmalıdır. Başarısız teslimatlar 1, 5, 30 dakika, 2 ve 6 saat sonra yeniden denenir. Aynı olay birden fazla gelebilir; id alanıyla tekilleştirin.
| Olay | Ne zaman |
|---|---|
demand.bidding_started | Talep dolup ihaleye çıktı (alıcılara ve ilgili tedarikçilere). |
demand.awarded | İhale sonuçlandı, kazanan tedarikçinin onayı bekleniyor. |
demand.completed | Kazanan onayladı, anlaşmalar açıldı. |
demand.cancelled | Talep iptal oldu (minimum miktara ulaşılamadı, teklif gelmedi vb.). |
bid.won | Teklifiniz kazandı veya yedekten kazanana yükseldi (tedarikçi). |
deal.created | Yeni anlaşma oluştu. |
deal.status_changed | Anlaşma durumu değişti. |
subscription.activated | Abonelik aktif edildi. |
subscription.expiring | Abonelik 3 gün içinde bitiyor. |
subscription.expired | Abonelik sona erdi. |
İmzayı doğrulama
Her istek X-Pazaryeri-Signature: t=ZAMAN,v1=İMZA başlığı taşır. İmza, ZAMAN.GÖVDE metninin sırrınızla HMAC-SHA256 değeridir. 5 dakikadan eski zaman damgalarını reddedin.
import { createHmac, timingSafeEqual } from 'crypto';
export function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = createHmac('sha256', secret).update(parts.t + '.' + rawBody).digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
// Gövde örneği
// { "id": "…", "type": "demand.awarded", "createdAt": "2026-10-07T12:00:00Z",
// "data": { "demandId": "…", "finalUnitPrice": 3.5 } }Önemli kurallar
- Platform firmalar arasında ödeme almaz; API'de ödeme uçları yoktur. Ödeme koşulları (peşin, çek, taksit, vade) teklifte bilgi olarak taşınır.
- Karşı tarafın iletişim bilgileri yalnızca anlaşma açıldıktan sonra ve aboneliği aktif kullanıcılara döner.
- Tedarikçilerin teklifleri birbirine gösterilmez; yalnızca kendi teklifinizin önde olup olmadığını görürsünüz.