Yeni·E-Ticaret Pro Paketi Yayında — Entegre Ödeme, Stok ve Sipariş YönetimiBlog·2025'te Küçük İşletmeler İçin Web Tasarım TrendleriKampanya·Mayıs Ayına Özel %20 İndirim — Kartvizit & Başlangıç Paketleriİçgörü·Müşteri Projelerinde Dönüşüm Oranı Ortalama %40 Artış SağlandıBlog·SEO'ya Yeni Başlayanlar İçin Temel Rehber — Ücretsiz İndirHaber·Ankara'da Yeni Çözüm Ortaklıkları ile Hizmet Ağı GenişliyorGüncelleme·Tüm Projeler İçin Ücretsiz SSL, CDN ve Hız Optimizasyonu DahilYeni·Çözümler Sayfası Açıldı — Sektöre Özel Web ÇözümleriKampanya·Ücretsiz Web Sitesi Değerlendirmesi — Bugün Başvurİçgörü·Ortalama Proje Teslim Süresi: 14 Gün — GarantiliYeni·E-Ticaret Pro Paketi Yayında — Entegre Ödeme, Stok ve Sipariş YönetimiBlog·2025'te Küçük İşletmeler İçin Web Tasarım TrendleriKampanya·Mayıs Ayına Özel %20 İndirim — Kartvizit & Başlangıç Paketleriİçgörü·Müşteri Projelerinde Dönüşüm Oranı Ortalama %40 Artış SağlandıBlog·SEO'ya Yeni Başlayanlar İçin Temel Rehber — Ücretsiz İndirHaber·Ankara'da Yeni Çözüm Ortaklıkları ile Hizmet Ağı GenişliyorGüncelleme·Tüm Projeler İçin Ücretsiz SSL, CDN ve Hız Optimizasyonu DahilYeni·Çözümler Sayfası Açıldı — Sektöre Özel Web ÇözümleriKampanya·Ücretsiz Web Sitesi Değerlendirmesi — Bugün Başvurİçgörü·Ortalama Proje Teslim Süresi: 14 Gün — Garantili
ilkkod
Pazar Yeri Entegrasyonları

Trendyol ve Hepsiburada API Entegrasyonu: Next.js ile Ürün Yönetim Paneli

Trendyol Seller API ve Hepsiburada Merchant API'yi Next.js App Router ile entegre edin. Basic Auth, batchRequestId async onay döngüsü, webhook + polling stratejisi ve Vercel Cron kısıtları.

İlker
19 Mart 2026
22 dk
Trendyol ve Hepsiburada API Entegrasyonu: Next.js ile Ürün Yönetim Paneli

Önemli Not: Bu yazıdaki teknik bilgiler yazım tarihi itibarıyla geçerlidir. Kullanılan kütüphaneler, API'ler ve servisler zaman içinde değişebilir. Ücretlendirme, yasal düzenleme ve vergi konularında ilgili resmi kaynakları ve uzmanları referans alınız. Bu içerik bilgilendirme amaçlı olup herhangi bir finansal veya hukuki tavsiye niteliği taşımamaktadır.

Türkiye'de bir KOBİ için yazılım geliştiriyorsanız, er ya da geç Trendyol veya Hepsiburada API'siyle yüzleşmek zorunda kalırsınız. Resmi dokümantasyonlar var; ama "Next.js App Router ile nasıl entegre ederim, async ürün onay sürecini nasıl yönetirim, Vercel'de cron job kısıtlarını nasıl aşarım?" sorularının yanıtları dağınık ve eksik.

Bu rehberde sıfırdan bir Ürün Yönetim Paneli mimarisi kuruyoruz. Trendyol ve Hepsiburada API kimlik doğrulaması, webhook + polling stratejisi, batchRequestId ile async ürün onayı döngüsü ve Vercel Cron kısıtlarını detaylıca ele alacağız.

Türkiye E-Ticaret Ekosistemi: Hangi Platformlar Önemli?

