# API ile Veri Erişimi

> /api/v1 yanıt zarfı, sayfalama ve hız sınırları; sipariş, müşteri, envanter, ürün şekilleri; Tools API ile yazma ve uygulamaya özel uçlar.
>
> Kaynak: https://tecof-app-dev.vercel.app/app-api · Bölüm: API’ler · Son güncelleme: 2018-10-20

Uygulamanızın sunucusu, kurulum token'ıyla (`tcfi_…`) Tecof Developer API'sini (`/api/v1`) kullanır. Kişisel erişim anahtarlarıyla (PAT) aynı uçlar ve aynı yanıt zarfı geçerlidir; fark, token'ın bir kullanıcıya değil bir **kuruluma** bağlı olması ve mağazanın onayladığı kapsamlarla sınırlanmasıdır.

```text
Base URL: https://api.tecof.com/api/v1
Authorization: Bearer tcfi_...
```

Token almak için bkz. [Kimlik Doğrulama → Kurulum token'ı](/app-auth). SDK kullanıyorsanız token yönetimi otomatiktir:

```ts
import { tecof } from "@/lib/tecof";

const api = tecof.client(installationId);
```

---

## Yanıt Zarfı

Tüm uçlar Tecof standart zarfını döner:

```json
{
  "success": true,
  "message": "İşlem başarılı",
  "messageCode": "success",
  "data": [],
  "totalData": 128
}
```

| Alan | Açıklama |
| :--- | :--- |
| `success` | İşlem sonucu |
| `message` | İnsan okur mesaj |
| `messageCode` | Makine okur kod (hata ayrımı için bunu kullanın) |
| `data` | Yük |
| `totalData` | Liste uçlarında toplam kayıt sayısı |

SDK zarfı açar: başarılı çağrı doğrudan `data`'yı döner; hata durumunda `TecofApiError { status, code, data }` fırlatır (`code` = `messageCode`).

```ts
import { TecofApiError } from "@tecof/app-sdk";

try {
  const order = await api.orders.get("TCF-1001");
} catch (err) {
  if (err instanceof TecofApiError && err.code === "insufficient-scope") {
    console.warn("Eksik kapsam:", err.data); // { required, missing }
  } else {
    throw err;
  }
}
```

### Sık hata kodları

| HTTP | `messageCode` | Ne yapmalı |
| :--- | :--- | :--- |
| 401 | `token-expired` | Token'ın süresi doldu; yeni token alın (SDK otomatik yeniler) |
| 401 | `token-revoked` | Token iptal edildi (kaldırma, kapsam değişikliği); yeni token alın, kurulum aktif değilse çağrıyı bırakın |
| 401 | `token-invalid` | Token tanınmıyor ya da biçimi bozuk |
| 401 | `app-suspended` | Uygulama Tecof tarafından askıya alındı; token basılmaz |
| 403 | `app-token-required` | `/api/v1/app/*` uçları kişisel erişim anahtarıyla (PAT) çağrıldı; bu uçlar yalnız uygulama token'ı kabul eder |
| 403 | `insufficient-scope` | `data: { required, missing }`; kapsamı `tecof.app.json`'a ekleyin, mağaza onaylamalı |
| 404 | `not-found` | Kayıt yok |
| 429 | `rate-limited` | Hız sınırı aşıldı; bekleyip yeniden deneyin |

---

## Sayfalama ve Süzgeçler

| Parametre | Açıklama |
| :--- | :--- |
| `page` | 1'den başlar |
| `limit` | En fazla 200; varsayılan 50 (ürün listesi eski sözleşmeyi korur: varsayılan 30) |
| `updatedSince` | ISO 8601; yalnız bu tarihten sonra değişen kayıtlar |
| Kaynağa özel süzgeçler | Aşağıdaki kaynak bölümlerinde |

Tutarlar sayı, tarihler ISO 8601 biçimindedir.

**Artımlı senkron örneği** — son çalışmadan beri değişen siparişleri sayfa sayfa okur:

```ts
import type { TecofApp } from "@tecof/app-sdk";

type ApiClient = ReturnType<TecofApp["client"]>;

export async function syncChangedOrders(api: ApiClient, since: string) {
  const limit = 200;
  for (let page = 1; ; page++) {
    const batch = await api.orders.list({ updatedSince: since, page, limit });
    for (const order of batch) {
      // siparişi işle
    }
    if (batch.length < limit) break;
  }
}
```

---

## Hız Sınırları

| Tür | Sınır | Kapsam |
| :--- | :--- | :--- |
| Okuma | 240 istek/dk | Kurulum başına |
| Yazma | 60 istek/dk | Kurulum başına |

Aşımda `429 rate-limited` döner. Uygulama token'ında mağazanın paket özelliği kapısı (`apiAccess`) uygulanmaz.

---

## Siparişler

| Metot | Uç | Kapsam |
| :--- | :--- | :--- |
| `GET` | `/api/v1/orders` | `orders:read` |
| `GET` | `/api/v1/orders/:idOrNumber` | `orders:read` |

Liste süzgeçleri: `status`, `paymentStatus`, `search`, `createdFrom`, `createdTo`, `updatedSince`. Tek sipariş uçu kimlik ya da sipariş numarası (`TCF-1001`) kabul eder.

```bash
curl "https://api.tecof.com/api/v1/orders?paymentStatus=paid&limit=20" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN"
```

```ts
const paid = await api.orders.list({ paymentStatus: "paid", limit: 20 });
const order = await api.orders.get("TCF-1001");
```

Sipariş nesnesi:

```json
{
  "id": "6720bb00cc11dd22ee33ff44",
  "orderNumber": "TCF-1001",
  "status": "confirmed",
  "paymentStatus": "paid",
  "currency": "TRY",
  "orderedAt": "2026-10-10T09:15:00.000Z",
  "createdAt": "2026-10-10T09:15:00.000Z",
  "updatedAt": "2026-10-10T09:16:12.000Z",
  "cancelledAt": null,
  "cancelReason": null,
  "customer": {
    "id": "66f1aa00bb11cc22dd33ee77",
    "firstName": "Örnek",
    "lastName": "Müşteri",
    "email": "musteri@example.com",
    "phone": "+905550000000"
  },
  "billingAddress": {
    "firstName": "Örnek", "lastName": "Müşteri", "company": "", "phone": "+905550000000",
    "email": "musteri@example.com", "country": "TR", "city": "İstanbul", "district": "Kadıköy",
    "zip": "34000", "line1": "Örnek Mah. Deneme Sk. No: 1", "line2": "", "identityNumber": "11111111111",
    "invoiceType": "individual", "taxNumber": "", "taxOffice": ""
  },
  "shippingAddress": {
    "firstName": "Örnek", "lastName": "Müşteri", "company": "", "phone": "+905550000000",
    "email": "musteri@example.com", "country": "TR", "city": "İstanbul", "district": "Kadıköy",
    "zip": "34000", "line1": "Örnek Mah. Deneme Sk. No: 1", "line2": "", "identityNumber": "",
    "invoiceType": "individual", "taxNumber": "", "taxOffice": ""
  },
  "lineItems": [
    {
      "id": "li_1", "productId": "66f2aa00bb11cc22dd33ee88", "variantId": "66f2aa00bb11cc22dd33ee99",
      "name": "Pamuklu Tişört", "variantTitle": "S / Siyah", "sku": "TS-S",
      "quantity": 2, "unitPrice": 500, "totalPrice": 1000,
      "taxRate": 20, "taxAmount": 166.67, "discountAmount": 0, "netTotal": 833.33, "taxIncluded": true,
      "personalizationTotal": 0
    }
  ],
  "shippingLines": [
    { "title": "Standart Kargo", "carrier": "Örnek Kargo", "deliveryMethod": "standard", "price": 50 }
  ],
  "discountLines": [],
  "totals": {
    "subtotal": 1000, "discount": 0, "shipping": 50, "paymentFee": 0,
    "tax": 175, "taxAddedToTotal": 0, "total": 1050,
    "pricesIncludeTax": true, "shippingTaxRate": 20, "shippingTaxAmount": 8.33, "shippingTaxIncluded": true
  },
  "payment": {
    "provider": "iyzico", "paidAmount": 1050, "paidAt": "2026-10-10T09:16:10.000Z",
    "installmentCount": 1, "cardAssociation": "VISA", "lastFourDigits": "0000"
  },
  "packages": [],
  "note": "",
  "tags": [],
  "salesChannelId": null
}
```

- **Fatura kimliği** (`billingAddress`): `invoiceType` `"individual"` ya da `"corporate"`. Kurumsalda `company` unvan, `taxNumber` vergi numarası, `taxOffice` vergi dairesidir. Türkiye'de `taxNumber` 10 haneli VKN (sağlama hanesi doğrulanmış) ya da şahıs şirketi için 11 haneli TCKN olur; yurt dışı kurumsal alıcıda serbest biçimlidir ve vergi dairesi boş olabilir. Bireysel alıcıda bu iki alan boştur, kimlik `identityNumber`'dadır (anonim alıcı `11111111111`). Ayrıntı ve hazır sınıflandırma için [Fatura Uygulamaları](/app-invoicing).
- `lineItems[].discountAmount`: satıra düşen sipariş indirimi, satırın kendi KDV modunda (hediye çeki hariç). Satırların toplamı `totals.discount`a eşittir. `netTotal` ve `taxAmount` indirim **sonrası** matrahı ve KDV'yi verir: KDV, indirim düşüldükten sonra kalan tutar üzerinden hesaplanır. Kapsamlı kupon yalnız kendi satırlarının matrahını düşürür. 10.10.2026 öncesi siparişlerde `discountAmount` 0'dır ve KDV indirim öncesi tutardan hesaplanmıştır.
- `lineItems[].taxRate` `null` ise kayıt eski bir siparişe aittir ve oran bilinmez; fatura uygulamaları mağaza varsayılan oranına düşmelidir.
- `packages[]`: `{ id, trackingNumber, carrier, status, items: [{ lineItemId, quantity }], shippedAt, deliveredAt }`.
- `discountLines[]`: `{ source, title, amount }`.

---

## Müşteriler

| Metot | Uç | Kapsam |
| :--- | :--- | :--- |
| `GET` | `/api/v1/customers` | `customers:read` |
| `GET` | `/api/v1/customers/:id` | `customers:read` |

Liste süzgeçleri: `search`, `updatedSince`.

```ts
const customers = await api.customers.list({ search: "musteri@example.com" });
const customer = await api.customers.get("66f1aa00bb11cc22dd33ee77");
```

```json
{
  "id": "66f1aa00bb11cc22dd33ee77",
  "firstName": "Örnek", "lastName": "Müşteri", "fullName": "Örnek Müşteri",
  "email": "musteri@example.com", "phone": "+905550000000",
  "accountStatus": "active", "isEmailVerified": true, "preferredLanguage": "tr",
  "groupIds": [], "tagIds": [], "note": "",
  "addresses": [
    {
      "id": "addr_1", "title": "Ev", "firstName": "Örnek", "lastName": "Müşteri",
      "phone": "+905550000000", "country": "TR", "city": "İstanbul", "district": "Kadıköy",
      "zip": "34000", "line1": "Örnek Mah. Deneme Sk. No: 1", "line2": "", "isDefault": true
    }
  ],
  "totalOrders": 3, "totalSpent": 2450, "firstOrderAt": "2026-08-01T10:00:00.000Z",
  "lastOrderAt": "2026-10-10T09:15:00.000Z",
  "createdAt": "2026-08-01T09:58:00.000Z", "updatedAt": "2026-10-10T09:15:00.000Z"
}
```

Parola ve token alanları hiçbir koşulda dönmez.

---

## Envanter

| Metot | Uç | Kapsam |
| :--- | :--- | :--- |
| `GET` | `/api/v1/inventory` | `products:read` |

Süzgeçler: `sku`, `productId`, `lowStock`, `updatedSince`. Her satır bir varyanttır:

```json
{
  "productId": "66f2aa00bb11cc22dd33ee88",
  "productName": "Pamuklu Tişört",
  "productSlug": "pamuklu-tisort",
  "variantId": "66f2aa00bb11cc22dd33ee99",
  "sku": "TS-S",
  "barcode": "8690000000000",
  "title": "S / Siyah",
  "price": 500,
  "stock": 12,
  "locations": [{ "locationId": "66f3aa00bb11cc22dd33ee00", "name": "Ana Depo", "quantity": 12 }],
  "updatedAt": "2026-10-10T08:00:00.000Z"
}
```

```ts
const lowStock = await api.inventory.list({ lowStock: true });
```

Stok yazma Tools API üzerinden yapılır (`apply_stock_count`, `products:write`) — aşağıya bakın.

---

## Ürünler

| Metot | Uç | Kapsam |
| :--- | :--- | :--- |
| `GET` | `/api/v1/products` | `products:read` |
| `GET` | `/api/v1/products/:idOrSlug` | `products:read` |
| `POST` | `/api/v1/products` | `products:write` (upsert) |
| `PATCH` | `/api/v1/products/:id` | `products:write` |

Ürün uçları mevcut Developer API ürün sözleşmesini kullanır: liste hafiftir (`fields=full` ile açıklama ve varyantlar gelir), `:idOrSlug` kimlik, slug ya da varyant SKU'su kabul eder, çok dilli alanlar `[{ code, value }]` biçimindedir. Ürün listesinde süzgeçler: `search`, `status`, `category`, `brand`, `tag`, `updatedSince`, `fields=full`. Ürün listesinin varsayılan `limit` değeri 30'dur (en fazla 200). Ürün nesneleri kimliği `_id` alanında taşır (sipariş, müşteri ve envanterde `id`).

```ts
const products = await api.products.list({ status: "active", limit: 50 });
const product = await api.products.get("pamuklu-tisort");
```

```json
{
  "_id": "66f2aa00bb11cc22dd33ee88",
  "slug": "pamuklu-tisort",
  "name": [{ "code": "tr", "value": "Pamuklu Tişört" }],
  "status": "active",
  "type": "variable",
  "totalStock": 12,
  "variantCount": 2,
  "variants": [
    {
      "_id": "66f2aa00bb11cc22dd33ee99", "sku": "TS-S", "barcode": null,
      "price": 500, "compareAtPrice": 650, "weight": 300, "isActive": true,
      "stock": 12, "stocks": [{ "stockLocationId": "66f3aa00bb11cc22dd33ee00", "quantity": 12 }],
      "variantValues": [{ "variantTypeId": "…", "variantValueId": "…" }]
    }
  ]
}
```

> Ürün yazma anında canlıdır: `status: "active"` gönderilen ürün vitrine çıkar. Ürün yazma ayrıca mağaza paketinde e-ticaretin açık olmasını ister (`403 plan-feature-unavailable`).

---

## Yazma İşlemleri: Tools API

Okuma dışındaki işlemler (stok sayımı uygulama gibi) Tecof'un tek araç kayıt defteri üzerinden, Tools API ile yapılır. Aynı araçlar MCP sunucusunda da kullanılır. Uygulama token'ı `api` yüzeyindeki araçları, mağazanın **verdiği** kapsamlarla görür ve çalıştırır.

| Metot | Uç | Açıklama |
| :--- | :--- | :--- |
| `GET` | `/api/v1/tools?surface=api` | Araç kataloğu (ad, açıklama, JSON Schema girdi, gereken kapsamlar, onay ve kredi bilgisi) |
| `GET` | `/api/v1/tools/:name` | Tek aracın tanımı |
| `POST` | `/api/v1/tools/:name` | Aracı çalıştırır; gövde = araç girdisi (JSON) |

Her aracın girdi şeması katalogda `inputSchema` olarak yayımlanır. Çağırmadan önce şemayı okuyun:

```bash
curl "https://api.tecof.com/api/v1/tools/apply_stock_count" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN"
```

```ts
// Girdi alanlarını aracın inputSchema'sına göre doldurun
const result = await api.tools.call("apply_stock_count", input);
```

Ham HTTP ile çalıştırma:

```bash
curl -X POST "https://api.tecof.com/api/v1/tools/apply_stock_count" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: stock-sync-2026-10-10-0001" \
  -d @input.json
```

| Konu | Davranış |
| :--- | :--- |
| Kapsam | Araç başına denetlenir: `403 insufficient-scope { required, missing }` |
| Doğrulama | `400 validation-error { issues: [{ path, message }] }` |
| `Idempotency-Key` | İsteğe bağlı (≤128 karakter). Aynı anahtar + aynı girdi → saklanan yanıt (`Idempotency-Replayed: true`); farklı girdi → `422 idempotency-key-reused`; işlem sürerken → `409 idempotency-in-progress`. Saklama 24 saat |
| Onay isteyen araçlar | İlk çağrı `409 confirmation-required { needsConfirmation, confirmId, summary, expiresAt }` döner; **aynı girdiyle** `confirm: true` ve `confirmId` ekleyerek yeniden çağırın (aşağıda) |
| Hız sınırı | `429 rate-limited` + `Retry-After: 60` |
| Akış | `?stream=1` ile `text/event-stream` (ilerleme + sonuç çerçeveleri) |

### Onay isteyen araçlar

Silme ya da canlıyı doğrudan değiştiren araçlar iki adımda çalışır. Uygulama token'ında da akış kişisel erişim anahtarıyla aynıdır: onayı sizin uygulamanız verir (gerekirse kullanıcıya App Bridge `confirm` ile sorarak).

```ts
import { TecofApiError } from "@tecof/app-sdk";

async function callWithConfirm(api: ApiClient, name: string, input: Record<string, unknown>) {
  try {
    return await api.tools.call(name, input);
  } catch (err) {
    if (err instanceof TecofApiError && err.code === "confirmation-required") {
      const { confirmId, summary } = err.data as { confirmId: string; summary: string };
      // summary'yi kaydedin ya da kullanıcıya gösterin; onaylandıysa aynı girdiyle tekrar çağırın
      return api.tools.call(name, { ...input, confirm: true, confirmId });
    }
    throw err;
  }
}
```

`confirmId` süresi dolmuşsa `409 confirmation-expired` döner; `confirmId` olmadan baştan çağırın.

---

## Uygulamaya Özel Uçlar

Bu uçlar yalnız uygulama token'ıyla çalışır ve kapsam istemez (metafield'lar hariç); veri kuruluma aittir. Kişisel erişim anahtarıyla (PAT) `/api/v1/app/*` çağrısı `403 app-token-required` döner.

