// geliştirici

Misafir Wi-Fi'yi kendi
yazılımınızdan yönetin.

Otel programınızdan misafir hesabı açın, PDKS'inizden personel tanımlayın, şube şube doluluk görün, oturum sonlandırın ve olayları imzalı webhook ile dinleyin. Sunucudan sunucuya JSON REST — sürümlü ve sözleşmeli.

Genel bakış

WiPoint Entegrasyon API'si https://api.wipoint.tr tabanında çalışan JSON REST servisidir. Sürüm yola gömülüdür: /v1/…. Yalnız HTTPS kabul edilir.

01

Müşteri anahtarı üretir

API Entegrasyon paketi olan müşteri, portalından anahtar oluşturur ve client_id / client_secret ikilisini size verir.

02

Token alırsınız

Gizli anahtarı 15 dakikalık erişim token'ına çevirirsiniz. Uzun ömürlü sır iş çağrılarında hiç taşınmaz.

03

Olayları dinlersiniz

Misafir bağlandı, kota doldu, nokta çevrimdışı — HMAC imzalı POST ile kendi sisteminize düşer.

Ne yapılabilir

  • Hotspot kullanıcısı oluşturma, listeleme, güncelleme, pasife alma
  • Erişim profillerini (hız, süre, kota) okuma ve kullanıcıya atama
  • Aktif oturumları görme ve sonlandırma
  • Nokta durumu, eşzamanlı kullanıcı sayısı ve doluluk yüzdesi
  • Olay bildirimleri için webhook tanımlama

Ne yapılamaz — bilinçli olarak

Cihaz yapılandırması (köprü, port, SSID), karşılama ekranı tasarımı, abonelik ve ödeme işlemleri, KVKK metinleri ve 5651 delil paketi indirme API'de yoktur; bunlar panelde, yetki ve denetim kaydıyla yapılır. Bir anahtar da yalnız kendisine tanımlanan noktalara erişir — başka müşterinin verisine hiçbir koşulda ulaşamaz.

Erişim nasıl açılır

  1. Müşteri API Entegrasyon paketini satın alır (ya da WiPoint yöneticisi firmaya elle yetki tanımlar).
  2. Hak firma seviyesinde durur ve kendi süresi vardır; şubelerin hotspot aboneliğinden bağımsız yenilenir.
  3. Müşteri portalda Hotspot Yönetimi → API & Entegrasyon ekranından anahtar üretir. Sihirbaz dört adımdır: ad, kapsam, yetkiler, kaynak IP.
  4. client_secret yalnız üretim anında bir kez görünür. Kaybolursa yenilenir; yenileme eski anahtarı anında geçersiz kılar, client_id değişmez.

Erişim ne zaman durur

API paketi süresi biterTüm anahtarlar pasife düşer, açık token'lar anında geçersiz olur
Bir şubenin hotspot aboneliği dururYalnız o şube düşer (node_not_entitled); diğer şubeler çalışır
Müşteri anahtarı iptal ederO anahtar ve token'ları anında ölür
Paket yenilenirAnahtarlar aynı client_id ile tekrar aktifleşir — yeni anahtar dağıtmanız gerekmez

Kimlik doğrulama — token exchange

İki adımlıdır: uzun ömürlü client_secret hiçbir iş çağrısında taşınmaz, kısa ömürlü opak erişim token'ına çevrilir. Token sunucuda tutulur; anahtar iptal edildiğinde ya da paket bittiğinde anında geçersiz olur.

curl -X POST https://api.wipoint.tr/v1/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=wpi_9f4c21ab…" \
  -d "client_secret=wps_7a1e…"
{
  "access_token": "wpat_3f9c8e21…",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "nodes:read users:read users:write sessions:read"
}

Sonraki isteklerde:

Authorization: Bearer wpat_3f9c8e21…

Token'ı bellekte tutun, her istekte yeniden almayın — token ucu ayrıca dakikada 10 istekle sınırlıdır.