2024 verileri Türkiye e-ticaret pazarının yaklaşık 3 trilyon TL GMV'ye ulaştığını gösteriyor (Ticaret Bakanlığı, "E-Ticaretin Görünümü 2025" raporu). 2024 yılında gerçekleşen işlem sayısı 5,91 milyar.

Aktif marketplace'ler (2026):

  • Trendyol — pazar lideri, yaklaşık %36 pay
  • Hepsiburada — ikinci büyük
  • N11 — düşük trafikle faaliyette (Hâlâ açık, 2025'te DMSF Holding'e geçti)
  • Çiçeksepeti, Sahibinden (ilan), Letgo (ilan) — niş segmentler

GittiGidiyor hakkında: Platform tamamen kapandı. Yeni listeleme 20 Haziran 2022'de, son alışveriş 18 Temmuz 2022'de sona erdi. Devam eden API yoktur.

N11 hakkında: Amazon N11'i satın almadı — bu yaygın bir yanlış bilgi. Sahiplik zinciri: Doğuş Grubu + SK Planet → Getir kurucusu Nazım Salur (2023) → Borancılı Teknoloji (2024) → DMSF Holding (Abu Dhabi, 2025). API hâlâ erişilebilir, ancak DMSF sonrası developer portal değişiklikleri için güncel dokümantasyonu kontrol edin.

Hedef kitlemiz açısından Trendyol ve Hepsiburada öncelikli entegrasyon noktaları. Bu iki platform için custom bir yönetim paneli kuracağız.

Ne İnşa Ediyoruz?

Ürün Yönetim Paneli — bir KOBİ'nin kendi ürünlerini hem Trendyol hem Hepsiburada'da yönetebileceği basit bir Next.js uygulaması:

  • Ürün listesi ve stok görüntüleme
  • Trendyol'a ürün gönderme + onay durumu takibi
  • Hepsiburada sipariş bildirimleri (webhook)
  • Otomatik stok senkronizasyonu (cron job)

Tech stack: Next.js 16 App Router, TypeScript, Drizzle ORM, Bun

Trendyol Seller API

Erişim Alma

Trendyol API erişimi için önce satıcı hesabı açmanız, ardından entegrasyon başvurusunu Seller Panel üzerinden yapmanız gerekiyor. Onay sürecini resmi developers.trendyol.com adresinden takip edin.

Kimlik Doğrulama

Trendyol, HTTP Basic Auth kullanır. Seller Panel → Hesap Bilgilerim → Entegrasyon Bilgileri bölümünden üç credential alırsınız:

  • supplierId (a.k.a. sellerId)
  • apiKey
  • apiSecret

Authorization header'ı: Basic Base64(apiKey:apiSecret)

Kritik nokta — User-Agent zorunlu: Trendyol, her istekte özel bir User-Agent header'ı bekler. Bu header olmadan istekler reddedilir:

User-Agent: "<supplierId> - SelfIntegration"

Base URL'ler

Production: https://apigw.trendyol.com
Stage:      https://stageapigw.trendyol.com

Önemli: Production ve Stage credential'ları tamamen ayrıdır. Stage ortamı için Trendyol ekibinden ayrıca credential almanız gerekiyor. Ayrıca Stage ortamı IP whitelist zorunlu tutuyor — sunucunuzun IP adresini Trendyol'a bildirmeniz gerekiyor.

TypeScript API Client

Ortam değişkenlerini ve API client'ı ayarlayalım:

// lib/marketplace/trendyol-client.ts const TRENDYOL_BASE_URL = process.env.TRENDYOL_STAGE === "true" ? "https://stageapigw.trendyol.com" : "https://apigw.trendyol.com" interface TrendyolConfig { supplierId: string apiKey: string apiSecret: string } function getTrendyolHeaders(config: TrendyolConfig): HeadersInit { const credentials = Buffer.from(`${config.apiKey}:${config.apiSecret}`).toString("base64") return { "Authorization": `Basic ${credentials}`, "User-Agent": `${config.supplierId} - SelfIntegration`, "Content-Type": "application/json", } } export async function trendyolFetch<T>( path: string, options: RequestInit = {}, ): Promise<T> { const config: TrendyolConfig = { supplierId: process.env.TRENDYOL_SUPPLIER_ID!, apiKey: process.env.TRENDYOL_API_KEY!, apiSecret: process.env.TRENDYOL_API_SECRET!, } const url = `${TRENDYOL_BASE_URL}${path}` const response = await fetch(url, { ...options, headers: { ...getTrendyolHeaders(config), ...options.headers, }, }) if (!response.ok) { const errorText = await response.text() throw new Error(`Trendyol API error ${response.status}: ${errorText}`) } return response.json() as Promise<T> }

