TN.TC API

QR, link, Box, Chat, Bell, site ve Hub işlemlerini API ile yönet. Her istek hesabının yetki ve kullanım sınırlarına tabidir.

https://tn.tc/api/v1OpenAPI 3.1

OpenAPI 3.1, API’nin makinece okunan tam tanımıdır: Postman, Insomnia veya kod üreticilere yükleyip istemci oluşturabilirsin. Dosya olarak iner.

Kimlik doğrulama

Taban adres /api/v1. Her istekte Authorization: Bearer tntc_sk_… başlığı gönder.

  • Anahtar, bir çalışma alanına ve oluşturan kişinin güncel rolüne bağlıdır; seçilen kapsamların dışına çıkamaz.
  • Web oturumu ve mobil erişim belirteci ayrı kimliklerdir; anahtar onların yerine geçmez.
  • Anahtarı tarayıcı koduna, mobil uygulamaya, URL'ye veya log'a koyma. Sızarsa hemen iptal et veya döndür.

Kapsamlar

Her uç nokta bir kapsam ister; kaynak uç noktaları (/resources) kaydın türüne göre qr, links, box veya sites kapsamını kontrol eder. OpenAPI belgesinde her işlemin x-tntc-key-scope değeri vardır.

Hesap ve kullanım

profile:read
Profil, çalışma alanları, ekip listesi
profile:write
Profil ve bildirim okundu bilgisi
usage:read
Paket kapasitesi ve kullanım
billing:read
Paket durumunu oku

QR

qr:read
QR kodlarını oku, SVG al
qr:write
QR oluştur, düzenle, arşivle
analytics:read
Tarama ve ziyaret istatistikleri

Link ve adres

links:read
Linkleri ve adres uygunluğunu oku
links:write
Link oluştur, düzenle, arşivle

Box ve dosyalar

box:read
Box, politika ve gönderimleri oku
box:write
Box oluştur, politika ve incelemeyi yönet
files:read
Dosya bilgisi ve izinli indirme
files:write
Yükleme başlat/tamamla, dosya yönet

Chat ve Bell

chat:read
Sohbetler, mesajlar, canlı akış
chat:write
Mesaj gönder, düzenle, tepki ver
bell:read
Bell siparişleri ve durumları
bell:write
Bell teklif ayarları ve sipariş başlatma

Mini site

sites:read
Siteleri, menüleri, şablonları ve sürümleri oku
sites:write
Site/menü oluştur; sosyal link, görsel ve tasarımı düzenle
sites:publish
Yayınla
leads:read
İzinli müşteri listesini oku ve dışa aktar (sahip/yönetici)
leads:write
İzni geri çek veya kişileri sil (sahip/yönetici)

Ürünler ve kurslar

commerce:read
Ürünleri, izinli siparişleri ve satın alınan içeriği oku
commerce:write
Ürün ve kurs taslaklarını yönet (tahsilat/iade yetkisi vermez)

UGC

ugc:read
Creator, kampanya, başvuru oku
ugc:write
Kampanya ve başvuru işlemleri
earnings:read
Kazançları oku (ödeme yok)

Anahtarla yapılamayanlar: hesap silme ve dışa aktarma, ödeme başlatma, kazanç ödemesi, ekip yönetimi, anahtar ve webhook yönetimi, platform yönetimi.

Hatalar

Hatalar kararlı bir makine kodu ve destekte kullanabileceğin bir requestId döndürür.

{ "error": { "code": "insufficient_scope", "requestId": "…" } }
HTTPcode
400/422invalid_input
401unauthorized
403insufficient_scope · forbidden · quota_exceeded
404not_found
409conflict · idempotency_conflict · idempotency_in_progress
413invalid_input
429rate_limited (Retry-After)
503configuration_missing

Tekrar güvenli istekler

POST, PATCH ve DELETE isteklerine Idempotency-Key ekle. Aynı anahtar ve gövde 24 saat içinde ilk yanıtı döndürür (Idempotent-Replayed: true); farklı gövde 409 idempotency_conflict alır; ilk istek sürerken 409 idempotency_in_progress döner.

Limitler

Free
10/ dk
Pro
60/ dk

