İçeriğe geç

Fiyat ve teklif

Portföy villalarının fiyatını Trimango hesaplar. Sezon fiyatı, en az gece kuralı, ek kişi, temizlik, kampanya ve erken rezervasyon indirimleri, ön ödeme oranı ve döviz kuru tek bir fiyat motorundan geçer. Trimango ekibinin panelde gördüğü tutar ile sizin API’den aldığınız tutar aynı girdide kuruşu kuruşuna aynıdır. Fiyatı kendi tarafınızda hesaplamayın; her zaman teklif uçlarını çağırın.

Uç Ne zaman Sınır
POST /quotes Tek villa için ayrıntılı kırılım: acente bir villayı seçti, rezervasyon formunu açtı 1 villa
POST /quotes/batch Çok villa, aynı tarih ve kişi sayısı: arama sonucu listesi 1–48 villa
POST /quotes/recheck Daha önce alınmış teklifleri yeniden doğrulamak: kayıtlı teklifler, talepten hemen önce 1–12 satır

Üç uç da istemci kimliğiyle çağrılır ve genel hız sınırına girer (bkz. Sınırlar ve önbellek). Alanların tam tanımı API başvurusunda.

Terminal window
curl -s "$TRIMANGO_BASE_URL/quotes" \
-u "$TRIMANGO_CLIENT_ID:$TRIMANGO_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"villa_id": "01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80",
"check_in": "2027-07-10",
"check_out": "2027-07-17",
"adults": 2,
"children": 1,
"heating": false
}'
quote.mjs
const BASE = process.env.TRIMANGO_BASE_URL; // ör. https://…/api/public/v1
const AUTH = "Basic " + Buffer.from(`${process.env.TRIMANGO_CLIENT_ID}:${process.env.TRIMANGO_CLIENT_SECRET}`).toString("base64");
const res = await fetch(`${BASE}/quotes`, {
method: "POST",
headers: { Authorization: AUTH, "Content-Type": "application/json" },
body: JSON.stringify({
villa_id: "01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80",
check_in: "2027-07-10",
check_out: "2027-07-17",
adults: 2,
children: 1,
}),
});
const quote = await res.json();
if (quote.bookable) {
console.log(`${quote.nights} gece, toplam ${quote.price.totals.total_try} TL`);
} else {
console.log("Rezervasyon yapılamaz:", quote.reason, quote.warnings);
}
Alan Zorunlu Açıklama
villa_id ya da slug Biri Villanın kimliği (uuid) ya da slug’ı. Kayıtlarınızda kimliği tutun; slug değişebilir.
check_in, check_out Evet YYYY-MM-DD. Giriş bugünden önce olamaz; konaklama 1–120 gece.
adults Evet En az 1.
children Hayır Varsayılan 0.
heating Hayır Havuz ısıtma isteniyorsa true. Varsayılan false.

coupon alanını göndermeyin. Portföy villalarında kupon geçmez.

Villa dolu ya da kurallara uymuyorsa da yanıt 200 döner. Rezervasyon talebi gönderilip gönderilemeyeceğini bookable söyler.

{
"villa": {
"id": "01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80",
"code": "V-1042",
"slug": "villa-defne",
"title": "Villa Defne",
"capacity": 6,
"max_guests": 7
},
"check_in": "2027-07-10",
"check_out": "2027-07-17",
"nights": 7,
"adults": 2,
"children": 1,
"currency": "EUR",
"fx_rate": 36.5,
"fx_date": "2027-03-02",
"bookable": true,
"reason": null,
"availability": { "free": true, "busy_nights": [] },
"rules": {
"min_nights": 7,
"min_nights_ok": true,
"check_in_days": [6],
"check_in_day_ok": true,
"max_nights": null,
"max_nights_ok": true
},
"unpriced_nights": [],
"warnings": [],
"price": {
"nightly": [
{ "date": "2027-07-10", "season": "Yüksek sezon", "list_price": 300, "price": 300, "last_minute": false, "gift": false, "campaign_percent": null },
{ "date": "2027-07-11", "season": "Yüksek sezon", "list_price": 300, "price": 300, "last_minute": false, "gift": false, "campaign_percent": null }
],
"lines": [
{ "kind": "stay", "label": "7 gece konaklama", "amount": 2100, "amount_try": 76650, "from_prepayment": false },
{ "kind": "early_booking", "label": "Erken rezervasyon %10", "amount": -210, "amount_try": -7665, "from_prepayment": false },
{ "kind": "cleaning", "label": "Temizlik", "amount": 100, "amount_try": 3650, "from_prepayment": false }
],
"promotions": [{ "type": "early_booking", "name": "Erken rezervasyon %10", "amount": 210 }],
"coupon": null,
"totals": {
"stay": 2100,
"discounts": 210,
"total": 1990,
"list_total": 2200,
"prepayment": 597,
"due_on_arrival": 1393,
"prepayment_rate": 30,
"damage_deposit": 500,
"total_try": 72635,
"list_total_try": 80300,
"prepayment_try": 21790.5,
"due_on_arrival_try": 50844.5,
"damage_deposit_try": 18250
},
"without_coupon": null,
"optional_fees": [{ "label": "Bebek yatağı", "amount": 10, "unit": "night" }],
"heating_fee": 350
}
}