Temel Endpoint'ler

İşlemMethodPath
Ürün oluşturPOST/integration/product/sellers/{supplierId}/products
Ürün güncellePUT/integration/product/sellers/{supplierId}/products
Fiyat + stok güncellePUT/integration/product/sellers/{supplierId}/products/price-and-inventory
Batch sonucu kontrolGET/integration/product/sellers/{supplierId}/batch-requests/{batchRequestId}
Siparişleri çekGET/integration/order/sellers/{supplierId}/orders
Kargo takibi güncellePUT/integration/order/sellers/{supplierId}/shipment-packages/{packageId}/tracking
Tedarikçi adresleriGET/integration/sellers/{supplierId}/addresses

Rate Limit

Güncel rate limit bilgisi için resmi dokümantasyonu kontrol edin — bu değerler değişebilir. Araştırma bulguları endpoint başına 50 istek / 10 saniye düzeyine işaret ediyor, ancak bu bilgiyi developers.trendyol.com üzerinden doğrulayın.

Async Ürün Onayı: batchRequestId Döngüsü

Trendyol'un en kritik mimarisi burada. Ürün oluşturma veya güncelleme işlemleri anlık değildir. Trendyol, her ürün yazma çağrısına bir batchRequestId (UUID format) döner. Ürün, Trendyol moderasyonundan geçtikten sonra yayına alınır.

Bu asenkron döngüyü naif bir şekilde ele alırsanız (örneğin bir while döngüsüyle sürekli poll etmek), Vercel'in serverless timeout kısıtlarına çarpar veya rate limit'e takılırsınız.

batchRequestId ile Stok Güncelleme Route Handler

// app/api/trendyol/products/route.ts import { NextResponse } from "next/server" import { db } from "@/lib/db" import { productBatches } from "@/lib/db/schema" import { trendyolFetch } from "@/lib/marketplace/trendyol-client" interface PriceInventoryItem { barcode: string quantity: number salePrice: number listPrice: number } interface TrendyolBatchResponse { batchRequestId: string } export async function PUT(request: Request) { const supplierId = process.env.TRENDYOL_SUPPLIER_ID! const items: PriceInventoryItem[] = await request.json() // Trendyol'a fiyat + stok güncellemesi gönder const result = await trendyolFetch<TrendyolBatchResponse>( `/integration/product/sellers/${supplierId}/products/price-and-inventory`, { method: "PUT", body: JSON.stringify({ items }), }, ) // batchRequestId'yi DB'ye kaydet await db.insert(productBatches).values({ batchRequestId: result.batchRequestId, status: "PENDING", itemCount: items.length, createdAt: new Date(), }) // Async işlem başlatıldı — hemen yanıt dön return NextResponse.json({ batchRequestId: result.batchRequestId, message: "Güncelleme kuyruğa alındı. Onay durumu takip edilecek.", }) }

Drizzle ORM ile Batch Takip Şeması

// lib/db/schema/product-batches.ts import { pgTable, text, integer, timestamp } from "drizzle-orm/pg-core" export const productBatches = pgTable("product_batches", { id: text("id").primaryKey().default("gen_random_uuid()"), batchRequestId: text("batch_request_id").notNull().unique(), platform: text("platform").notNull().default("trendyol"), // "trendyol" | "hepsiburada" status: text("status").notNull().default("PENDING"), // PENDING | IN_PROGRESS | COMPLETED | FAILED itemCount: integer("item_count"), errorDetails: text("error_details"), createdAt: timestamp("created_at").notNull().defaultNow(), resolvedAt: timestamp("resolved_at"), })

