Vebhuk - nəsə baş verdikdə GREM-in sizin URL-ə göndərdiyi POST sorğusudur: tapşırıq tamamlanır, elan və ya lid dəyişir. Abunəliklərin idarə edilməsi üçün webhooks scope-u lazımdır və ödənişsizdir. Agentliyin vebhukları agentlik səviyyəli açarla idarə olunur; agent səviyyəli açar 403 alır.
Abunə olmaq
curl -X POST https://developers.grem.capital/api/v1/webhooks \
-H "Authorization: Bearer gsk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/grem-hook","events":["content.completed","content.failed","lead.created"]}'
{ "id": "...", "url": "https://example.com/grem-hook", "events": [...], "status": "active",
"failureCount": 0, "lastDeliveryAt": null, "secret": "whsec_..." }
url- standart portda (443) ictimaihttps://ünvanı, daxilindəuser:passwordolmadan. Başqa portlar, ünvanda giriş məlumatları, şəxsi, lokal və daxili ünvanlar rədd edilir (400). Port qaydası ünvanı təyin edərkən tətbiq olunur: əvvəllər başqa portda saxlanmış endpoint-lər çatdırılmaları almağa davam edir.events- aşağıdakı siyahıdan ən azı bir hadisə; naməlum adlar atılır.secret- imza sirri. O, yalnız bir dəfə qaytarılır - onu saxlayın.- Hesab başına 10 ünvana qədər, ayrıca isə test açarları ilə yaradılmış 10 sandbox ünvanına qədər; 11-ci ünvan
422 business_ruleilə rədd edilir. - Test açarı ilə yaradılmış endpoint-lər sandbox endpoint-ləridir: onlar yalnız sandbox tapşırıqlarının hadisələrini alır (Sandbox).
Abunəlikləri kabinetdə də idarə etmək olar: API → Vebhuklar. İmza sirrini orada dəyişmək mümkündür.
İdarəetmə
| Sorğu | Nə edir |
|---|---|
GET /webhooks | abunəlikləriniz (sirlər olmadan) |
PATCH /webhooks/{id} | url, events və ya status (active / disabled) dəyişmək |
DELETE /webhooks/{id} | abunəliyi silmək |
POST /webhooks/{id}/test | nümunə hadisə göndərmək; {"eventType": "content.completed"} gövdəsi nümunənin formasını təyin edir |
GET /webhooks/{id}/deliveries | son 50 çatdırılma: status, cavab kodu, gecikmə, cavabın başlanğıcı |
POST /webhooks/{id}/deliveries/{deliveryId}/resend | çatdırılmanı yenidən göndərmək; deliveryId jurnaldakı sətrin _id dəyəridir |
events daxilində heç bir etibarlı hadisə olmayan və ya status dəyəri active / disabled olmayan PATCH 400 ilə rədd edilir. Naməlum abunəliyin DELETE sorğusu 404 cavabı verir. Çatdırılma jurnalında payload hadisənin data sahəsidir.
Hadisələr
Tamamlanmış tapşırıqlar
| Hadisə | Nə vaxt |
|---|---|
valuation.completed, valuation.failed | tam qiymətləndirmə hesabatı |
express.completed, express.failed | Prefer: respond-async ilə başladılmış ekspres qiymətləndirmə |
rent.completed, rent.failed | Prefer: respond-async ilə başladılmış icarə qiymətləndirməsi |
draft.completed, draft.failed | Prefer: respond-async ilə işə salınmış elan qaralaması |
site.completed, site.failed | Prefer: respond-async ilə işə salınmış obyekt saytı |
review.completed, review.failed | hesabatın yoxlanması |
review.action_required | hesabatın yoxlanması sənədi oxuyub və confirm gözləyir |
content.completed, content.partial, content.failed | kontent paketi (partial - bəzi fayllar alınmadı) |
text.completed, text.failed | mətnlər |
video.completed, video.failed | video |
avatar.completed, avatar.failed | avatar video |
photo.completed, photo.failed | foto yaxşılaşdırma |
floorplan.completed, floorplan.failed | mərtəbə planı |
pdf.completed, pdf.failed | PDF təqdimat |
data: { "jobId", "status", "state" }. status alətin böyük hərflərlə yazılmış xam statusudur (məsələn, COMPLETED) - məntiqi state üzrə qurun. Tapşırıq 30 dəqiqə ərzində tamamlanmayıbsa - "reason": "timeout" ilə .failed. Tapşırıq yalnız o yaradılarkən onun hadisəsinə abunəlik mövcud olduqda izlənilir (Tapşırıqlar və nəticələr). express.* və rent.* hadisələrində status DONE və ya FAILED olur. Prefer: respond-async ilə başladılmış mərtəbə planı və ya hesabat yoxlaması üçün hadisə sorğu tapşırığının id-sini (areq_…) daşıyır; belə tapşırığın review.completed hadisəsi sənədin oxunduğunu və confirm tələb etdiyini bildirir - yoxlamanın özü isə, həmişəki kimi, təsdiqdən sonra öz hadisəsini göndərir.
review.action_required hesabatın yoxlanması sənədi oxuyub confirm gözlədikdə bir dəfə gəlir: jobId yoxlamanın özünün id-sidir (Prefer: respond-async ilə işə salındıqda da), status - NEED_CONFIRM, state - action_required.
Elanlar
| Hadisə | Nə vaxt |
|---|---|
object.created | siz elan yaratdınız |
object.updated | elan dəyişdi, o cümlədən moderator tərəfindən |
object.published | elan ictimai oldu |
object.deleted | qaralama silindi və ya dərc edilmiş elan arxivə köçürüldü |
data: { "objectId", "kind", "status", "occurredAt" }; object.deleted hadisəsində status əvəzinə mode (deleted və ya archived) olur. Tam məlumat - GET /objects/{kind}/{id}.
Lidlər
| Hadisə | Nə vaxt |
|---|---|
lead.created | sizə ünvanlanmış yeni lid |
lead.updated | status və ya məsul şəxs dəyişdi |
data: { "leadId", "status", "type", "source", "objectId", "occurredAt" }. Hadisədə müştərinin şəxsi məlumatları yoxdur - tam lidi GET /leads/{id} ilə oxuyun.
Swipe Match
| Hadisə | Nə vaxt |
|---|---|
match.lead.offered | lid sizə (və ya agentliyinizin agentinə) təklif edildi |
match.lead.offer_closed | təklif sizsiz bağlandı (vaxt bitdi) |
match.lead.matched | lid sizə təyin edildi |
match.lead.updated | lid yeni mərhələyə keçdi |
match.lead.unassigned | lid sizdən götürüldü |
data: { "leadId", "eventId", "eventCode", "occurredAt", "source", "stage", "active", "leadKind", "clientType", "country", "brokerId", "agencyId" }. Müştərinin adı, telefonu və e-poçtu heç vaxt hadisələrdə olmur (Swipe Match).
Çatdırılma formatı
POST https://example.com/grem-hook
Content-Type: application/json
x-grem-event: content.completed
x-grem-signature: t=1759400000,v1=3b78a03b78058d229023db2a0b4ee072...
{ "id": "...", "type": "content.completed", "createdAt": "2026-10-02T10:00:00.000Z", "data": { ... } }
idbir çatdırılmanın bütün təkrar cəhdlərində eynidir - hadisəni iki dəfə emal etməmək üçün ondan istifadə edin.tvəcreatedAtkonkret cəhdin vaxtıdır.- Siyahıdakı
eventTypeilə test çatdırılması (POST /webhooks/{id}/test)datadaxilindətest: truedaşıyır; onsuz hadisənin tipiwebhook.testolur. Siyahıda olmayaneventType-400.webhook.testözü qəbul edilir.
İmzanın yoxlanması
İmza abunəliyin sirri ilə "<t>.<raw body>" sətrindən hesablanmış HMAC-SHA256-dır, v1 daxilində hex formatında kodlanır. İmzanı istənilən emaldan əvvəl yoxlayın və köhnəlmiş t dəyərlərini rədd edin (təkrar göndərmədən qorunma).
İmzanı JSON-u təhlil etməzdən əvvəl, sorğunun xam gövdəsi üzərində, tam alındığı kimi hesablayın. Yenidən seriyalaşdırma baytları dəyişir və imza uyğun gəlməyəcək.
const crypto = require('crypto');
function verifyGremSignature(secret, header, rawBody, toleranceSec = 300) {
const parts = Object.fromEntries(String(header || '').split(',').map((kv) => kv.split('=')));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1 || '');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
app.post('/grem-hook', express.raw({ type: 'application/json' }), (req, res) => {
const raw = req.body.toString('utf8');
if (!verifyGremSignature(process.env.GREM_WEBHOOK_SECRET, req.get('x-grem-signature'), raw)) {
return res.status(400).send('invalid signature');
}
const event = JSON.parse(raw);
// event.id, event.type, event.data
res.sendStatus(200);
});
SDK-da verifyWebhookSignature() eyni işi görür.
Təkrar cəhdlər və söndürmə
- Serveriniz 10 saniyə ərzində
2xxcavabı verdikdə çatdırılma uğurlu sayılır. Tez cavab verin, ağır işləri isə arxa planda görün. - Uğursuz çatdırılma 5 dəqiqə, 30 dəqiqə, 2 saat və 6 saat sonra təkrarlanır - cəmi 5 cəhdə qədər.
- Ardıcıl 5 çatdırılma tamamilə uğursuz olduqdan sonra abunəlik söndürülür (
status: disabled). OnuPATCH /webhooks/{id}və{"status":"active"}ilə və ya kabinetdə yenidən aktivləşdirin. - Çatdırılma jurnalı (
GET /webhooks/{id}/deliveries) serverinizin cavab kodunu və cavab gövdəsinin başlanğıcını göstərir - çatdırılmanın niyə alınmadığını orada görürsünüz.
Əlaqəli
- Tapşırıqlar və nəticələr - tapşırıqların vəziyyətləri.
- Swipe Match - modulun lid hadisə kodları.