Kaynak IP kuralı

Anahtar üretilirken en az bir kaynak IP tanımlanması zorunludur. IP'siz anahtar oluşturulamaz.

En fazla kayıt4
İzin verilen en geniş blok/24 — örn. 203.0.113.0/24
Tek adres203.0.113.10 (maske yazmanıza gerek yok)
IPv6yalnız tek adres (/128)

Daha geniş bloklar (/16 gibi) reddedilir. Sınırlar, gerekçesi kayda geçirilerek müşteri bazında gevşetilebilir. IP hem token alırken hem her istekte doğrulanır; uymayan kaynak 403 ip_not_allowed alır ve istek denetim günlüğüne yazılır.

Sabit çıkış IP'niz yoksa entegrasyon açılamaz. Bu bilinçli bir güvenlik kararıdır: misafir kimlik verisine dokunan bir arayüzün nereden çağrıldığı belirsiz kalamaz.

Anahtar kapsamı — çok şubeli müşteriler

Bir anahtar birden çok noktaya yetkilendirilebilir. Müşteri üretim sırasında iki kapsamdan birini seçer:

tüm noktalarımFirmanın tüm hotspot noktaları; sonradan açılan şube otomatik dahil
seçtiğim noktalarYalnız işaretlenen noktalar; yeni şube otomatik eklenmez

Örnek: 50 şubeli bir zincir tek anahtarla tüm şubelerde hesap açar ve doluluk görür; ikinci bir anahtar yalnız dört pilot şubeye yetkilendirilir. Kapsam dışı bir noktaya istek 403 node_not_in_scope döner.

Yetkiler anahtarın tamamı için geçerlidir — aynı anahtar bir şubede salt-okunur, diğerinde yazma yetkili olamaz. Farklı yetki gerekiyorsa ikinci anahtar üretilir.

Yetki seviyeleri

Anahtar üretilirken müşteri işaretler; token yanıtındaki scope alanı fiilî yetkidir. Yetkisiz çağrı 403 insufficient_scope döner.

nodes:readNokta listesi, durum, kapasite ve doluluk yüzdesi
users:readHotspot kullanıcılarını listeleme / görüntüleme
users:writeYeni hotspot kullanıcısı oluşturma
users:quotaErişim profili, geçerlilik süresi, parola güncelleme
users:disableKullanıcıyı pasife alma / silme
sessions:readAktif oturumları görme
sessions:kickAktif oturumu sonlandırma
webhooks:manageWebhook tanımlarını yönetme

Pasife alma ayrı bir yetkidir: kota düzenleyen bir entegrasyon, misafiri internetten atma hakkını kendiliğinden kazanmaz.

Başlarken

Token aldıktan sonra ilk anlamlı çağrı, erişebildiğiniz noktaları listelemektir:

curl https://api.wipoint.tr/v1/nodes \
  -H "Authorization: Bearer wpat_3f9c8e21…"

Ardından bir noktada misafir hesabı açın:

curl -X POST https://api.wipoint.tr/v1/nodes/6bc7e95c-…/users \
  -H "Authorization: Bearer wpat_3f9c8e21…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: oda-214-2026-08-26" \
  -d '{
    "username": "oda-214",
    "password": "G3cici!Parola",
    "full_name": "Ayşe Yılmaz",
    "type": "guest",
    "expires_in_minutes": 1440
  }'

201 yanıtı:

{
  "id": "9f4c21ab-…",
  "username": "oda-214",
  "status": "active",
  "type": "guest",
  "full_name": "AYŞE Y.",
  "phone_masked": null,
  "identity_verified": false,
  "expires_at": "2026-08-27T09:00:00.000Z",
  "created_at": "2026-08-26T09:00:00.000Z",
  "created_via": "api"
}

Ağ koparsa: Idempotency-Key