Batch Durumu Poll Endpoint'i

// app/api/trendyol/batches/[batchRequestId]/route.ts import { NextResponse } from "next/server" import { db } from "@/lib/db" import { productBatches } from "@/lib/db/schema" import { trendyolFetch } from "@/lib/marketplace/trendyol-client" import { eq } from "drizzle-orm" interface BatchResult { batchRequestId: string status: "COMPLETED" | "FAILED" | "IN_PROGRESS" items: Array<{ requestItem: { barcode: string } status: "SUCCESS" | "ERROR" failureReasons?: Array<{ code: string; message: string }> }> } export async function GET( _request: Request, { params }: { params: Promise<{ batchRequestId: string }> }, ) { const { batchRequestId } = await params const supplierId = process.env.TRENDYOL_SUPPLIER_ID! const result = await trendyolFetch<BatchResult>( `/integration/product/sellers/${supplierId}/batch-requests/${batchRequestId}`, ) // DB'deki kaydı güncelle await db .update(productBatches) .set({ status: result.status, resolvedAt: result.status !== "IN_PROGRESS" ? new Date() : null, errorDetails: result.status === "FAILED" ? JSON.stringify(result.items.filter((i) => i.status === "ERROR")) : null, }) .where(eq(productBatches.batchRequestId, batchRequestId)) return NextResponse.json(result) }

Inngest veya QStash ile Durable Execution

Batch durumunu her istekte veya naif bir setTimeout ile poll etmek serverless ortamda mümkün değil. İki sağlam çözüm var:

Seçenek A: Inngest (Karmaşık Step Function)

Inngest, Vercel ile native entegrasyona sahip. Trendyol'un 5-30 dakika sürebilen async onay beklemesini durable execution ile yönetmek için idealdir.

// inngest/functions/trendyol-batch-poll.ts import { inngest } from "@/lib/inngest" import { db } from "@/lib/db" import { productBatches } from "@/lib/db/schema" import { trendyolFetch } from "@/lib/marketplace/trendyol-client" import { eq } from "drizzle-orm" export const trendyolBatchPollFn = inngest.createFunction( { id: "trendyol-batch-poll" }, { event: "trendyol/batch.created" }, async ({ event, step }) => { const { batchRequestId } = event.data // İlk kontrol: 5 dakika bekle await step.sleep("initial-delay", "5 minutes") for (let attempt = 0; attempt < 10; attempt++) { const result = await step.run(`check-batch-${attempt}`, async () => { const supplierId = process.env.TRENDYOL_SUPPLIER_ID! return trendyolFetch( `/integration/product/sellers/${supplierId}/batch-requests/${batchRequestId}`, ) }) if ((result as { status: string }).status === "COMPLETED") { await db .update(productBatches) .set({ status: "COMPLETED", resolvedAt: new Date() }) .where(eq(productBatches.batchRequestId, batchRequestId)) return { success: true } } if ((result as { status: string }).status === "FAILED") { await db .update(productBatches) .set({ status: "FAILED", resolvedAt: new Date() }) .where(eq(productBatches.batchRequestId, batchRequestId)) return { success: false, reason: "Trendyol batch başarısız" } } // IN_PROGRESS → 3 dakika daha bekle if (attempt < 9) { await step.sleep(`retry-delay-${attempt}`, "3 minutes") } } return { success: false, reason: "Maksimum deneme sayısına ulaşıldı" } }, )

Ürün gönderimi yapan Route Handler'da event'i tetikleyin:

import { inngest } from "@/lib/inngest" // batchRequestId aldıktan sonra: await inngest.send({ name: "trendyol/batch.created", data: { batchRequestId: result.batchRequestId }, })

Seçenek B: QStash (Basit HTTP Kuyruğu)

Upstash QStash, Vercel'in 10 saniyelik timeout sorununu aşmak için daha basit bir çözüm sunar. Ayrıca Vercel Hobby planının cron kısıtlarını bypass etmek için QStash cron kullanabilirsiniz.

