Webhook events
Both marketplaces deliver async events via webhooks, but the delivery models differ — Trendyol is body-discriminated, Hepsiburada is endpoint-per-event. The SDKs ship a parser for each.
Trendyol — single endpoint, body-discriminated
Section titled “Trendyol — single endpoint, body-discriminated”You register one URL with Trendyol. Every event lands at that URL; the JSON body contains the discriminator.
import express from 'express';import { parseWebhookEvent } from '@lonca/trendyol';
const app = express();app.use(express.json());
app.post('/ty/webhook', (req, res) => { // Returns { packages, pageInfo, raw } const { packages } = parseWebhookEvent(req.body);
for (const pkg of packages) { console.log(pkg.shipmentPackageId, pkg.status, pkg.createdBy); } res.status(200).end();});The parser:
- Validates the JSON shape (throws
ValidationErroron bad input) - Normalizes each shipment package via the same path used by
client.orders.list() - Surfaces a
WebhookEventStatusunion (CREATED | PICKING | INVOICED | SHIPPED | DELIVERED | UNDELIVERED | RETURNED | CANCELLED | UNPACKED | UNSUPPLIED | AT_COLLECTION_POINT | VERIFIED) plusPackageCreatedBy(order-creation | cancel | split | transfer)
See Trendyol guide for context and API Reference for the exact WebhookEvent type.
Hepsiburada — endpoint-per-event
Section titled “Hepsiburada — endpoint-per-event”You register one base URL with Hepsiburada. Hepsiburada PUTs to <baseUrl>/<eventName> — one route per event, 12 events total.
import express from 'express';import { parseHepsiburadaWebhookEvent, ORDER_WEBHOOK_EVENTS, CLAIM_WEBHOOK_EVENTS, type HepsiburadaWebhookEvent,} from '@lonca/hepsiburada';
const app = express();app.use(express.json());
const allEvents: readonly HepsiburadaWebhookEvent[] = [ ...ORDER_WEBHOOK_EVENTS, ...CLAIM_WEBHOOK_EVENTS,];
for (const event of allEvents) { app.put(`/hb/${event}`, (req, res) => { const { body } = parseHepsiburadaWebhookEvent(event, req.body); handle(event, body); res.status(204).end(); });}
function handle(event: HepsiburadaWebhookEvent, body: Record<string, unknown>) { // Exhaustive switch — TypeScript will warn if a new event is added switch (event) { case 'createOrder': /* new paid order */ break; case 'createPackages': /* Hepsiburada packaged your items */ break; case 'orderCancel': /* buyer cancelled */ break; case 'unpack': /* package unpacked */ break; case 'intransit': /* handed to cargo */ break; case 'deliver': /* delivered */ break; case 'undeliver': /* delivery failed */ break; case 'changeShippingAddressOrder': /* address updated */ break; case 'awaitingAction': /* claim needs accept/reject */ break; case 'awaitingPreApproval': /* pre-approval flow */ break; case 'disputedClaimResult': /* disputed-claim decision */ break; case 'packageFromClaimResult': /* return package from approval */ break; }}The parser:
- Validates the event name is one of the documented 12 (throws
ValidationErrorotherwise) - Accepts a JSON string or already-parsed object
- Returns
{ event, body, raw }—bodyisRecord<string, unknown>because Hepsiburada documents field sets in HTML tables; the SDK keepsbodyloose and exposes the raw payload verbatim
Shared contract notes
Section titled “Shared contract notes”Both marketplaces expect:
- 2xx response within a few seconds (5s for Hepsiburada, 30s for Trendyol)
- Idempotent receiver — both retry on non-2xx responses
If you’re behind a reverse proxy (nginx, Cloudflare, IIS), make sure PUT is allowed (IIS disables it by default).
See also
Section titled “See also”Unofficial. Lonca is an independent, community-maintained project — not affiliated with, endorsed by, or supported by Trendyol, Hepsiburada, or any other marketplace. All marketplace names and trademarks belong to their respective owners.