Aynı anahtarla tekrar deneyin — 24 saat boyunca aynı yanıt döner ve yanıta Idempotent-Replay: true başlığı eklenir. Kurallar:

  • Yalnız başarılı yanıtlar saklanır. Hata alırsanız aynı anahtarla düzeltilmiş gövdeyi gönderebilirsiniz — geçici bir hata 24 saat kalıcı hâle gelmez.
  • Aynı anahtar farklı bir gövdeyle kullanılırsa 422 idempotency_key_reused.
  • Aynı anahtarla eşzamanlı ikinci istek gelirse 409 idempotency_in_progress.
  • Başlığı göndermezseniz idempotency çalışmaz; tekrar denemede aynı kullanıcı adı için 409 username_taken alırsınız (kayıt yine çiftlenmez).

Noktalar & doluluk

GET/v1/nodesYetkili olduğunuz tüm noktalar — tek çağrıda
GET/v1/nodes/{nodeId}Tek nokta detayı
{
  "data": [
    {
      "id": "6bc7e95c-…",
      "name": "Kadıköy Şube",
      "status": "online",
      "last_seen_at": "2026-08-26T11:42:07.000Z",
      "concurrent_limit": 50,
      "active_users": 31,
      "usage_percent": 62,
      "subscription_status": "active",
      "entitled": true,
      "hotspot_servers": [{ "id": "…", "name": "lobi" }]
    }
  ],
  "next_cursor": null,
  "has_more": false
}

/v1/nodes sayfalanmaz — kapsamınızdaki tüm noktalar tek yanıtta gelir (has_more her zaman false). Şube başına ayrı istek atmanız gerekmez.

status: online · offline · never (tünel el sıkışmasından hesaplanır, eşik 15 dakika). entitled: false olan şube listede görünür ama iş çağrılarında node_not_entitled döner — aboneliği durmuştur.

Hotspot kullanıcıları

GET/v1/nodes/{nodeId}/usersListele (limit, cursor, status, type, q)
POST/v1/nodes/{nodeId}/usersOluştur
GET/v1/nodes/{nodeId}/users/{id}Detay
PATCH/v1/nodes/{nodeId}/users/{id}Durum, parola, ad, tip, profil
DELETE/v1/nodes/{nodeId}/users/{id}Pasife al (açık oturumları düşer)
GET/v1/nodes/{nodeId}/profilesErişim profilleri (hız / süre / kota)

Zorunlu alanlar ve sınırlar

  • username, password ve full_name zorunludur. 5651 sayılı kanun gereği her internet erişimi bir kimliğe bağlanmak zorundadır; doğrulamayı siz yaptığınız için kimlik sizden gelir. Eksikse 422 identity_required döner.
  • expires_in_minutes tavanı 1440 (24 saat). Süre dolunca giriş kapanır, kayıt silinmez.
  • Aynı kullanıcı adı ikinci kez gönderilirse 409 username_taken.

Kimlik alanları maskelidir

Okuma yanıtlarında telefon maskeli döner (0555 *** ** 67), ad-soyad kısaltılır (AYŞE Y.), TCKN ve pasaport numarası hiç dönmez — yalnız identity_verified bayrağı vardır. Eşleşme anahtarınız username'dir; ham kimliğe ihtiyacınız olmaz. Ham veri panelde, gerekçe ve denetim kaydıyla açılır.

Oturumlar

GET/v1/nodes/{nodeId}/sessionsAktif oturumlar
POST/v1/nodes/{nodeId}/sessions/{sessionId}/disconnectOturumu sonlandır
{ "ok": true, "path": "coa" }

path alanı işin gerçekte nasıl bittiğini söyler:

  • coa — cihaza RFC 5176 Disconnect-Request gönderildi ve yanıt alındı
  • device — CoA yanıtsız kaldı, oturum cihaz üzerinden düşürüldü
  • none — düşürülemedi; reason alanı sebebi taşır

"Gönderdim ama düşmedi" belirsizliğinde kalmayasınız diye bu alan yanıtta yer alır.

Webhook'lar