| Metot | Uç | Açıklama | SDK |
| :--- | :--- | :--- | :--- |
| `GET` | `/api/v1/app/installation` | Kurulumun kendisi | `api.installation()` |
| `GET` | `/api/v1/app/settings` | Ayarlar | `api.settings.get()` |
| `PUT` | `/api/v1/app/settings` | Ayar yazma | `api.settings.set(obj, { merge })` |
| `GET` | `/api/v1/app/secrets` | Sır listesi (değer yok) | `api.secrets.list()` |
| `GET` | `/api/v1/app/secrets/:key` | Sır okuma | `api.secrets.get(key)` |
| `PUT` | `/api/v1/app/secrets/:key` | Sır yazma | `api.secrets.set(key, value)` |
| `DELETE` | `/api/v1/app/secrets/:key` | Sır silme | `api.secrets.delete(key)` |
| `POST` | `/api/v1/app/events` | Uygulama olayı yayınlama | `api.events.publish(name, data)` |
| `GET` | `/api/v1/app/events/catalog` | Mağazadaki uygulama olayları | `api.events.catalog()` |
| `GET` | `/api/v1/metafields` | Metafield listesi | `api.metafields.list({...})` |
| `PUT` | `/api/v1/metafields` | Metafield yazma | `api.metafields.set({...})` |
| `DELETE` | `/api/v1/metafields/:id` | Metafield silme | `api.metafields.delete(id)` |

