İçeriğe geç
Docs

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.

Son güncelleme:

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.

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

Token almak için bkz. Kimlik Doğrulama → Kurulum token'ı. SDK kullanıyorsanız token yönetimi otomatiktir:

TypeScript
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
}
AlanAçıklama
successİşlem sonucu
messageİnsan okur mesaj
messageCodeMakine okur kod (hata ayrımı için bunu kullanın)
dataYük
totalDataListe 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).

TypeScript
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ı#

HTTPmessageCodeNe yapmalı
401token-expiredToken'ın süresi doldu; yeni token alın (SDK otomatik yeniler)
401token-revokedToken iptal edildi (kaldırma, kapsam değişikliği); yeni token alın, kurulum aktif değilse çağrıyı bırakın
401token-invalidToken tanınmıyor ya da biçimi bozuk
401app-suspendedUygulama Tecof tarafından askıya alındı; token basılmaz
403app-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
403insufficient-scopedata: { required, missing }; kapsamı tecof.app.json'a ekleyin, mağaza onaylamalı
404not-foundKayıt yok
429rate-limitedHız sınırı aşıldı; bekleyip yeniden deneyin

Sayfalama ve Süzgeçler#

ParametreAçıklama
page1'den başlar
limitEn fazla 200; varsayılan 50 (ürün listesi eski sözleşmeyi korur: varsayılan 30)
updatedSinceISO 8601; yalnız bu tarihten sonra değişen kayıtlar
Kaynağa özel süzgeçlerAş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:

TypeScript
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ürSınırKapsam
Okuma240 istek/dkKurulum başına
Yazma60 istek/dkKurulum başına

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


Siparişler#

MetotUçKapsam
GET/api/v1/ordersorders:read
GET/api/v1/orders/:idOrNumberorders:read

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

Terminal
curl "https://api.tecof.com/api/v1/orders?paymentStatus=paid&limit=20" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN"
TypeScript
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ı.
  • lineItems[].discountAmount: satıra düşen sipariş indirimi, satırın kendi KDV modunda (hediye çeki hariç). Satırların toplamı totals.discounta 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#

MetotUçKapsam
GET/api/v1/customerscustomers:read
GET/api/v1/customers/:idcustomers:read

Liste süzgeçleri: search, updatedSince.

TypeScript
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#

MetotUçKapsam
GET/api/v1/inventoryproducts: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"
}
TypeScript
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#

MetotUçKapsam
GET/api/v1/productsproducts:read
GET/api/v1/products/:idOrSlugproducts:read
POST/api/v1/productsproducts:write (upsert)
PATCH/api/v1/products/:idproducts: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).

TypeScript
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.

MetotUçAçıklama
GET/api/v1/tools?surface=apiAraç kataloğu (ad, açıklama, JSON Schema girdi, gereken kapsamlar, onay ve kredi bilgisi)
GET/api/v1/tools/:nameTek aracın tanımı
POST/api/v1/tools/:nameAracı ç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:

Terminal
curl "https://api.tecof.com/api/v1/tools/apply_stock_count" \
  -H "Authorization: Bearer $TECOF_INSTALLATION_TOKEN"
TypeScript
// 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:

Terminal
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
KonuDavranış
KapsamAraç başına denetlenir: 403 insufficient-scope { required, missing }
Doğrulama400 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).

TypeScript
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.

MetotUçAçıklamaSDK
GET/api/v1/app/installationKurulumun kendisiapi.installation()
GET/api/v1/app/settingsAyarlarapi.settings.get()
PUT/api/v1/app/settingsAyar yazmaapi.settings.set(obj, { merge })
GET/api/v1/app/secretsSır listesi (değer yok)api.secrets.list()
GET/api/v1/app/secrets/:keySır okumaapi.secrets.get(key)
PUT/api/v1/app/secrets/:keySır yazmaapi.secrets.set(key, value)
DELETE/api/v1/app/secrets/:keySır silmeapi.secrets.delete(key)
POST/api/v1/app/eventsUygulama olayı yayınlamaapi.events.publish(name, data)
GET/api/v1/app/events/catalogMağazadaki uygulama olaylarıapi.events.catalog()
GET/api/v1/metafieldsMetafield listesiapi.metafields.list({...})
PUT/api/v1/metafieldsMetafield yazmaapi.metafields.set({...})
DELETE/api/v1/metafields/:idMetafield silmeapi.metafields.delete(id)

Kurulum#

TypeScript
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#

Terminal
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" } }
Terminal
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)#

Terminal
# 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.

Metafield'lar#

Terminal
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ı#

Terminal
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:

TypeScript
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.