Bir adres tanımlayın; seçtiğiniz olaylar HMAC-SHA256 imzalı JSON gövdeyle POST edilir. Adres HTTPS ve genel internetten erişilebilir olmalıdır (iç ağ adresleri reddedilir).

Olaylar

user.createdYeni hotspot kullanıcısı açıldı (panel, portal ya da API)
user.disabledKullanıcı pasife alındı ya da silindi
session.startedMisafir bağlandı
session.endedOturum kapandı
quota.exceededKota aşıldı
node.online / node.offlineNokta çevrimiçi / çevrimdışı oldu
POST https://sizin-sisteminiz.com/wipoint-webhook
X-WiPoint-Signature: t=1755550000,v1=8f2c…
X-WiPoint-Event-Id: evt_8f2c…
X-WiPoint-Event: session.started

{
  "id": "evt_8f2c…",
  "event": "session.started",
  "occurred_at": "2026-08-26T11:04:11.000Z",
  "node_id": "6bc7e95c-…",
  "data": {
    "session_id": "81a0f3c2",
    "username": "oda-214",
    "ip": "10.24.7.112",
    "mac": "A1:B2:C3:D4:E5:F6"
  }
}

İmza doğrulama

İmzalanan metin <t> + "." + ham gövde'dir. t ile sizin saatiniz arasındaki fark ±300 saniye içinde olmalı; karşılaştırmayı sabit zamanlı yapın.

// Node.js
const crypto = require('node:crypto')

function wipointDogrula(rawBody, header, secret) {
  const p = Object.fromEntries(header.split(',').map(x => x.trim().split('=')))
  const t = Number(p.t)
  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 300) return false
  const beklenen = crypto.createHmac('sha256', secret)
    .update(`${t}.${rawBody}`).digest('hex')
  const a = Buffer.from(beklenen, 'hex')
  const b = Buffer.from(p.v1 ?? '', 'hex')
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}
// PHP
function wipoint_dogrula(string $rawBody, string $header, string $secret): bool {
    parse_str(str_replace(',', '&', $header), $p);
    $t = (int)($p['t'] ?? 0);
    if ($t === 0 || abs(time() - $t) > 300) return false;
    $beklenen = hash_hmac('sha256', $t . '.' . $rawBody, $secret);
    return hash_equals($beklenen, $p['v1'] ?? '');
}
// C#
static bool WipointDogrula(string rawBody, string header, string secret) {
    var p = header.Split(',').Select(x => x.Trim().Split('='))
                  .ToDictionary(x => x[0], x => x[1]);
    if (!long.TryParse(p["t"], out var t)) return false;
    var simdi = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    if (Math.Abs(simdi - t) > 300) return false;
    using var h = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
    var beklenen = Convert.ToHexString(
        h.ComputeHash(Encoding.UTF8.GetBytes($"{t}.{rawBody}"))).ToLowerInvariant();
    return CryptographicOperations.FixedTimeEquals(
        Encoding.UTF8.GetBytes(beklenen), Encoding.UTF8.GetBytes(p["v1"]));
}

Yönetim uçları

GET/v1/webhooksTanımlı webhook'lar
POST/v1/webhooksTanımla — secret yalnız bu yanıtta döner
DELETE/v1/webhooks/{id}Sil
POST/v1/webhooks/{id}/testGerçek imzayla tek seferlik test olayı
GET/v1/webhooks/{id}/deliveriesSon teslimatlar — teşhis için
GET/v1/webhooks/eventsDinlenebilecek olayların listesi

Teslimat garantisi

Teslimat at-least-once'tır: ağ koptuğunda isteği almış olabilirsiniz ama yanıt bize ulaşmamış olabilir; aynı olay tekrar gönderilir. Gövdedeki id sabittir — alıcı tarafın idempotent olması gerekir.

2xx dışı yanıt ya da 10 saniye zaman aşımı → 5 deneme: 1 dk · 5 dk · 30 dk · 2 sa · 6 sa. Hepsi başarısızsa teslimat düşer ve müşterinin panelinde "başarısız teslimat" olarak görünür.