### Kurulum

```ts
const installation = await api.installation();
```

```json
{
  "installationId": "6720aa00bb11cc22dd33ee55",
  "status": "active",
  "installedAt": "2026-10-10T08:00:00.000Z",
  "isTestInstall": false,
  "scopes": ["orders:read", "customers:read", "products:read"],
  "pendingScopes": [],
  "merchant": {
    "id": "66f0c0ffee0000000000abcd", "name": "Örnek Mağaza", "productType": "ecommerce",
    "languages": ["tr", "en"], "defaultLanguage": "tr", "currency": "TRY"
  },
  "app": { "clientId": "tcfa_xxxxxxxxxxxxxxxx", "slug": "isbasi", "name": "Logo İşbaşı", "configVersion": 3 },
  "subscription": { "planKey": "standart", "status": "active", "trialEndsAt": null, "currentPeriodEnd": "2026-11-10T09:16:10.000Z" }
}
```

`isTestInstall: true`, kurulumun uygulamanın test mağazalarından birinde olduğunu gösterir. Plan yoksa `subscription` `null` olur. `pendingScopes`, mağazanın henüz onaylamadığı kapsam artışıdır.

### Ayarlar

```bash
curl "https://api.tecof.com/api/v1/app/settings" -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN"
```

```json
{ "success": true, "messageCode": "success", "data": { "settings": { "invoiceMode": "draft" }, "updatedAt": "2026-10-10T09:00:00.000Z" } }
```