Örnekte nightly kısaltıldı; gerçek yanıtta her gece için bir satır vardır.

Alan Anlamı
price.totals.total Misafirin ödeyeceği toplam, villanın para biriminde (currency).
price.totals.list_total İndirimsiz toplam (total + discounts). İndirim varsa üstü çizili fiyat olarak gösterebilirsiniz.
price.totals.stay İndirimsiz konaklama tutarı (gecelerin toplamı).
price.totals.discounts Toplam indirim, pozitif sayı.
price.lines[] Kalemler: konaklama, indirimler (eksi), ek kişi, temizlik, ısıtma, ücretler. label misafire gösterilebilir.
price.nightly[] Gece gece fiyat: sezon adı, liste fiyatı, uygulanan fiyat, son dakika ve hediye gece işaretleri.
price.optional_fees[] Misafirin isteğine bağlı ücretler (unit: konaklama, gece, kişi …). Toplama girmez; bilgi olarak gösterin.
price.heating_fee Giriş sezonunun havuz ısıtma ücreti (konaklama başına). null ise o sezonda ısıtma tanımlı değil. Isıtma toplama ancak heating: true gönderilirse girer.
price.totals.damage_deposit Hasar depozitosu. Girişte alınır, çıkışta iade edilir, toplama girmez. null ise yok.

price alanı iki durumda null olur: kişi sayısı villanın alabileceğinden fazlaysa ya da fiyatı girilmemiş gece varsa. Villa dolu olsa bile price hesaplanır; böylece “bu tarihler dolu, bu villa bu süre için şu kadar” diyebilirsiniz.

Misafir rezervasyon kesinleşirken ön ödemeyi (prepayment), kalanını girişte (due_on_arrival) öder. Ön ödeme oranı prepayment_rate (yüzde). Bazı indirimler ön ödemeden düşer; bu kalemlerde from_prepayment: true olur ve girişte kalan tutar değişmez. Ön ödemenin ya da kalanın tahsilatı Trimango’dadır (bkz. Rezervasyon).

Villanın fiyatı EUR, USD, GBP ya da TL olabilir; currency bunu söyler ve tutarlar bu para biriminde, 2 haneye yuvarlıdır. Misafirden ödeme her zaman TL alınır. Her tutarın TL karşılığı *_try alanlarındadır (total_try, prepayment_try, due_on_arrival_try, list_total_try, damage_deposit_try, lines[].amount_try).

  • Kur TCMB döviz satış kurudur: fx_rate (1 birim = X TL; TL villada 1) ve fx_date. Trimango kuru hafta içi günde iki kez (İstanbul saatiyle 10:00 ve 15:45) günceller.
  • TL tutarlar kuruşa yuvarlanır (yarım yukarı). prepayment_try toplamı aşmaz, due_on_arrival_try = total_try − prepayment_try, kalemlerin amount_try toplamı total_try’ı tutar. TL tutarları kendiniz çarpıp yeniden hesaplamayın; yanıttakini kullanın.
  • Teklifteki kur ve TL tutarlar, aynı anda açılan rezervasyon talebinde dondurulacak değerlerle aynıdır. Talepten sonra kur değişse de o rezervasyonun TL tutarları değişmez.
  • Kur henüz yoksa (TCMB verisi gelmemişse) fx_rate, fx_date ve *_try alanları null olur.

Misafir TL ödediği için acentelerinize TL tutarı (total_try) esas olarak göstermenizi öneririz; villanın kendi para birimindeki tutarı yanında bilgi olarak verebilirsiniz.

Uygulanan indirimler price.promotions[] içinde, adı ve tutarıyla gelir:

type Anlamı
campaign Kampanya. name kampanyanın adıdır, gösterilebilir. Gecelerde campaign_percent dolu olur.
early_booking Erken rezervasyon indirimi.
last_minute Son dakika indirimi. Gecelerde last_minute: true; indirim gecelik fiyata işlenmiştir.
gift_night Hediye gece. O gece gift: true ve ücretsizdir.

