Özet: Restoran mutfak, manav ve market zincirlerinde sebze-meyve maliyeti çoğu zaman sabah hali panosundan Excel’e elle aktarılır. Bu yazıda apibir Hal Fiyatları API ile Ticaret Bakanlığı Hal Kayıt Sistemi kaynaklı toptancı hali fiyatlarını çekmeyi, şehir/hal karşılaştırmasını, geçmiş seriyi ve market/mutfak maliyet otomasyonunu Node.js ile Python örnekleriyle adım adım entegre ediyoruz.
İçindekiler
- Neden Hal Fiyatları API’si kullanmalısınız?
- Uç noktalar ve alanlar
- Günlük fiyat çekme (prices)
- Hal listesi ve ürün sözlüğü
- Geçmiş fiyat serisi
- Pratik senaryolar: mutfak, manav/market, şehir karşılaştırması, enflasyon, alarm
- Tarımsal Ürün Fiyatları ve Döviz ile birlikte kullanım
- Sık yapılan hatalar
- Sık sorulan sorular
Taze sebze ve meyve fiyatı, restoran reçetesi ile manav raf fiyatının ortak girdidir. İstanbul Bayrampaşa’da sera domatesi ile Antalya hali karpuzu aynı gün farklı min/max/ortalama verir; maydanoz demet, karpuz kg, domates kg biriminde listelenir. Belediye sitesinden ekran görüntüsü veya PDF bülteni ile takipte tipik kırılma şudur: mutfak panosu dünkü ortalamayı gösterir, satın alma motorunuz ise bir gün geriden çalışır. apibir’in /hal/* uçları Hal Kayıt Sistemi kamuya açık fiyatlarını tek JSON zarfta sunar; belediye sitelerinden kazıma yapılmaz. Aşağıdaki rehber entegrasyonu uç nokta tablosu, örnek JSON ve kopyala-yapıştır kodlarla tamamlar.
Not: Bu API, hububat / yağlı tohum / TÜRİB ELÜS / TMO bülteni fiyatlarını kapsayan Tarımsal Ürün Fiyatları (/agriculture/*) servisinden ayrıdır. Burada odak toptancı hali sebze, meyve ve yesillik fiyatlarıdır.
Neden Hal Fiyatları API’si Kullanmalısınız?
Hal fiyatı tek bir “domates kuru” değildir. Operasyonunuzun ihtiyacına göre şu katmanlar ayrı ayrı gelir:
- Günlük toptancı fiyatı — min / max / ortalama; birim
kg,adet,demetveyakasa. - Şehir ve hali boyutu — aynı ürün İstanbul Bayrampaşa ile başka hali/şehirde farklı işlem görür.
- Kategori —
sebze,meyve,yesillikile sepeti daraltma. - Önceki gün karşılaştırması —
previousAvgvechangePercentile günlük oynaklık. - Geçmiş seri — mutfak bütçesi, enflasyon sepeti ve alarm eşiği için.
Manuel veya kazıma tabanlı kurulumda tipik kırılmalar:
- Gecikme: Sabah panosu 09:00 civarı oturur; mutfak panonuz hala önceki günü gösterir.
- Karışıklık: Hububat borsa fiyatı (buğday, ayçiçeği) ile hali taze ürün aynı “tarım” etiketi altında karışır.
- Tarihçe yok: “Son 30 günde domates kaç TL/kg oynadı?” sorusuna yanıt veremezsiniz.
- Kazıma kırılganlığı: Belediye HTML’i değişince scraper düşer; SOAP yeniden dağıtım yazılı protokol ister. Lisanslı API bunu hedeflemez.
API tabanlı kurgu üçünü birden çözer: günlük ~09:00 güncelleme, alanlar ayrı tutulur ve /hal/history ile geçmiş seri sorgulanabilir. Kod yazmadan günlük özet isteyen ekipler için apibir WhatsApp / e-posta raporları da aynı veri ailesini kullanır.
Uç Noktalar ve Alanlar
Temel adres: https://api.apibir.com/v1
| Uç | Ne döner |
|---|---|
GET /hal/prices |
Günlük toptancı hali sebze/meyve fiyatları |
GET /hal/markets |
Toptancı hali listesi |
GET /hal/products |
Ürün sözlüğü ve kategoriler |
GET /hal/history |
Ürün bazında geçmiş fiyat serisi |
Kimlik doğrulama tüm apibir uçlarında aynıdır:
Authorization: apikey APIBIR-8f2c...9d41
Accept: application/json
Yanıt zarfı diğer servislerle ortaktır: success, creditsUsed, date, market, currency, data[]. Her başarılı istek tipik olarak 1 kredi harcar; 4xx hataları kredi düşürmez. Ücretsiz plan yaklaşık 100 kredi/ay ile geliştirme ve deneme için yeterlidir. Güncelleme sıklığı: günlük (~09:00). Kaynak: Ticaret Bakanlığı Hal Kayıt Sistemi kamuya açık fiyatları.
/hal/prices sorgu parametreleri:
| Parametre | Örnek | Açıklama |
|---|---|---|
city |
istanbul |
Şehir kodu / adı |
market |
bayrampasa |
Toptancı hali kodu |
product |
domates |
Ürün kodu veya adı (opsiyonel) |
category |
sebze |
sebze | meyve | yesillik |
date |
2026-09-21 |
YYYY-MM-DD; varsayılan bugün |
Sık görülen alanlar (data[] satırları):
| Alan | Örnek | Açıklama |
|---|---|---|
product |
Domates (Sera) |
Görünen ürün adı |
productCode |
domates-sera |
Sabit ürün anahtarı |
category |
sebze |
Ürün kategorisi |
unit |
kg |
kg | adet | demet | kasa |
minPrice / maxPrice / avgPrice |
28.00 / 42.00 / 35.50 | Günlük en düşük, en yüksek, ortalama |
previousAvg / changePercent |
34.20 / 3.80 | Önceki ortalama ve yüzde değişim |
1. Adım: Günlük Fiyat Çekme
En sık kullanılan uç GET /hal/prices’tır. Şehir, hali, ürün veya kategori ile daraltın; tarih vermezseniz bugün (varsayılan) döner.
cURL — İstanbul hali, sebze kategorisi
curl --request GET \
--url "https://api.apibir.com/v1/hal/prices?city=istanbul&category=sebze" \
--header "authorization: apikey APIBIR-8f2c...9d41" \
--header "accept: application/json"
cURL — Bayrampaşa, domates
curl --request GET \
--url "https://api.apibir.com/v1/hal/prices?city=istanbul&market=bayrampasa&product=domates" \
--header "authorization: apikey APIBIR-8f2c...9d41" \
--header "accept: application/json"
Node.js (fetch)
async function halFiyatlari(params = {}) {
const url = new URL("https://api.apibir.com/v1/hal/prices");
for (const [k, v] of Object.entries(params)) {
if (v != null && v !== "") url.searchParams.set(k, String(v));
}
const res = await fetch(url, {
headers: { authorization: `apikey ${process.env.APIBIR_KEY}` }
});
if (!res.ok) throw new Error(`apibir ${res.status}`);
const body = await res.json();
return {
date: body.date,
market: body.market,
currency: body.currency,
rows: body.data,
creditsUsed: body.creditsUsed,
};
}
const sebze = await halFiyatlari({ city: "istanbul", category: "sebze" });
const domates = await halFiyatlari({
city: "istanbul",
market: "bayrampasa",
product: "domates",
});
console.log(sebze.date, sebze.rows?.length);
console.log(domates.rows?.[0]?.avgPrice, domates.rows?.[0]?.changePercent);
Python
import os, requests
HEADERS = {"authorization": f"apikey {os.environ['APIBIR_KEY']}"}
BASE = "https://api.apibir.com/v1"
def hal_prices(**params):
r = requests.get(
f"{BASE}/hal/prices",
params={k: v for k, v in params.items() if v is not None},
headers=HEADERS,
timeout=15,
)
r.raise_for_status()
body = r.json()
return body.get("date"), body.get("market"), body["data"]
date, market, rows = hal_prices(city="istanbul", category="sebze")
print(date, market, len(rows))
date, market, domates = hal_prices(
city="istanbul", market="bayrampasa", product="domates"
)
if domates:
print(domates[0]["avgPrice"], domates[0]["changePercent"], domates[0]["unit"])
Örnek yanıt (ürün sayfasındaki şemaya uygun, illüstratif):
{
"success": true,
"creditsUsed": 1,
"date": "2026-09-21",
"market": "bayrampasa",
"currency": "TRY",
"data": [
{
"product": "Domates (Sera)",
"productCode": "domates-sera",
"category": "sebze",
"unit": "kg",
"minPrice": 28.00,
"maxPrice": 42.00,
"avgPrice": 35.50,
"previousAvg": 34.20,
"changePercent": 3.80
},
{
"product": "Karpuz",
"productCode": "karpuz",
"category": "meyve",
"unit": "kg",
"minPrice": 8.50,
"maxPrice": 14.00,
"avgPrice": 11.20,
"previousAvg": 10.80,
"changePercent": 3.70
},
{
"product": "Maydanoz",
"productCode": "maydanoz",
"category": "yesillik",
"unit": "demet",
"minPrice": 12.00,
"maxPrice": 18.00,
"avgPrice": 15.00,
"previousAvg": 14.50,
"changePercent": 3.45
}
]
}
Maliyet motorunda genelde avgPrice kullanılır; üst bant senaryosu için maxPrice ile çapraz kontrol edin. Birim (unit) karışırsa kg ile demeti aynı kolona yazmayın — reçete dönüşümünü kendi ERP’nizde tutun.
2. Adım: Hal Listesi ve Ürün Sözlüğü
UI’de sabit string tutmak yerine önce sözlükleri çekin; productCode ve hali kodunu kendi veritabanınızda anahtar olarak saklayın.
curl --request GET \
--url "https://api.apibir.com/v1/hal/markets" \
--header "authorization: apikey APIBIR-8f2c...9d41"
curl --request GET \
--url "https://api.apibir.com/v1/hal/products" \
--header "authorization: apikey APIBIR-8f2c...9d41"
async function haliListesi() {
const res = await fetch("https://api.apibir.com/v1/hal/markets", {
headers: { authorization: `apikey ${process.env.APIBIR_KEY}` }
});
if (!res.ok) throw new Error(`apibir ${res.status}`);
const { data } = await res.json();
return data; // market kodları, şehir, ad ...
}
async function urunSozlugu() {
const res = await fetch("https://api.apibir.com/v1/hal/products", {
headers: { authorization: `apikey ${process.env.APIBIR_KEY}` }
});
if (!res.ok) throw new Error(`apibir ${res.status}`);
const { data } = await res.json();
return data; // productCode, name, category ...
}
const markets = await haliListesi();
const products = await urunSozlugu();
console.log(markets.length, products.length);
def markets():
r = requests.get(f"{BASE}/hal/markets", headers=HEADERS, timeout=15)
r.raise_for_status()
return r.json()["data"]
def products():
r = requests.get(f"{BASE}/hal/products", headers=HEADERS, timeout=15)
r.raise_for_status()
return r.json()["data"]
print(len(markets()), len(products()))
Sözlükleri günde bir kez (veya sürüm hash’i değişince) önbelleğe alın; her kullanıcı isteğinde tekrar çekmek gereksiz kredi tüketir. Fiyat poll’unda yalnızca /hal/prices çağırın.
3. Adım: Geçmiş Fiyat Serisi
Trend, volatilite ve alarm eşiği için GET /hal/history kullanılır. Ürün kodunu zorunlu düşünün; şehir/hali ile daraltın.
curl --request GET \
--url "https://api.apibir.com/v1/hal/history?product=domates-sera&city=istanbul&market=bayrampasa" \
--header "authorization: apikey APIBIR-8f2c...9d41"
async function fiyatGecmisi(product, extra = {}) {
const url = new URL("https://api.apibir.com/v1/hal/history");
url.searchParams.set("product", product);
for (const [k, v] of Object.entries(extra)) {
if (v != null) url.searchParams.set(k, String(v));
}
const res = await fetch(url, {
headers: { authorization: `apikey ${process.env.APIBIR_KEY}` }
});
if (!res.ok) throw new Error(`apibir ${res.status}`);
const { data } = await res.json();
return data; // [{ date, avgPrice, minPrice, maxPrice, ... }, ...]
}
const seri = await fiyatGecmisi("domates-sera", {
city: "istanbul",
market: "bayrampasa",
});
const son = seri?.[seri.length - 1];
console.log(son?.date, son?.avgPrice);
def hal_history(product, **params):
q = {"product": product, **params}
r = requests.get(
f"{BASE}/hal/history",
params=q,
headers=HEADERS,
timeout=15,
)
r.raise_for_status()
return r.json()["data"]
seri = hal_history("karpuz", city="istanbul")
print(seri[-1] if seri else None)
Mutfak bütçesinde “son 20 işlem günü ortalaması + %X tampon” kuralını history üzerinden hesaplayın; tek günlük spike’ı doğrudan menü fiyatına yansıtmayın.
4. Adım: Pratik Senaryolar
Restoran / zincir mutfak tedariki
Günlük reçete listesindeki ürünler için hali ortalamasını çekin; fire ve birim dönüşümü kendi stoğunuzda kalsın.
async function mutfakMaliyet(urunListesi, city, market) {
const { date, rows } = await halFiyatlari({ city, market });
const byCode = new Map((rows || []).map((r) => [r.productCode, r]));
return {
date,
lines: urunListesi.map(({ productCode, qty, fire = 0.05 }) => {
const r = byCode.get(productCode);
if (!r) return { productCode, ok: false };
const netQty = qty * (1 + fire);
return {
productCode,
ok: true,
unit: r.unit,
avgPrice: r.avgPrice,
lineCost: Number(r.avgPrice) * netQty,
changePercent: r.changePercent,
};
}),
};
}
// örnek: 12 kg sera domates + %5 fire
const kart = await mutfakMaliyet(
[{ productCode: "domates-sera", qty: 12, fire: 0.05 }],
"istanbul",
"bayrampasa"
);
console.log(kart.date, kart.lines);
Manav / market marj hesabı
def manav_marj(alis_avg, hedef_marj_yuzde=0.28):
"""Raf satış önerisi: hali ortalama + hedef marj."""
return round(alis_avg * (1 + hedef_marj_yuzde), 2)
date, market, rows = hal_prices(city="istanbul", market="bayrampasa", category="meyve")
for r in rows or []:
print(r["product"], r["avgPrice"], "→ raf", manav_marj(r["avgPrice"]))
Üst bant stok riski için maxPrice ile “kötümser alış” senaryosu da tutun; kampanya fiyatını yalnızca minPrice’a kilitlemeyin.
Şehir / hali karşılaştırması
async function sehirKarsilastir(productCode, cities) {
const table = [];
for (const city of cities) {
const { date, rows } = await halFiyatlari({ city, product: productCode });
const row = rows?.[0];
if (row) {
table.push({
city,
date,
avgPrice: row.avgPrice,
minPrice: row.minPrice,
maxPrice: row.maxPrice,
changePercent: row.changePercent,
});
}
}
table.sort((a, b) => (a.avgPrice || 0) - (b.avgPrice || 0));
return { product: productCode, cheapest: table[0], table };
}
Lojistik rotasında “en ucuz hali + nakliye” dengesi için bu tabloyu kendi km maliyetinizle birleştirin.
Gıda enflasyon sepeti
Sabit bir sepet (ör. domates, patates, soğan, limon, maydanoz) için her gün avgPrice toplayın; /hal/history ile aylık endeks üretin. Araştırma panosunda birim tutarlılığını (kg vs demet) ayrı kolonlarda tutun.
Fiyat alarmı
async function fiyatAlarmKur(productCode, maxAvg, city, market) {
const { date, rows } = await halFiyatlari({
product: productCode,
city,
market,
});
const row = rows?.[0];
if (!row) return { triggered: false, reason: "no_data", date };
const triggered = Number(row.avgPrice) >= Number(maxAvg);
return {
triggered,
date,
avgPrice: row.avgPrice,
threshold: maxAvg,
changePercent: row.changePercent,
message: triggered
? `${row.product} ${row.avgPrice} TL/${row.unit} — eşik aşıldı`
: `${row.product} ${row.avgPrice} TL/${row.unit} — eşik altında`,
};
}
5. Adım: Tarımsal Ürün Fiyatları ve Döviz ile Birlikte Kullanım
Gıda e-ticaret veya entegre mutfak / üretim panosunda üç katman sık bir arada durur:
- Hal Fiyatları API — sebze/meyve toptancı hali; taze ürün alış maliyeti (bu yazı).
- Tarımsal Ürün Fiyatları API — hububat / yağlı tohum / ELÜS–TMO; un, yağ, yem hammadde katmanı.
- Döviz Kurları / Geçmiş Kur API — ithal ambalaj veya ithal meyve USD/EUR maliyeti; fatura günü kuru.
def gida_maliyet_karti(hal_fn, agri_fn, fx_fn, vade_tarihi):
"""Hali taze + hububat + kur katmanı (şema örneği)."""
domates = hal_fn("domates-sera") # /hal/prices
bugday = agri_fn() # /agriculture/prices
kur = fx_fn(vade_tarihi) # geçmiş döviz
return {
"halDomatesAvg": domates.get("avgPrice"),
"hububatAverage": bugday.get("average"),
"tmoPrice": bugday.get("tmoPrice"),
"usdTry": kur.get("selling"),
}
Ürün kuralınızı “hali taze + ELÜS/TMO hububat + kur” üçlüsü olarak yazın; tek kaynağa güvenmek yerine çapraz kontrol operasyon ve denetimde işe yarar. İnce kart seviyesindeki Hal Fiyatları özetinin entegrasyon derinliği bu rehberdedir — ürün sayfası: apibir.com/apis/hal-fiyatlari. Hububat katmanı için ayrıca Tarımsal Ürün Fiyatları API rehberine bakın.
Sık Yapılan Entegrasyon Hataları
| Hata | Sonucu | Doğrusu |
|---|---|---|
Hububat fiyatını /hal/* içinde aramak |
Yanlış ürün / boş sonuç. | Sebze-meyve için /hal/*; hububat–ELÜS–TMO için /agriculture/*. |
| Belediye sitesini kazımak | HTML kırılınca üretim düşer; SOAP yeniden dağıtım protokol ister. | Hal Kayıt Sistemi kaynaklı lisanslı API kullanın. |
Görünen adı (product) anahtar yapmak |
İsim değişince join bozulur. | productCode ve hali/şehir kodunu saklayın. |
| Her UI tıklamasında sözlük çekmek | Gereksiz kredi tüketimi. | /markets ve /products önbelleğe alın; poll’da yalnızca /prices. |
| 09:00 öncesi “bugün tamam” varsaymak | Eksik veya önceki gün verisi. | Güncelleme günlük ~09:00; date alanını panoda gösterin. |
| Tek günlük spike’ı doğrudan menüye yazmak | Fiyat şoku / yanlış marj. | /history ile kayan ortalama + tampon kullanın. |
kg ile demet’i aynı kolonda toplamak |
Maliyet hesabı bozulur. | unit alanına göre dönüşüm tablosu tutun. |
no_data (404) görünce anahtarı silmek |
Gereksiz panik. | O gün/ürün için veri yok demektir; tarihi ve filtreyi kontrol edin. |
Sık Sorulan Sorular
Veriler nereden geliyor?
Ticaret Bakanlığı Hal Kayıt Sistemi kamuya açık fiyatları. Belediye sitelerinden kazıma yapılmaz; SOAP üzerinden yeniden dağıtım yazılı protokol gerektirir. apibir bu kamuya açık fiyatları JSON uçlarla sunar.
Tarımsal Ürün Fiyatları ile farkı nedir?
Hal Fiyatları sebze/meyve toptancı hali odaklıdır (/hal/*). Tarımsal Ürün Fiyatları hububat, yağlı tohum ve ticaret borsası / ELÜS / TMO göstergelerine odaklanır (/agriculture/*). Gıda panosunda ikisini ayrı katman tutun.
Ne sıklıkla güncellenir?
Günlük — tipik olarak sabah ~09:00. date alanı hangi güne ait olduğunu gösterir; panoda “son hali günü: …” etiketi kullanın.
Ücretsiz planda yeterli mi?
Ücretsiz plan yaklaşık 100 kredi/ay ile geliştirme, staging ve düşük frekanslı cron’lar için uygundur. Yoğun panolarda sözlükleri önbelleğe alıp yalnızca fiyat uçlarını poll edin. Başarılı istek 1 kredi; 4xx kredi düşürmez.
Kod yazmadan takip edebilir miyim?
Evet. apibir’in WhatsApp veya e-posta günlük raporları hali sebze/meyve özetini kodsuz iletebilir. Kapsam için hizmetler sayfasına bakın.
Hata kodları kredi düşürür mü?
4xx istemci hataları tipik olarak kredi düşürmez; başarılı 2xx yanıtlar creditsUsed ile düşer. Anahtarınızı APIBIR-8f2c...9d41 biçiminde maskeleyin; üretimde process.env.APIBIR_KEY / os.environ['APIBIR_KEY'] kullanın. Sık kodlar: invalid_api_key (401), insufficient_credits (402), invalid_parameter (422), no_data (404), rate_limited (429).
Başlamak için: Ücretsiz API anahtarı ile /hal/prices?city=istanbul ve /hal/history uçlarını deneyin. Restoran mutfak tedariki, manav/market marjı, şehir karşılaştırması, enflasyon sepeti ve fiyat alarmı senaryoları aynı entegrasyon deseniyle çözülür. Uç noktaların tamamı Hal Fiyatları API kapsamında; kimlik doğrulama ve hata kodları dokümantasyonda yer alır. Ücretsiz plan ~100 kredi/ay ile deneme için yeterlidir — apibir.com üzerinden anahtar alın ve ilk hali fiyat sorgunuzu bugün çalıştırın.