İçeriğe geç
developers
Geliştirici merkezi

VISWOO BELGELERİ

Webhooklar

Ekran, medya ve onay olaylarını kendi sunucunuzda alın; imza doğrulama, yeniden deneme ve teslim kaydı.

Webhook, Viswoo’da bir olay olduğunda sizin sunucunuza imzalı bir POST isteğidir. Adresler panelde Eklentiler → API erişimi sayfasından ya da API’den (webhooks:manage) yönetilir. İşletme başına en çok 5 adres; adres https olmalıdır, iç ağa yönelen adrese istek gönderilmez.

Olay Ne zaman data
screen.offline Ekran bir süredir görünmüyor (panelin çevrimdışı e-postasıyla aynı anda) { screenId, screenName, lastSeenAt }
screen.online Çevrimdışı ekran yeniden bağlandı { screenId, screenName, lastSeenAt }
media.processed Yüklenen medya işlendi, kullanılabilir { mediaId, name, type, status, failureCode }
media.failed Medya işlenemedi { mediaId, name, type, status, failureCode }
approval.requested Editörün değişikliği onay bekliyor (İçerik onayı) { changeId, kind, playlistId, title, requestedBy }
approval.decided Onay isteği onaylandı ya da reddedildi { changeId, kind, playlistId, title, status, decidedBy, note }
webhook.test Panelden ya da API’den “deneme gönder” { message }

Gövde:

{
"id": "0195…",
"event": "media.processed",
"createdAt": "2026-11-01T09:30:00Z",
"data": { "mediaId": "…", "name": "yaz-kampanyasi", "type": "image", "status": "ready", "failureCode": null }
}

id olayındır; aynı olay her adrese aynı kimlikle gider ve yeniden denemede değişmez. Tekrarları id ile ayıklayın.

Her istek X-Viswoo-Signature: t=<unix saniye>,v1=<hex> başlığı taşır:

v1 = HMAC-SHA256(sır, "<t>.<ham gövde>")

Sır adres başınadır (whsec_…), yalnız adres açılırken ve yenilenirken bir kez gösterilir. Sunucunuz gövdeyi ayrıştırmadan önce ham hâliyle imzayı hesaplamalı, sabit zamanlı karşılaştırmalı ve 5 dakikadan eski t’yi reddetmelidir.

import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(secret, header, rawBody) {
const parts = Object.fromEntries(
String(header ?? '')
.split(',')
.map((part) => part.split('=')),
);
const t = Number(parts.t);
if (!parts.v1 || !Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 300) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
const given = Buffer.from(parts.v1, 'hex');
return given.length === expected.length && timingSafeEqual(given, expected);
}
using System.Security.Cryptography;
using System.Text;
static bool Verify(string secret, string? header, string rawBody)
{
var parts = (header ?? "").Split(',').Select(p => p.Split('=', 2)).Where(p => p.Length == 2)
.ToDictionary(p => p[0], p => p[1]);
if (!parts.TryGetValue("t", out var t) || !parts.TryGetValue("v1", out var v1) || !long.TryParse(t, out var unix)
|| Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - unix) > 300)
{
return false;
}
var expected = HMACSHA256.HashData(Encoding.UTF8.GetBytes(secret), Encoding.UTF8.GetBytes($"{t}.{rawBody}"));
return CryptographicOperations.FixedTimeEquals(expected, Convert.FromHexString(v1));
}
  • 10 saniye içinde 2xx dönün; işi kuyruğa alıp hemen cevap verin.
  • 2xx dışı cevap ya da bağlantı hatası yeniden denenir: 1 dk, 5 dk, 30 dk, 2 sa, 6 sa ve 15 sa sonra (toplam yaklaşık 24 saat).
  • Bir adres art arda 50 kez başarısız olursa durdurulur ve hesap yöneticilerine e-posta gider. Sorunu çözüp adresi panelden ya da PUT /webhooks/{id} ile (enabled: true) yeniden açın; durduğu sürenin olayları yeniden gönderilmez.
  • Son 7 günün teslimleri panelde ve GET /webhooks/{id}/deliveries ile görülür.
  • Sırrı POST /webhooks/{id}/rotate-secret ile yenileyin; eski sır hemen geçersiz olur.