İçeriğe geç
Docs

Uygulamalar Arası İletişim

Uygulamalar arası olaylar (pub/sub), paylaşılan metafield’lar ve keşif kataloğu.

Son güncelleme:

Aynı mağazada kurulu uygulamalar birbirleriyle gevşek bağlı biçimde çalışabilir: bir uygulama olay yayınlar, diğeri abone olur; bir uygulama kaynağa veri yazar, diğeri okur. Mağazanın onayı kurulumla örtüktür: iki uygulama da mağazada kuruluysa ve olaylar yapılandırmada bildirildiyse iletişim kurulur.

YöntemNe zamanYön
Uygulama olayları (pub/sub)"Bir şey oldu" bildirimi (fatura kesildi, gönderi oluşturuldu)Yayıncı → aboneler (webhook)
Paylaşılan metafield'larKaynağa bağlı kalıcı veri (fatura numarası, takip numarası)Yazan → okuyan (API)
Keşif kataloğuMağazada hangi olayların yayınlandığını öğrenmekAPI

Uygulama Olayları#

Adlandırma#

Yayıncı olay adını kısa haliyle bildirir (invoice.created); Tecof bunu yayıncının slug'ıyla önekler:

Metin
app.<yayıncı slug>.<olay adı>      ör. app.isbasi.invoice.created

Öneki sunucu ekler; bu sayede bir uygulama başka bir uygulamanın adına olay yayınlayamaz.

Yayınlama#

  1. Olayı tecof.app.json içinde bildirin:
JSON
{
  "appEvents": {
    "publishes": [
      { "name": "invoice.created", "description": { "tr": "Fatura oluşturuldu", "en": "Invoice created" } }
    ]
  }
}
  1. Olayı yayınlayın:
TypeScript
await tecof.client(installationId).events.publish("invoice.created", {
  orderId: "6720bb00cc11dd22ee33ff44",
  orderNumber: "TCF-1001",
  invoiceNumber: "ABC2026000000123",
});

Ham HTTP: POST /api/v1/app/events { name, data }.

KuralDeğer
data boyutuEn fazla 32 KB
Bildirilmemiş ad400 app-event-undeclared
KapsamGerekmez (uygulamanın kendi verisi)

Abone olma#

Abone uygulama, dinlediği olayları appEvents.subscribes içinde tam adla ya da yayıncı jokeriyle bildirir:

JSON
{
  "appEvents": {
    "subscribes": ["app.isbasi.invoice.created", "app.kargo.*"]
  }
}

Olay, aynı mağazada kurulu ve bu adı (ya da app.<slug>.* jokerini) listeleyen uygulamalara webhook olarak appUrl + webhooks.path adresine teslim edilir. Abone uygulamada webhooks.path tanımlı değilse uygulama olayları teslim edilemez. Teslimat biçimi, imza, yeniden deneme ve idempotency kuralları normal webhook'larla aynıdır (Webhook'lar); data alanı şu biçimdedir:

JSON
{
  "id": "evt_91c0d2aa47",
  "event": "app.isbasi.invoice.created",
  "test": false,
  "timestamp": "2026-10-10T09:20:00.000Z",
  "merchantId": "66f0c0ffee0000000000abcd",
  "installationId": "6720aa00bb11cc22dd33ee77",
  "data": {
    "source": { "slug": "isbasi", "clientId": "tcfa_yyyyyyyyyyyyyyyy" },
    "payload": {
      "orderId": "6720bb00cc11dd22ee33ff44",
      "orderNumber": "TCF-1001",
      "invoiceNumber": "ABC2026000000123"
    }
  }
}

installationId burada abone uygulamanın kurulumudur. Yayıncıyı data.source ile tanırsınız.

Keşif#

Mağazada kurulu uygulamaların yayınladığı olayları listelemek için:

TypeScript
const catalog = await tecof.client(installationId).events.catalog();
JSON
[
  {
    "slug": "isbasi",
    "appName": "Logo İşbaşı",
    "event": "app.isbasi.invoice.created",
    "description": { "tr": "Fatura oluşturuldu", "en": "Invoice created" }
  }
]

Ham HTTP: GET /api/v1/app/events/catalog. Liste, mağazada aktif kurulu platform uygulamalarının appEvents.publishes bildirimlerinden üretilir; event tam (önekli) addır. Panelinizde "şu uygulama kuruluysa şu entegrasyonu aç" gibi akışlar için kullanabilirsiniz.


Paylaşılan Metafield'lar#