// app/api/trendyol/batches/poll-worker/route.ts // Bu endpoint QStash tarafından çağrılır import { verifySignatureAppRouter } from "@upstash/qstash/dist/nextjs" import { NextResponse } from "next/server" import { db } from "@/lib/db" import { productBatches } from "@/lib/db/schema" import { trendyolFetch } from "@/lib/marketplace/trendyol-client" import { eq, and } from "drizzle-orm" async function handler(_request: Request) { const supplierId = process.env.TRENDYOL_SUPPLIER_ID! // Bekleyen tüm batch'leri kontrol et const pendingBatches = await db .select() .from(productBatches) .where( and( eq(productBatches.status, "PENDING"), eq(productBatches.platform, "trendyol"), ), ) for (const batch of pendingBatches) { try { const result = await trendyolFetch<{ status: string }>( `/integration/product/sellers/${supplierId}/batch-requests/${batch.batchRequestId}`, ) if (result.status !== "IN_PROGRESS") { await db .update(productBatches) .set({ status: result.status, resolvedAt: new Date(), }) .where(eq(productBatches.batchRequestId, batch.batchRequestId)) } } catch { // Rate limit veya geçici hata — bir sonraki turda dene } } return NextResponse.json({ processed: pendingBatches.length }) } export const POST = verifySignatureAppRouter(handler)

Webhook + Polling Fallback Stratejisi

Trendyol webhook desteği sunuyor — satıcı başına maksimum 15 webhook tanımlanabilir (pasif olanlar da bu sayıya dahil). Başarısız webhook teslimatları 5 dakikada bir yeniden deneniyor.

Ancak dikkat: Trendyol'un kendi resmi dokümantasyonu bile, webhook'a ek olarak periyodik polling (getshipmentpackage) yapmanızı öneriyor. Webhook teslimatı garantili değil.

Sipariş webhook'u için Route Handler:

// app/api/webhooks/trendyol/route.ts import { NextResponse } from "next/server" import { db } from "@/lib/db" import { orders } from "@/lib/db/schema" interface TrendyolOrderWebhook { orderId: string orderNumber: string status: string lines: Array<{ id: string quantity: number productName: string }> } export async function POST(request: Request) { // Trendyol webhook imzası — resmi dokümantasyonu kontrol edin const payload: TrendyolOrderWebhook = await request.json() await db.insert(orders).values({ externalId: payload.orderId, orderNumber: payload.orderNumber, platform: "trendyol", status: payload.status, rawPayload: JSON.stringify(payload), receivedAt: new Date(), }) return NextResponse.json({ received: true }) }

Polling fallback — sipariş çekme:

// lib/marketplace/trendyol-sync.ts export async function syncTrendyolOrders(): Promise<void> { const supplierId = process.env.TRENDYOL_SUPPLIER_ID! const since = new Date(Date.now() - 15 * 60 * 1000) // Son 15 dakika const startDate = since.getTime() // Unix timestamp ms const result = await trendyolFetch<{ content: unknown[] }>( `/integration/order/sellers/${supplierId}/orders?startDate=${startDate}&orderByField=CreatedDate&orderByDirection=DESC`, ) for (const order of result.content) { // Idempotent upsert — webhook ile gelen sipariş tekrar işlenmez await upsertOrder(order as Record<string, unknown>, "trendyol") } }

Hepsiburada Merchant API

Kimlik Doğrulama

Hepsiburada da HTTP Basic Auth kullanıyor. Seller Portal üzerinden username + password alınıyor.

Authorization: Basic Base64(username:password)

Dikkat: Hepsiburada kimlik doğrulama yapısı yakın zamanda değişti. Eski implementasyonlarınız varsa güncel developer dokümantasyonunu kontrol edin.

Base URL'ler

Production: https://marketplace-api.hepsiburada.com
Test/SIT:   https://marketplace-api-sit.hepsiburada.com

SIT ortamı için Hepsiburada Marketplace Integration ekibine başvurmanız gerekiyor. Onay sonrası Merchant ID email ile gönderilir.