Hata kodları & limitler

{
  "error": { "code": "insufficient_scope",
             "message": "Bu anahtarda users:write yetkisi yok." },
  "request_id": "req_4b1e…"
}

Destek talebinde request_id paylaşın — istek denetim günlüğünde birebir bulunur.

400invalid_requestŞema / alan hatası
400ip_range_too_broad/24'ten geniş blok
401invalid_clientclient_id / secret hatalı ya da iptal
401invalid_tokenToken geçersiz ya da süresi dolmuş
403insufficient_scopeAnahtarda o yetki yok
403ip_not_allowedKaynak IP tanımlı değil
403entitlement_requiredFirmada aktif API paketi yok
403node_not_entitledŞubenin hotspot aboneliği durmuş
403node_not_in_scopeNokta bu anahtarın kapsamında değil
404not_foundKayıt yok
409username_takenKullanıcı adı alınmış
422identity_requiredfull_name eksik (5651)
422idempotency_key_reusedAynı Idempotency-Key farklı gövdeyle kullanıldı
409idempotency_in_progressAynı anahtarla bir istek hâlâ işleniyor
429rate_limitedHız sınırı — Retry-After başlığına bakın

Sayfalama, hız sınırı, sürüm

  • Sayfalama: limit (varsayılan 50, tavan 200) + cursor. Yanıt: data, next_cursor, has_more. Ofset yoktur — kayan liste sorununu önlemek için.
  • Hız sınırı: anahtar başına 120 istek/dakika; token ucu 10 istek/dakika. Başarılı yanıtlar kalan hakkı X-RateLimit-Remaining başlığında taşır.
  • Sürüm sözü: yeni alan eklenmesi kırıcı değişiklik sayılmaz — bilinmeyen alanları yok sayacak şekilde ayrıştırın. Alan kaldırma ya da anlam değiştirme yalnız /v2 ile olur; /v1 en az 12 ay yaşar. Kullanımdan kaldırılacak uçlar en az 90 gün önce Deprecation ve Sunset başlıklarıyla işaretlenir.
  • Tüm zaman damgaları ISO 8601 UTC'dir.

Gizlilik ve 5651

Bu API kişisel veriye dokunur; üç kayıt katmanı istisnasız çalışır:

  • Anahtar yaşam döngüsü — kim, ne zaman oluşturdu; hangi yetkiler ve IP'ler verildi; kim iptal etti.
  • Her istek — request_id, anahtar, nokta, yol, sonuç, kaynak IP, süre. Ayrı bir erişim günlüğünde 2 yıl saklanır ve müşteri panelinden görülebilir.
  • Her değişiklik — denetim kaydına api kanalı, anahtar kimliği ve kaynak IP ile yazılır.

API ile açılan bir hesabın ürettiği erişim kayıtları, kaydın kendi satırında hangi anahtarla, hangi tarih-saatte ve hangi kaynak IP'den oluşturulduğunu taşır. Resmî bir talepte bu bilgi delil paketinde görünür.

Sizin sorumluluğunuz: aldığınız verinin saklanması, silinmesi ve paylaşılması KVKK kapsamında size aittir. client_secret ve webhook secret değerlerini kaynak koda gömmeyin, sürüm sistemine koymayın.

İndirilebilir kaynaklar

OPENAPI

OpenAPI 3.1 şeması

Tüm uçların makine-okur tanımı; istemci kodunuzu otomatik üretin.
wipoint-api-v1.yaml

DESTEK

Entegrasyon desteği

Takıldığınız yerde [email protected] — entegrasyon mühendisimiz eşlik eder.

Geliştirici kaydı

Entegrasyonunuzu anlatın; hangi uçlara ihtiyaç duyduğunuzu birlikte netleştirelim ve müşterinizin anahtarı üretmesi için yol gösterelim. Test ortamı ve örnek istek dizisiyle destekleriz.