visibility: "shared" ile yazılan metafield'ları aynı mağazadaki diğer uygulamalar okuyabilir. Okuyan uygulama, kaynağın okuma kapsamına sahip olmalıdır (sipariş için orders:read).

TypeScript
// Yazan: İşbaşı uygulaması
await api.metafields.set({
  ownerType: "order",
  ownerId: orderId,
  key: "invoiceNumber",
  type: "string",
  value: "ABC2026000000123",
  visibility: "shared",
});

// Okuyan: kargo uygulaması
const shared = await kargoApi.metafields.list({ ownerType: "order", ownerId: orderId, namespace: "isbasi" });
const invoiceNumber = shared.find((m: { key: string }) => m.key === "invoiceNumber")?.value;

Namespace yazan uygulamanın slug'ıdır; okurken namespace süzgeciyle hangi uygulamanın verisini istediğinizi belirtin. private metafield'lar başka uygulamalara dönmez.


Örnek: Fatura → Kargo#

Senaryo: İşbaşı uygulaması ödenen sipariş için fatura keser ve invoice.created yayınlar. Mağazada kurulu bir kargo uygulaması (kargo) bu olayı dinler, gönderiyi faturalı olarak oluşturur ve kendi olayı shipment.created'i yayınlar.

sequenceDiagram
    participant T as Tecof
    participant I as İşbaşı uygulaması (isbasi)
    participant K as Kargo uygulaması (kargo)

    T->>I: webhook order.paid
    I->>I: Faturayı kes
    I->>T: PUT /api/v1/metafields (invoiceNumber, shared)
    I->>T: POST /api/v1/app/events { name: "invoice.created" }
    T->>K: webhook app.isbasi.invoice.created
    K->>T: GET /api/v1/orders/:id
    K->>K: Gönderiyi oluştur
    K->>T: POST /api/v1/app/events { name: "shipment.created" }
    T->>I: webhook app.kargo.shipment.created
Diyagram

İşbaşı yapılandırması

JSON
{
  "slug": "isbasi",
  "scopes": ["orders:read", "customers:read", "products:read"],
  "webhooks": { "path": "/api/webhooks", "events": ["order.paid"] },
  "appEvents": {
    "publishes": [{ "name": "invoice.created", "description": { "tr": "Fatura oluşturuldu", "en": "Invoice created" } }],
    "subscribes": ["app.kargo.shipment.created"]
  }
}

Kargo uygulaması yapılandırması

JSON
{
  "slug": "kargo",
  "scopes": ["orders:read"],
  "webhooks": { "path": "/api/webhooks", "events": ["order.fulfilled"] },
  "appEvents": {
    "publishes": [{ "name": "shipment.created", "description": { "tr": "Gönderi oluşturuldu", "en": "Shipment created" } }],
    "subscribes": ["app.isbasi.invoice.created"]
  }
}

Kargo uygulamasının işleyicisi

TypeScript
// kargo: app/api/webhooks/route.ts
import { createWebhookHandler } from "@tecof/app-sdk";
import { tecof } from "@/lib/tecof";

type InvoiceCreated = {
  source: { slug: string; clientId: string };
  payload: { orderId: string; invoiceNumber: string };
};

export const POST = createWebhookHandler({
  app: tecof,
  handlers: {
    "app.isbasi.invoice.created": async (event) => {
      const { payload } = event.data as InvoiceCreated;
      const api = tecof.client(event.installationId);
      const order = await api.orders.get(payload.orderId);
      // … gönderiyi payload.invoiceNumber ile oluştur
      await api.events.publish("shipment.created", { orderId: order.id, trackingNumber: "TRK000000001" });
    },
  },
});

Notlar:

  • Yayıncı kurulu değilse olay gelmez; abone uygulama bu entegrasyonu isteğe bağlı bir özellik olarak tasarlamalıdır. Keşif kataloğuyla yayıncının varlığını kontrol edebilirsiniz.
  • Olay yükü yalnız bildirimdir; kaydın güncel hâlini API'den okuyun.
  • Aynı olay birden fazla gelebilir; X-Tecof-Event-Id ile idempotent olun.

Yol Haritası#

Aşağıdakiler gelecek genişletme noktalarıdır ve henüz mevcut değildir:

  • Uygulamalar arası doğrudan istek (capability): bir uygulamanın başka bir uygulamanın sunduğu işlevi doğrudan çağırması.
  • Vitrin (tema) uzantıları: uygulamaların mağaza vitrinine bileşen eklemesi.