Temel Endpoint'ler

POST /product/api/products/import        — Ürün yükleme (dosya tabanlı)
GET  /product/api/products/all-products-of-merchant  — Tüm ürünleri listele
GET  /order-items/...                    — Sipariş yönetimi

Önemli fark: Hepsiburada'da ürün yükleme dosya tabanlı import ile çalışıyor — Trendyol'daki gibi doğrudan JSON API değil. Bu biraz daha yüksek entegrasyon süresi anlamına geliyor.

Hepsiburada API Client

// lib/marketplace/hepsiburada-client.ts const HB_BASE_URL = process.env.HEPSIBURADA_STAGE === "true" ? "https://marketplace-api-sit.hepsiburada.com" : "https://marketplace-api.hepsiburada.com" export async function hepsiburadaFetch<T>( path: string, options: RequestInit = {}, ): Promise<T> { const username = process.env.HEPSIBURADA_USERNAME! const password = process.env.HEPSIBURADA_PASSWORD! const credentials = Buffer.from(`${username}:${password}`).toString("base64") const response = await fetch(`${HB_BASE_URL}${path}`, { ...options, headers: { "Authorization": `Basic ${credentials}`, "Content-Type": "application/json", ...options.headers, }, }) if (!response.ok) { const errorText = await response.text() throw new Error(`Hepsiburada API error ${response.status}: ${errorText}`) } return response.json() as Promise<T> }

Hepsiburada Webhook

Hepsiburada webhook desteği Trendyol'a göre daha iyi belgelenmiş. Sipariş bildirimleri için base URL'inizi Hepsiburada'ya bildirirsiniz; platform {baseUrl}/orders endpoint'inize POST atar.

Idempotent işleme zorunlu — tekrar gönderim olabilir. Her webhook payload'ını bir ID ile takip edin:

// app/api/webhooks/hepsiburada/orders/route.ts import { NextResponse } from "next/server" import { db } from "@/lib/db" import { orders } from "@/lib/db/schema" import { eq } from "drizzle-orm" export async function POST(request: Request) { const payload = await request.json() const externalOrderId = payload.id as string // Idempotent upsert — aynı sipariş tekrar işlenmez const existing = await db .select() .from(orders) .where(eq(orders.externalId, externalOrderId)) if (existing.length === 0) { await db.insert(orders).values({ externalId: externalOrderId, platform: "hepsiburada", status: payload.status, rawPayload: JSON.stringify(payload), receivedAt: new Date(), }) } return NextResponse.json({ received: true }) }

Trendyol vs Hepsiburada Karşılaştırması

KriterTrendyolHepsiburada
AuthBasic Auth + User-Agent zorunluBasic Auth
Ürün yüklemeDoğrudan JSON APIDosya tabanlı import
Async onaybatchRequestId ilePlatform bağımlı
WebhookVar (polling fallback önerilir)Var (first-class)
SandboxIP whitelist gerekliBaşvuru sonrası
Dokümantasyonİyi (developers.trendyol.com)Orta-iyi
Pazar payı~%36 (lider)İkinci sıra

Vercel Cron ile Stok Senkronizasyonu

Stok verilerinin her iki platformda güncel kalması için periyodik senkronizasyon gerekiyor.

Vercel Cron Kısıtları

Bu kritik bilgiyi düzgünce anlamamak ciddi sorunlara yol açar:

  • Hobby (Ücretsiz plan): Maksimum 2 cron job, her biri günde en fazla 1 kez çalışabilir. 0 * * * * (saatlik) bir cron deploy'da hata verir.
  • Pro plan: Dakika düzeyinde granülarite (Amazon EventBridge Scheduler üzerinden). Gerçek marketplace polling için Pro gerekli.
  • Hobby alternatif: QStash cron ile Vercel kısıtını bypass edebilirsiniz. QStash herhangi bir takvimde sync'i tetikleyebilir.

next.config.ts ile Cron Tanımlama (Pro)

// next.config.ts import type { NextConfig } from "next" const nextConfig: NextConfig = { experimental: { // Pro plan için cron route'ları }, } export default nextConfig