Anahtar başına dakikada istek: Ücretsiz 10, Pro 60. Aşılırsa 429 ve Retry-After döner. Oluşturduğun kaynaklar paketinin kaynak, depolama ve Box kotasından düşer.

Paket sayıları geçicidir ve ticari teklif değildir; hız limiti bir SLA değildir.

Webhook'lar

Gövde: id, type, schemaVersion, occurredAt, workspaceId, data. Başlıklar: TNTC-Event-Id, TNTC-Event-Type, TNTC-Delivery-Attempt, TNTC-Signature (t=zaman damgası, v1=HMAC-SHA256(secret, t + '.' + ham gövde)). Beş dakikadan eski imzaları reddet.

resource.created
QR, link, Box veya site oluşturuldu
resource.updated
Kaynak değişti (sürüm artar)
resource.archived
Kaynak arşivlendi
qr.import.completed
QR aktarımı tamamlandı (yalnız sayılar ve iş kimliği)
links.import.completed
Link aktarımı tamamlandı (yalnız sayılar ve iş kimliği)
box.submission.completed
Box isteğine dosya geldi
file.ready
Dosya kullanıma hazır ya da yeni sürümü var
chat.message.created
Yeni mesaj (yalnız kimlikler; içerik yok)
chat.conversation.updated
Grup/kanal ayarı veya üyelik yönetimi değişti
bell.order.updated
Bell sipariş durumu değişti
site.published
Mini site yayınlandı
menu.published
Menü yayınlandı (fiyat/ürün değişikliği)
quote.received
Siteden teklif talebi geldi (yalnız kimlikler)
quote.updated
Teklif talebinin durumu veya brief Box’ı değişti
commerce.product.updated
Ürün değişti
commerce.order.updated
Sipariş değişti (yalnız kimlik ve işlem)
ugc.application.updated
UGC başvurusu değişti
lead.confirmed
E-posta kaydı doğrulandı (yalnız kimlikler)
lead.unsubscribed
Kişi e-posta iznini geri çekti (yalnız kimlikler)
Webhook imzasını doğrula (Node.js)
import { createHmac, timingSafeEqual } from 'node:crypto';

// header: TNTC-Signature: t=<unix seconds>,v1=<hex>[,v1=<hex during rotation>]
export function verifyTntcSignature(secret: string, header: string, rawBody: string) {
  const parts = header.split(',');
  const t = Number(parts.find((p) => p.startsWith('t='))?.slice(2));
  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
  return parts
    .filter((p) => p.startsWith('v1='))
    .some((p) => {
      const given = Buffer.from(p.slice(3), 'hex');
      return given.length === expected.length && timingSafeEqual(given, expected);
    });
}
// Deliveries are at least once: store TNTC-Event-Id and ignore repeats.

Örnekler

cURL: QR kodlarını listele
curl -sS "https://tn.tc/api/v1/resources?kind=qr&limit=5" \
  -H "Authorization: Bearer $TNTC_API_KEY"
cURL: tekrar güvenli QR oluştur
curl -sS -X POST "https://tn.tc/api/v1/resources" \
  -H "Authorization: Bearer $TNTC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: menu-qr-2026-09-25" \
  -d '{"kind":"qr","name":"Menu QR","qrType":"website","targetUrl":"https://example.com/menu"}'
TypeScript
const api = 'https://tn.tc/api/v1';
const headers = {
  Authorization: `Bearer ${process.env.TNTC_API_KEY}`,
  'Content-Type': 'application/json',
};

// Retry-safe create: the same Idempotency-Key returns the first result.
const created = await fetch(`${api}/resources`, {
  method: 'POST',
  headers: { ...headers, 'Idempotency-Key': crypto.randomUUID() },
  body: JSON.stringify({ kind: 'qr', name: 'Menu QR', qrType: 'website', targetUrl: 'https://example.com/menu' }),
});
if (!created.ok) throw new Error((await created.json()).error.code);
const qr = await created.json();

// Change the destination later; the printed QR keeps working.
await fetch(`${api}/resources/${qr.id}`, {
  method: 'PATCH',
  headers,
  body: JSON.stringify({ targetUrl: 'https://example.com/menu-autumn' }),
});