Her indirim lines[] içinde eksi tutarlı bir kalem olarak da görünür. Fırsat yoksa promotions boş dizidir ve list_total = total olur.

  • availability.free bütün gecelerin boş olduğunu, busy_nights konaklama içindeki dolu geceleri söyler.
  • rules girişteki en az gece (min_nights), en çok gece (max_nights) ve izinli giriş günlerini (check_in_days, ISO: 1 pazartesi … 7 pazar; boşsa her gün) ve isteğin bunlara uyup uymadığını (*_ok) verir. Acentenin tarih seçimini bunlarla yönlendirebilirsiniz.
  • unpriced_nights fiyatı girilmemiş gecelerdir; bu gecelerle satış yapılamaz.
  • warnings misafire gösterilebilecek kısa notlardır, ör. “Bu dönemde en az 7 gece konaklanabilir”.

bookable: false olduğunda reason ilk geçerli nedeni verir. Birden çok neden varsa şu sırayla ilki döner:

reason Anlamı Ne yapılabilir
closed Villa girişte satışa kapalı. Başka villa önerin.
capacity Kişi sayısı villanın kapasitesini ve kabul ettiği ek kişiyi aşıyor (villa.max_guests). Kişi sayısını ya da villayı değiştirin.
occupied En az bir gece dolu (availability.busy_nights). Başka tarih önerin; çok villa teklifinde next_free yardımcı olur.
min_stay Dönemin en az gece kuralına uymuyor (rules.min_nights). Konaklamayı uzatın.
max_stay En çok gece kuralı aşılıyor (rules.max_nights). Konaklamayı kısaltın.
check_in_day Giriş günü kurala uymuyor (rules.check_in_days). İzinli bir günde giriş seçin.
other Fiyatı olmayan gece, villa bulunamadı ya da giriş tarihi geçmiş. Tarihleri ya da villayı değiştirin.

bookable: false olan bir teklifle rezervasyon talebi gönderirseniz talep açılmaz (bkz. Rezervasyon).

Sizinle paylaşılmayan, yayında olmayan ya da arşivlenmiş bir villa için tek villa teklifi 404 döner. İstek alanları kurala uymuyorsa (geçmiş giriş, 120 geceden uzun konaklama, adults 0) 422 ve errors döner (bkz. Hatalar).

Arama sonucu gibi çok villayı aynı tarih ve kişi sayısıyla fiyatlamak için POST /quotes/batch kullanın. Bir istekte 1–48 villa gönderilebilir; tekrarlanan villa bir kez sayılır.

Terminal window
curl -s "$TRIMANGO_BASE_URL/quotes/batch" \
-u "$TRIMANGO_CLIENT_ID:$TRIMANGO_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"villa_ids": ["01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80", "01990c1f-2b3c-7d4e-8f50-6a7b8c9d0e1f"],
"check_in": "2027-07-10",
"check_out": "2027-07-17",
"adults": 4,
"children": 0
}'

Yanıt, istekte gönderdiğiniz kimlik (ya da slug) anahtarıyla bir nesnedir; her villa bir kez döner:

{
"01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80": {
"ok": true,
"reason": null,
"nights": 7,
"total": 1990,
"list_total": 2200,
"currency": "EUR",
"total_try": 72635,
"list_total_try": 80300,
"fx_rate": 36.5,
"fx_date": "2027-03-02",
"next_free": null
},
"01990c1f-2b3c-7d4e-8f50-6a7b8c9d0e1f": {
"ok": false,
"reason": "occupied",
"nights": 7,
"total": null,
"list_total": null,
"currency": "TRY",
"total_try": null,
"list_total_try": null,
"fx_rate": 1,
"fx_date": "2027-03-02",
"next_free": { "check_in": "2027-07-17", "check_out": "2027-07-24", "total": 58800, "total_try": 58800 }
}
}
  • Yalnız toplam döner, kırılım dönmez. Kırılım için seçilen villada POST /quotes çağırın.
  • Kuponsuz ve ısıtmasız hesaplanır.
  • ok tek villa teklifindeki bookable ile aynı anlamdadır; reason değerleri yukarıdaki tablodakilerdir.
  • Dolu (occupied) villada next_free, aynı gece sayısıyla ve haftanın aynı gününde giren en yakın boş konaklamadır (1–4 hafta önce ya da sonra; eşit uzaklıkta sonraki tarih), toplamıyla. Bulunamazsa null.
  • Bulunamayan ya da sizinle paylaşılmayan villa 404 değil, ok: false, reason: "other" döner; currency null olabilir.