vercel.json:

{ "crons": [ { "path": "/api/cron/sync-inventory", "schedule": "*/15 * * * *" } ] }

Stok Senkronizasyon Route Handler

// app/api/cron/sync-inventory/route.ts import { NextResponse } from "next/server" import { db } from "@/lib/db" import { products } from "@/lib/db/schema" import { trendyolFetch } from "@/lib/marketplace/trendyol-client" export async function GET(request: Request) { // Vercel Cron güvenlik kontrolü const authHeader = request.headers.get("authorization") if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) } const supplierId = process.env.TRENDYOL_SUPPLIER_ID! // DB'deki güncel stok bilgilerini al const inventory = await db.select().from(products) // Trendyol'a batch stok güncelleme gönder // Rate limit göz önünde bulundurularak batch'lere böl const BATCH_SIZE = 50 const batches = [] for (let i = 0; i < inventory.length; i += BATCH_SIZE) { batches.push(inventory.slice(i, i + BATCH_SIZE)) } const results = [] for (const batch of batches) { const items = batch.map((p) => ({ barcode: p.barcode, quantity: p.stock, salePrice: p.salePrice, listPrice: p.listPrice, })) const result = await trendyolFetch<{ batchRequestId: string }>( `/integration/product/sellers/${supplierId}/products/price-and-inventory`, { method: "PUT", body: JSON.stringify({ items }), }, ) results.push(result.batchRequestId) // Rate limit için kısa bekleme — güncel değer için dokümantasyonu kontrol edin await new Promise((resolve) => setTimeout(resolve, 500)) } return NextResponse.json({ synced: inventory.length, batches: results }) }

npm Paket Seçimi

Trendyol için:

  • @rexven-tech/trendyol-api — Daha aktif bakımlı, ürün/sipariş/finans/webhook kayıt desteği. Önerilen.
  • trendyol-api (myazarc) — TypeScript destekli ama 3 yıldır güncellenmemiş, güncel API sürümleriyle uyumsuz olabilir.

Her iki seçenek için de üretim öncesinde güncel API uyumluluğunu test edin. Özellikle hızlı büyüyen bu platformlarda API değişiklikleri sık olabiliyor — resmi dokümantasyonu baz almak en güvenli yaklaşım.

Ortam Değişkenleri

.env.local:

# Trendyol
TRENDYOL_SUPPLIER_ID=12345
TRENDYOL_API_KEY=your-api-key
TRENDYOL_API_SECRET=your-api-secret
TRENDYOL_STAGE=true

# Hepsiburada
HEPSIBURADA_USERNAME=your-username
HEPSIBURADA_PASSWORD=your-password
HEPSIBURADA_MERCHANT_ID=your-merchant-id
HEPSIBURADA_STAGE=true

# Cron güvenliği
CRON_SECRET=random-secret-string

# Inngest (opsiyonel)
INNGEST_EVENT_KEY=your-inngest-key
INNGEST_SIGNING_KEY=your-signing-key

Sık Hatalar ve Çözümleri

Trendyol 401 Unauthorized:

  • User-Agent header'ını eklediğinizden emin olun: "<supplierId> - SelfIntegration"
  • Stage ve production credential'larını karıştırmayın — tamamen ayrıdırlar

Trendyol Stage'de 403 Forbidden:

  • IP whitelist gerekli — sunucunuzun static IP'sini Trendyol'a bildirin
  • Yerel geliştirme için ngrok veya benzeri bir tünel servisi kullanın

batchRequestId sonucu hep IN_PROGRESS:

  • Moderasyon 5-30 dakika sürebilir; polling interval'i buna göre ayarlayın
  • Ürün verilerinde eksik zorunlu alan varsa (kategori, marka, vs.) süreç takılabilir — batch sonuç endpoint'inden hata detaylarını inceleyin

Hepsiburada ürün yükleme başarısız:

  • Hepsiburada ürün yükleme dosya tabanlı çalışır — doğrudan JSON body yeterli olmayabilir
  • SIT ortamı için Merchant ID'nizi Hepsiburada entegrasyon ekibinden alın