```bash
curl -X PUT "https://api.tecof.com/api/v1/app/settings" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "settings": { "invoiceMode": "issued" }, "merge": true }'
```

Yanıt: `{ settings, updatedAt }`. Sır olmayan JSON, en fazla 64 KB. `merge: true` mevcut nesneyle birleştirir. API'den ayar yazmak `app.settings.updated` olayı **üretmez** (olay yalnız panel formu kaydında gelir).

### Sırlar (Vault)

```bash
# Yazma
curl -X PUT "https://api.tecof.com/api/v1/app/secrets/isbasiApiKey" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "value": "örnek-api-anahtarı" }'
# → { "data": { "key": "isbasiApiKey", "updatedAt": "…" } }

# Listeleme (değer dönmez)
curl "https://api.tecof.com/api/v1/app/secrets" -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN"
# → { "data": [ { "key": "isbasiApiKey", "updatedAt": "…", "lastReadAt": "…", "length": 18 } ] }

# Okuma
curl "https://api.tecof.com/api/v1/app/secrets/isbasiApiKey" -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN"
# → { "data": { "key": "isbasiApiKey", "value": "örnek-api-anahtarı", "updatedAt": "…" } }
```

Kurallar ve şifreleme tasarımı: [Ayarlar, Vault ve Metafield'lar](/app-data).

### Metafield'lar

```bash
curl -X PUT "https://api.tecof.com/api/v1/metafields" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ownerType": "order",
    "ownerId": "6720bb00cc11dd22ee33ff44",
    "key": "invoiceNumber",
    "type": "string",
    "value": "ABC2026000000123",
    "visibility": "shared",
    "panel": { "label": { "tr": "İşbaşı fatura no", "en": "İşbaşı invoice no" }, "show": true }
  }'

curl "https://api.tecof.com/api/v1/metafields?ownerType=order&ownerId=6720bb00cc11dd22ee33ff44&namespace=isbasi" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN"
```

`PUT` yanıtı:

```json
{
  "id": "6720ee00ff11aa22bb33cc77",
  "namespace": "isbasi",
  "ownerType": "order",
  "ownerId": "6720bb00cc11dd22ee33ff44",
  "key": "invoiceNumber",
  "type": "string",
  "value": "ABC2026000000123",
  "visibility": "shared",
  "panel": { "label": { "tr": "İşbaşı fatura no", "en": "İşbaşı invoice no" }, "show": true },
  "own": true,
  "updatedAt": "2026-10-10T09:20:00.000Z"
}
```

`own`, kaydın çağıran uygulamanın namespace'ine ait olup olmadığını gösterir. `ownerType: "merchant"` için `ownerId` yok sayılır (kayıt mağazaya bağlanır).

### Uygulama olayları

```bash
curl -X POST "https://api.tecof.com/api/v1/app/events" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "invoice.created", "data": { "orderId": "6720bb00cc11dd22ee33ff44", "invoiceNumber": "ABC2026000000123" } }'
```

Mağazadaki diğer uygulamaların yayınladığı olaylar:

```ts
const catalog = await api.events.catalog();
// [{ slug: "kargo", appName: "Örnek Kargo", event: "app.kargo.shipment.created", description: { tr: "…", en: "…" } }]
```

Ayrıntılar: [Uygulamalar Arası İletişim](/app-interop).
