Agent skill

Trendyol Webhooks Skill

Receive and authenticate Trendyol seller order package webhooks. Use when setting up a Trendyol webhook endpoint, verifying the x-api-key header, debugging 401s, or handling package statuses like CREATED, SHIPPED, DELIVERED, CANCELLED and RETURNED.

Install this skill

npx skills add hookdeck/webhook-skills --skill trendyol-webhooks


Trendyol (the Turkish marketplace) sends a webhook to your seller endpoint when an order package changes status. Webhooks are not signed. When you create the webhook with authenticationType API_KEY, Trendyol sends the webhook's apiKey as plain text in the x-api-key header on every request, and your endpoint authenticates the request by comparing the whole header value with the key you stored.

Choose API key authentication (authenticationType API_KEY) when you create the Trendyol webhook.

Trendyol also offers BASIC_AUTHENTICATION, which Hookdeck's Trendyol source does not cover; this skill covers only API_KEY.

When to Use This Skill

  • How do I receive Trendyol order package webhooks?
  • How do I verify the x-api-key header on a Trendyol webhook?
  • Does Trendyol sign webhook payloads? (No: use the shared API key)
  • How do I handle CREATED, SHIPPED, DELIVERED, CANCELLED or RETURNED packages?
  • Why does my Trendyol webhook endpoint return 401, or why does Trendyol keep re-sending requests?

Verification (core)

const crypto = require('crypto');

// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
  const ha = crypto.createHash('sha256').update(String(a)).digest();
  const hb = crypto.createHash('sha256').update(String(b)).digest();
  return crypto.timingSafeEqual(ha, hb);
}

function verifyTrendyolRequest(headers, secret = process.env.TRENDYOL_WEBHOOK_SECRET) {
  if (!secret) return false;                  // never accept when unconfigured
  const received = headers['x-api-key'];      // the apiKey, sent as plain text
  return typeof received === 'string' && received !== '' && safeEqual(received, secret);
}
  • Header: x-api-key: <apiKey>. Compare the whole value with TRENDYOL_WEBHOOK_SECRET; there is no prefix, HMAC or timestamp. Look the header up case-insensitively (Node lowercases it already).
  • Return 401 for a missing or wrong key, 400 for a body that isn't a JSON object with a content array, 200 once handled.
  • Read the body raw (express.raw({ type: '*/*' })) and authenticate before parsing it.
  • In Python use hmac.compare_digest on bytes (a.encode(), b.encode()); passing str raises TypeError on non-ASCII input.
  • A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Serve the endpoint over HTTPS and rotate the apiKey (update the webhook) if it leaks.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Event Types

Trendyol sends the full order package whatever the status. The body is a page of packages, { "content": [ ... ] }; loop over content[] and dispatch on each package's status. The documentation lists the statuses in upper case but the example payload writes them in Title case ("status": "Delivered"), so compare case-insensitively.

StatusPackage is
CREATEDCreated from a new order
PICKINGBeing picked by the seller
INVOICEDInvoiced
SHIPPEDHanded to the carrier
DELIVEREDDelivered to the customer
UNDELIVEREDNot delivered
CANCELLEDCancelled
RETURNEDReturned
UNSUPPLIEDMarked as not supplied by the seller
AWAITINGAwaiting
UNPACKEDUnpacked
AT_COLLECTION_POINTWaiting at a collection point
VERIFIEDVerified

Requests are POST with a JSON body. If your endpoint fails, Trendyol re-sends every 5 minutes until it succeeds and eventually deactivates the webhook, so handlers must be idempotent.

Environment Variables

TRENDYOL_WEBHOOK_SECRET=your-webhook-api-key   # the apiKey set when creating the webhook

Local Development

Trendyol can't reach localhost. Tunnel with the Hookdeck CLI (no account required):

npx hookdeck-cli listen 3000 trendyol --path /webhooks/trendyol

Use the printed URL as the webhook URL (Trendyol rejects URLs containing "Trendyol", "Dolap" or "Localhost").

Resources


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 11, 2026

View on GitHub →