Teklif saklanmaz ve kimliği yoktur; bir teklif, istendiği andaki fiyatın fotoğrafıdır. Sonradan şunlar değişebilir:

  • Müsaitlik: villa başka bir kanaldan ya da başka bir talep ile opsiyona alınabilir.
  • Fiyat: sezon fiyatı, kampanya, son dakika ve erken rezervasyon indirimleri değişebilir. Tarihe bağlı kampanyalar her gece İstanbul saatiyle 00:01’de başlar ve biter.
  • Kur: döviz fiyatlı villada TL tutarlar günde iki kez kurla değişir.

Bu değişiklikler webhook ile bildirilir (availability, price, reference / currency). Teklifleri önbelleğe alıyorsanız ilgili olay gelince önbelleği atın.

Fiyat kesin olarak rezervasyon talebi açıldığı anda dondurulur. Talepte acentenin gördüğü toplamı expected_total ile gönderin; tutar değiştiyse talep açılmaz ve güncel toplam döner (bkz. Rezervasyon).

Acente bir teklifi aldıktan bir süre sonra (ör. ertesi gün, müşterisiyle konuştuktan sonra) talep göndermek istediğinde fiyatı ve müsaitliği yeniden doğrulayın:

  • Tek villa, kırılım gerekiyor ya da ısıtma istenmiş: POST /quotes ucunu aynı girdiyle yeniden çağırın.
  • Kayıtlı birden çok teklif (ör. müşteriye gönderilmiş teklif listesi): POST /quotes/recheck ile tek istekte en çok 12 satırı doğrulayın.
Terminal window
curl -s "$TRIMANGO_BASE_URL/quotes/recheck" \
-u "$TRIMANGO_CLIENT_ID:$TRIMANGO_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "villa_id": "01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80", "check_in": "2027-07-10", "check_out": "2027-07-17", "adults": 2, "children": 1 },
{ "villa_id": "01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80", "check_in": "2027-08-07", "check_out": "2027-08-14", "adults": 2, "children": 1 }
]
}'
{
"items": [
{
"villa_id": "01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80",
"check_in": "2027-07-10",
"check_out": "2027-07-17",
"ok": true,
"reason": null,
"nights": 7,
"total": 1990,
"list_total": 2200,
"currency": "EUR",
"total_try": 72635,
"list_total_try": 80300,
"fx_rate": 36.5,
"fx_date": "2027-03-02",
"next_free": null
},
{
"villa_id": "01990c1e-7a4b-7c21-9f3e-2b1d5c6a7e80",
"check_in": "2027-08-07",
"check_out": "2027-08-14",
"ok": false,
"reason": "occupied",
"nights": 7,
"total": null,
"list_total": null,
"currency": "EUR",
"total_try": null,
"list_total_try": null,
"fx_rate": 36.5,
"fx_date": "2027-03-02",
"next_free": { "check_in": "2027-08-14", "check_out": "2027-08-21", "total": 2240, "total_try": 81760 }
}
]
}
  • Her satır kendi villasını, tarihini ve kişi sayısını taşır; aynı villa farklı tarihlerle birden çok kez gelebilir. Yanıt istekteki sırayla döner.
  • Kuponsuz ve ısıtmasız hesaplanır. Teklifte ısıtma istendiyse toplam tutmaz; o satırı POST /quotes ile heating: true göndererek doğrulayın.
  • Girişi geçmiş satır 422 değil, ok: false, reason: "other" döner; bu teklifi kendi kaydınızdan silebilirsiniz.
  • Dolu satırda next_free çok villa teklifindeki kuralla en yakın boş konaklamayı verir.

Tutar değiştiyse acenteye yeni tutarı gösterip onay alın; talepte expected_total olarak yeni tutarı gönderin.

  • Fiyatı kendi tarafında hesaplamak: gece fiyatı × gece sayısı toplamı vermez; en az gece, ek kişi, temizlik ve indirimler motorun işidir. Toplamı her zaman yanıttan alın.
  • TL’yi kendi kurunuzla çevirmek: *_try alanlarını kullanın. Trimango’nun kuruyla sizin kurunuz arasındaki fark talepte reservation:price-changed hatasına yol açar.
  • Teklifi uzun süre saklamak: webhook gelince ya da talepten önce yeniden doğrulayın.
  • Villayı slug ile kaydetmek: slug değişebilir. Kimliği (villa.id) saklayın.