Vercel cron çalışmıyor (Hobby plan):

  • Hobby'de saatlik cron desteklenmiyor — günde 1 kez ile sınırlı
  • Çözüm: Vercel Pro'ya geçin ya da QStash cron ile kısıtı bypass edin

Rate limit hatası:

  • Trendyol'un rate limit bilgisi değişebilir — güncel değeri resmi dokümantasyondan kontrol edin
  • Büyük kataloglar için batch'lere bölün ve istekler arasına gecikme ekleyin

Ne Zaman Hazır Entegrasyon Kullanmalı?

Custom geliştirme yapmadan önce hazır marketplace entegrasyon araçlarını değerlendirin:

Hazır çözümler mantıklı olduğunda:

  • 10'dan fazla marketplace (Trendyol, Hepsiburada, Çiçeksepeti, N11, Sahibinden) aynı anda yönetilecekse
  • Ürün katalog sayısı onbinleri geçiyorsa
  • Ekipte marketplace API geliştirme deneyimi yoksa

Custom geliştirme mantıklı olduğunda:

  • Yalnızca 1-2 marketplace entegrasyonu gerekiyorsa
  • Özel iş mantığı var ve hazır çözümler uymuyor
  • Mevcut sistemle (özel ERP, muhasebe yazılımı) derin entegrasyon gerekiyorsa

Dopigo, Sentos, JetStok gibi Türk entegrasyon SaaS'ları bu alanda uzmanlaşmış. Özellikle çok kanallı satış yapan KOBİ'ler için değer sunabilirler.

Sonraki Adımlar

  • Hata yönetimi: Her iki platform için exponential backoff ile retry mekanizması ekleyin
  • Monitoring: Inngest veya QStash dashboard'ları ile job durumlarını izleyin
  • Stok çakışması: Aynı ürün birden fazla platformda satılıyorsa race condition yönetimini planlayın
  • N11 entegrasyonu: Düşük öncelikli ama aktif — DMSF sonrası API değişikliklerini developer portal üzerinden takip edin

SSS

Trendyol API erişimi almak ne kadar sürer? Başvuru ve onay süresi değişkendir — Trendyol Seller Panel üzerinden başvuruda bulunun ve güncel bilgi için Trendyol entegrasyon ekibiyle iletişime geçin.

Webhook olmadan sadece polling yeterli olur mu? Teknik olarak evet, ancak yüksek sipariş hacminde polling gecikmeli bildirim anlamına gelir. En iyi yaklaşım: webhook + polling fallback kombinasyonu. Trendyol resmi dokümantasyonu da bu kombinasyonu öneriyor.

Inngest ücretsiz mi? Inngest'in ücretsiz planı var — güncel limit ve ücretlendirme için inngest.com adresini kontrol edin. QStash de Upstash üzerinde ücretsiz tier sunuyor.

Vercel Hobby planıyla marketplace sync mümkün mü? Sınırlı. Günde 1 cron job ile yalnızca günlük senkronizasyon yapabilirsiniz. Gerçek zamanlıya yakın sync için QStash cron veya Vercel Pro gerekli.

Hepsiburada'da ürün güncellemesi neden Trendyol'dan yavaş? Hepsiburada'da ürün yükleme dosya tabanlı bir import sistemiyle çalışıyor. Bu durum Trendyol'un doğrudan JSON API'sine kıyasla daha fazla entegrasyon adımı gerektiriyor.

N11 entegrasyonu hâlâ değerli mi? N11 düşük hacimle de olsa aktif. Eğer müşteriniz N11'de de satış yapıyorsa entegrasyon anlam taşıyabilir, ancak DMSF sonrası API durumunu developer.n11.com üzerinden doğrulayın.

Stage ortamında test için statik IP zorunlu mu? Trendyol Stage için evet — IP whitelist gerekli. Yerel geliştirmede ngrok veya benzeri bir tünel aracı kullanın ve o IP'yi Trendyol'a bildirin.

Paylaş: