@lonca/trendyol 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -246,6 +246,350 @@ declare class CategoriesResource {
246
246
  getByBarcodes(barcodes: string[]): Promise<BarcodeCategoryLookup>;
247
247
  }
248
248
 
249
+ /**
250
+ * Trendyol claim ("iade" / return-claim) types.
251
+ *
252
+ * A claim is a customer-initiated return on a delivered order. The
253
+ * seller can also open a `createClaimIssue` (a rejection) against a
254
+ * customer-filed claim, and either party can have line items approved
255
+ * via `approveClaimLineItems`.
256
+ */
257
+
258
+ /** One item inside `claims.create()`. */
259
+ interface CreateClaimItemInput {
260
+ /** Barcode of the ordered SKU. */
261
+ barcode: string;
262
+ /** Number of units being returned. */
263
+ quantity: number;
264
+ /**
265
+ * Numeric reason code customers select on trendyol.com.
266
+ * Trendyol's docs note `401` ("Vazgectim" — changed my mind) as a
267
+ * safe default when you don't have a more specific code.
268
+ */
269
+ reasonId: number;
270
+ /** Free-text note from the customer. */
271
+ customerNote?: string;
272
+ }
273
+ /** Payload for `claims.create()`. */
274
+ interface CreateClaimInput {
275
+ /** The order to file the claim against. */
276
+ orderNumber: string;
277
+ claimItems: CreateClaimItemInput[];
278
+ /** Trendyol customer ID (the one who placed the order). */
279
+ customerId?: number;
280
+ /** Suppress this claim from listing pages. */
281
+ excludeListing?: boolean;
282
+ /** Force a new shipment package to be created for the return. */
283
+ forcePackageCreation?: boolean;
284
+ }
285
+ /**
286
+ * Payload for `claims.createIssue()` — file a seller-side rejection
287
+ * ("ret talebi") against a customer claim. Wire format is
288
+ * `multipart/form-data` because optional `files` are PDF / JPEG
289
+ * supporting documents.
290
+ */
291
+ interface CreateClaimIssueInput {
292
+ /** Numeric reason ID from `claims.getIssueReasons()`. */
293
+ claimIssueReasonId: number;
294
+ /** Per-line claim item IDs being rejected. SDK joins with commas. */
295
+ claimItemIdList: string[];
296
+ /** Free-text explanation (≤500 chars). */
297
+ description: string;
298
+ /** Optional supporting documents (Blob / File). */
299
+ files?: Blob[];
300
+ }
301
+ /** Payload for `claims.approveLineItems()`. */
302
+ interface ApproveClaimLineItemsInput {
303
+ /** Claim line-item IDs to approve. */
304
+ claimLineItemIdList: string[];
305
+ /** Optional extra params Trendyol forwards verbatim. */
306
+ params?: Record<string, string>;
307
+ }
308
+ /**
309
+ * Claim item lifecycle state. Open enum — Trendyol can add new states
310
+ * without breaking callers.
311
+ */
312
+ type ClaimItemStatus = 'Created' | 'WaitingInAction' | 'WaitingFraudCheck' | 'Accepted' | 'Unresolved' | 'Rejected' | (string & {});
313
+ /** Filter / pagination for `claims.list()`. */
314
+ interface ListClaimsParams extends CursorPaginationParams {
315
+ startDate?: Date;
316
+ endDate?: Date;
317
+ /** Filter claims by item-level status. */
318
+ claimItemStatus?: ClaimItemStatus;
319
+ }
320
+ /**
321
+ * A return claim. Trendyol returns ~20 fields; the SDK surfaces the
322
+ * stable subset and keeps everything else on `raw`.
323
+ */
324
+ interface Claim {
325
+ /** Claim ID (Trendyol returns it under both `id` and `claimId` — same value). */
326
+ id: string;
327
+ orderNumber: string;
328
+ /** ISO 8601 UTC (from ms-epoch `orderDate`). */
329
+ orderDate?: string;
330
+ /** ISO 8601 UTC (from ms-epoch `claimDate`). */
331
+ claimDate?: string;
332
+ customerFirstName?: string;
333
+ customerLastName?: string;
334
+ /** Untouched raw claim — pull undocumented fields from here. */
335
+ raw: Record<string, unknown>;
336
+ }
337
+ /** Rejection-reason catalog row from `claims.getIssueReasons()`. */
338
+ interface ClaimIssueReason {
339
+ id: number;
340
+ name: string;
341
+ }
342
+ /**
343
+ * Audit entry for a single claim item, returned by `claims.getItemAudits()`.
344
+ * Trendyol's response shape varies; only `raw` is guaranteed.
345
+ */
346
+ interface ClaimItemAudit {
347
+ /** Untouched raw audit row. */
348
+ raw: Record<string, unknown>;
349
+ }
350
+
351
+ /**
352
+ * Trendyol claims (return / iade) endpoints.
353
+ *
354
+ * Rate limit (per Trendyol service limits): shares the order service bucket;
355
+ * the SDK provisions its own 1000 req/min limiter that the caller can override.
356
+ */
357
+ declare class ClaimsResource {
358
+ private readonly transport;
359
+ private readonly sellerId;
360
+ private readonly limiter;
361
+ constructor(transport: TrendyolTransport, sellerId: number, limiter?: TokenBucketRateLimiter);
362
+ /**
363
+ * Create a return claim against an order. Use this to file a return on
364
+ * behalf of a customer (e.g. when they called your CS line). For
365
+ * customer-initiated returns coming from trendyol.com, you receive them
366
+ * via `claims.list()` — no need to call `create`.
367
+ *
368
+ * Returns whatever Trendyol returns (typically the new claim's identifier).
369
+ *
370
+ * @throws {ValidationError} when `claimItems` is empty.
371
+ */
372
+ create(input: CreateClaimInput): Promise<unknown>;
373
+ /**
374
+ * File a seller-side rejection ("ret talebi") against a customer claim.
375
+ *
376
+ * **Wire format: `multipart/form-data`** — the SDK builds the FormData
377
+ * internally from the typed input. `claimItemIdList` is joined with
378
+ * commas (Trendyol expects a single comma-separated string field).
379
+ * Attach supporting docs (PDF / JPEG) via `files: [Blob, ...]`.
380
+ */
381
+ createIssue(claimId: string, input: CreateClaimIssueInput): Promise<unknown>;
382
+ /**
383
+ * Approve specific claim line items. After approval, Trendyol moves
384
+ * those line items into the post-approval refund / return-shipping flow.
385
+ *
386
+ * @throws {ValidationError} when `claimLineItemIdList` is empty.
387
+ */
388
+ approveLineItems(claimId: string, input: ApproveClaimLineItemsInput): Promise<unknown>;
389
+ /**
390
+ * List claims (page-based; SDK exposes opaque cursor convention).
391
+ *
392
+ * @example
393
+ * ```ts
394
+ * import { paginate } from '@lonca/core';
395
+ * for await (const c of paginate((p) =>
396
+ * client.claims.list({ ...p, claimItemStatus: 'WaitingInAction' }),
397
+ * )) {
398
+ * console.log(c.id, c.orderNumber, c.claimDate);
399
+ * }
400
+ * ```
401
+ */
402
+ list(params?: ListClaimsParams): Promise<CursorPage<Claim>>;
403
+ /**
404
+ * Fetch the catalog of rejection-reason IDs the seller can use on
405
+ * `claims.createIssue()`. Cache the result — it changes rarely.
406
+ *
407
+ * Note: this endpoint is **not seller-scoped** (no `sellerId` in path).
408
+ */
409
+ getIssueReasons(): Promise<ClaimIssueReason[]>;
410
+ /**
411
+ * Fetch the audit log for a single claim item (state transitions,
412
+ * actor, timestamp). Trendyol's response shape varies — the SDK
413
+ * surfaces each row as `{ raw }` and leaves field extraction to the
414
+ * caller until we observe a stable shape on the wire.
415
+ */
416
+ getItemAudits(claimItemId: string): Promise<ClaimItemAudit[]>;
417
+ }
418
+
419
+ /**
420
+ * Misc types for Trendyol's smaller surfaces — invoices, finance,
421
+ * common labels, test orders, and location lookups. Most shapes are
422
+ * loosely typed (`Record<string, unknown>`) because the Trendyol response
423
+ * shapes here are wide and seldom-evolved; callers drill into `raw` for
424
+ * fields beyond the stable surface.
425
+ */
426
+
427
+ interface UploadInvoiceFileInput {
428
+ /** Trendyol shipment package ID (required). */
429
+ shipmentPackageId: number;
430
+ /** Invoice file (PDF / JPEG / PNG, max 10 MB). */
431
+ file: Blob;
432
+ /** ms-epoch — mandatory for micro-export orders, optional otherwise. */
433
+ invoiceDateTime?: number;
434
+ /**
435
+ * Invoice number — mandatory for micro-export orders. Format:
436
+ * `[A-Za-z0-9]{3}(20[2-9][0-9])\d{9}`.
437
+ */
438
+ invoiceNumber?: string;
439
+ }
440
+ interface SendInvoiceLinkInput {
441
+ invoiceLink: string;
442
+ shipmentPackageId: number;
443
+ invoiceDateTime?: number;
444
+ invoiceNumber?: string;
445
+ }
446
+ interface DeleteInvoiceLinkInput {
447
+ serviceSourceId?: number;
448
+ channelId?: number;
449
+ customerId?: number;
450
+ /** Forward-compatible: pass any extra fields Trendyol may add. */
451
+ [key: string]: unknown;
452
+ }
453
+ /**
454
+ * One row from Trendyol's current-account statement — returned by both
455
+ * `finance.getSettlements()` and `finance.getOtherFinancials()` (both
456
+ * endpoints share the `FinancialTransaction` wire schema).
457
+ *
458
+ * Field set verified against the spec on 2026-05-25. The SDK exposes the
459
+ * stable subset; anything Trendyol adds later remains accessible via `raw`.
460
+ */
461
+ interface FinancialTransaction {
462
+ /** Transaction ID (string per Trendyol). */
463
+ id: string;
464
+ /** ISO 8601 UTC (from ms-epoch `transactionDate`). */
465
+ transactionDate?: string;
466
+ /** Product barcode when the transaction is tied to a SKU. */
467
+ barcode?: string | null;
468
+ /** Transaction category (e.g. `'Satış'`, `'Ödeme'`). */
469
+ transactionType?: string;
470
+ /** Receipt ID ("dekont no") when applicable. */
471
+ receiptId?: number | null;
472
+ description?: string | null;
473
+ /** Debit amount on the seller's account. */
474
+ debt?: number;
475
+ /** Credit amount on the seller's account. */
476
+ credit?: number;
477
+ paymentPeriod?: number | null;
478
+ commissionRate?: number | null;
479
+ commissionAmount?: number | null;
480
+ commissionInvoiceSerialNumber?: string | null;
481
+ /** Net seller revenue after Trendyol's cut. */
482
+ sellerRevenue?: number | null;
483
+ orderNumber?: string | null;
484
+ paymentOrderId?: number | null;
485
+ /** ISO 8601 UTC (from ms-epoch `paymentDate`). */
486
+ paymentDate?: string;
487
+ sellerId?: number;
488
+ storeId?: number | null;
489
+ storeName?: string | null;
490
+ storeAddress?: string | null;
491
+ country?: string | null;
492
+ /** Untouched raw row — pull any undocumented fields from here. */
493
+ raw: Record<string, unknown>;
494
+ }
495
+ /**
496
+ * Aliases preserved for source-compatibility with `0.5.0`. Both legacy
497
+ * names now resolve to the unified `FinancialTransaction`.
498
+ *
499
+ * @deprecated since `0.5.1` — use `FinancialTransaction`.
500
+ */
501
+ type SettlementRow = FinancialTransaction;
502
+ /** @deprecated since `0.5.1` — use `FinancialTransaction`. */
503
+ type OtherFinancialRow = FinancialTransaction;
504
+ /**
505
+ * Shared filter shape for both finance endpoints.
506
+ * `transactionType` lets you scope to one settlement category.
507
+ */
508
+ interface ListFinanceParams extends CursorPaginationParams {
509
+ startDate?: Date;
510
+ endDate?: Date;
511
+ transactionType?: string;
512
+ }
513
+ interface CreateCommonLabelInput {
514
+ /** Currently the only documented format Trendyol accepts. */
515
+ format: 'ZPL' | (string & {});
516
+ boxQuantity?: number;
517
+ /** Volumetric height (height × width × depth / 3000 → desi). */
518
+ volumetricHeight?: number;
519
+ }
520
+ /** One label entry inside a `CommonLabel` response. */
521
+ interface CommonLabelEntry {
522
+ /** Encoded label payload (e.g. ZPL string `^XA...^XZ`). */
523
+ label: string;
524
+ format: 'ZPL' | (string & {});
525
+ }
526
+ /**
527
+ * Response from `labels.getCommon()` — Trendyol's wire shape is
528
+ * `{ data: [{ label, format }] }`. SDK surfaces the array directly via
529
+ * `labels` for ergonomic access; `raw` is the untouched response.
530
+ */
531
+ interface CommonLabel {
532
+ labels: CommonLabelEntry[];
533
+ raw: Record<string, unknown>;
534
+ }
535
+ /**
536
+ * Payload for `testOrders.create()`. Top-level requireds are
537
+ * `customer`, `invoiceAddress`, `lines`, `seller`, `shippingAddress`;
538
+ * each sub-object has its own field rules (see Trendyol's
539
+ * `createTestOrder` reference). Kept loose because the inner schema is
540
+ * deep and used only in STAGE.
541
+ */
542
+ interface CreateTestOrderInput {
543
+ customer: Record<string, unknown>;
544
+ invoiceAddress: Record<string, unknown>;
545
+ shippingAddress: Record<string, unknown>;
546
+ seller: Record<string, unknown>;
547
+ lines: Array<Record<string, unknown>>;
548
+ [key: string]: unknown;
549
+ }
550
+ type TestOrderStatus = 'Created' | 'Picking' | 'Invoiced' | 'Shipped' | 'Delivered' | 'Cancelled' | 'Returned' | 'UnDelivered' | (string & {});
551
+ interface Country {
552
+ /** ISO country code (e.g. `'TR'`, `'AZ'`). */
553
+ code: string;
554
+ name?: string;
555
+ raw: Record<string, unknown>;
556
+ }
557
+ interface City {
558
+ code: string;
559
+ name?: string;
560
+ countryCode?: string;
561
+ raw: Record<string, unknown>;
562
+ }
563
+ interface District {
564
+ code: string;
565
+ name?: string;
566
+ cityCode?: string;
567
+ raw: Record<string, unknown>;
568
+ }
569
+ interface Neighborhood {
570
+ code: string;
571
+ name?: string;
572
+ districtCode?: string;
573
+ raw: Record<string, unknown>;
574
+ }
575
+
576
+ /**
577
+ * Trendyol finance endpoints — current-account-statement settlements and
578
+ * "other financials" (cargo invoices, labor cost adjustments, etc.).
579
+ *
580
+ * Both endpoints return the same `FinancialTransaction` shape on the wire,
581
+ * so the SDK exposes one typed surface for them.
582
+ */
583
+ declare class FinanceResource {
584
+ private readonly transport;
585
+ private readonly sellerId;
586
+ private readonly limiter;
587
+ constructor(transport: TrendyolTransport, sellerId: number, limiter?: TokenBucketRateLimiter);
588
+ getSettlements(params?: ListFinanceParams): Promise<CursorPage<FinancialTransaction>>;
589
+ getOtherFinancials(params?: ListFinanceParams): Promise<CursorPage<FinancialTransaction>>;
590
+ private queryPage;
591
+ }
592
+
249
593
  /**
250
594
  * A single price / stock update entry.
251
595
  *
@@ -300,6 +644,82 @@ declare class InventoryResource {
300
644
  update(items: PriceInventoryUpdate[]): Promise<UpdatePriceInventoryResponse>;
301
645
  }
302
646
 
647
+ /**
648
+ * Trendyol invoice endpoints — upload PDF/JPEG/PNG invoice files or
649
+ * register/delete invoice links. Pair these with `orders.updatePackageStatus(_, { status: 'Invoiced' })`
650
+ * after invoice issuance.
651
+ */
652
+ declare class InvoicesResource {
653
+ private readonly transport;
654
+ private readonly sellerId;
655
+ private readonly limiter;
656
+ constructor(transport: TrendyolTransport, sellerId: number, limiter?: TokenBucketRateLimiter);
657
+ /**
658
+ * Upload an invoice file for a shipment package. **Multipart**: the
659
+ * SDK builds the FormData internally from the typed input.
660
+ *
661
+ * Max 10 MB. Accepted formats: PDF, JPEG, PNG.
662
+ */
663
+ uploadFile(input: UploadInvoiceFileInput): Promise<unknown>;
664
+ /** Register an invoice URL with Trendyol (alternative to uploading the file). */
665
+ sendLink(input: SendInvoiceLinkInput): Promise<unknown>;
666
+ /** Remove a previously-registered invoice link. */
667
+ deleteLink(input: DeleteInvoiceLinkInput): Promise<unknown>;
668
+ }
669
+
670
+ /**
671
+ * Common-label (ortak etiket) endpoints — request and retrieve a
672
+ * combined ZPL shipping label for a cargo tracking number.
673
+ */
674
+ declare class LabelsResource {
675
+ private readonly transport;
676
+ private readonly sellerId;
677
+ private readonly limiter;
678
+ constructor(transport: TrendyolTransport, sellerId: number, limiter?: TokenBucketRateLimiter);
679
+ /**
680
+ * Request a common ZPL label for a cargo tracking number. After this
681
+ * returns, call `getCommon()` with the same `cargoTrackingNumber` to
682
+ * retrieve the generated label.
683
+ *
684
+ * @throws {ValidationError} when `format` is missing.
685
+ */
686
+ createCommon(cargoTrackingNumber: string | number, input: CreateCommonLabelInput): Promise<unknown>;
687
+ /**
688
+ * Retrieve the previously-created common label. Trendyol returns
689
+ * `{ data: [{ label, format }] }`; the SDK surfaces the array as
690
+ * `labels[]` for ergonomic access.
691
+ *
692
+ * Typically `labels.length === 1` per tracking number, but kept as an
693
+ * array to match the wire shape.
694
+ */
695
+ getCommon(cargoTrackingNumber: string | number): Promise<CommonLabel>;
696
+ }
697
+
698
+ /**
699
+ * Trendyol location lookups for building shipment / invoice addresses
700
+ * with the correct city / district / neighborhood codes.
701
+ *
702
+ * Trendyol exposes these under a different prefix (`/integration/member/`)
703
+ * — not under `/integration/order/` or `/integration/product/`.
704
+ */
705
+ declare class LocationsResource {
706
+ private readonly transport;
707
+ private readonly limiter;
708
+ constructor(transport: TrendyolTransport, limiter?: TokenBucketRateLimiter);
709
+ /** List all supported countries (Türkiye + AZ + GULF + CEE). */
710
+ getCountries(): Promise<Country[]>;
711
+ getTurkeyCities(): Promise<City[]>;
712
+ getTurkeyDistricts(cityCode: string | number): Promise<District[]>;
713
+ getTurkeyNeighborhoods(cityCode: string | number, districtCode: string | number): Promise<Neighborhood[]>;
714
+ getAzerbaijanCities(): Promise<City[]>;
715
+ getAzerbaijanDistricts(cityCode: string | number): Promise<District[]>;
716
+ getCitiesByCountry(countryCode: string): Promise<City[]>;
717
+ getDistrictsByCity(countryCode: string, cityId: string | number): Promise<District[]>;
718
+ private cities;
719
+ private districts;
720
+ private neighborhoods;
721
+ }
722
+
303
723
  /**
304
724
  * Trendyol shipment-package status.
305
725
  *
@@ -591,6 +1011,63 @@ interface ShipmentPackage {
591
1011
  raw: Record<string, unknown>;
592
1012
  }
593
1013
 
1014
+ /**
1015
+ * Returns + compensation types for Trendyol orders.
1016
+ *
1017
+ * Trendyol distinguishes two separate concepts:
1018
+ * - **Manual return** — seller-side notification that a package was
1019
+ * received back (no body, just a state flip on the package).
1020
+ * - **Compensation ticket** — Trendyol Express-specific dispute filed
1021
+ * when a shipment is lost or damaged. Multi-state lifecycle with up to
1022
+ * ~18 documented states.
1023
+ */
1024
+
1025
+ /**
1026
+ * Lifecycle state of a Trendyol Express compensation ticket. Trendyol
1027
+ * documents 18 distinct states (`Empty`, `MarkInCompensation`,
1028
+ * `CompensationApproved`, etc.) — kept as an open enum so unknown future
1029
+ * values still type-check.
1030
+ *
1031
+ * Verified against the official spec on 2026-05-25.
1032
+ */
1033
+ type CompensationTicketState = 'Empty' | 'MarkInCompensation' | 'OpenedForRefund' | 'StartCompensationFinanceProgress' | 'StartCompensationInApprovalProgress' | 'CompensationApproved' | 'CompensationRejected' | 'FoundAfterCompensationComplete' | 'NotCompensationCase' | 'FoundInCompensation' | 'FoundInvestigationProgress' | 'MarkCompensationCancel' | 'CreateCompensationTicket' | 'FinalizeCompensation' | 'CloseCompensationTicket' | 'FoundInvestigationProgressDeliveredToCustomer' | 'FoundInCompensationDeliveredToCustomer' | 'FoundAfterCompensationCompleteDeliveredToCustomer' | (string & {});
1034
+ /** One line item under a compensation ticket. */
1035
+ interface CompensationItemDetail {
1036
+ /** Amount (e.g. unit price). */
1037
+ itemAmount?: number;
1038
+ itemCode?: string;
1039
+ /** Item count (number of units claimed). */
1040
+ itemCount?: number;
1041
+ itemName?: string;
1042
+ }
1043
+ /**
1044
+ * A Trendyol Express compensation ticket — filed when a shipment is lost
1045
+ * or damaged in transit. Returned by `orders.getCompensationTickets()`.
1046
+ */
1047
+ interface CompensationTicket {
1048
+ cargoProvider?: string;
1049
+ compensateReason?: string;
1050
+ /** ISO 8601 UTC string (converted from `createDate` ms-epoch). */
1051
+ createdAt?: string;
1052
+ currentState?: CompensationTicketState;
1053
+ deliveryNumber?: string;
1054
+ itemDetails: CompensationItemDetail[];
1055
+ orderNumber?: string;
1056
+ requestedBy?: string;
1057
+ stateMessage?: string;
1058
+ /** Total amount across items — Trendyol returns this as a string. */
1059
+ totalItemsAmount?: string;
1060
+ /** Untouched raw ticket response. */
1061
+ raw: Record<string, unknown>;
1062
+ }
1063
+ /** Filter / pagination params for `orders.getCompensationTickets()`. */
1064
+ interface ListCompensationTicketsParams extends CursorPaginationParams {
1065
+ /** Lower bound on `createDate` (Trendyol expects ms-epoch). */
1066
+ startDate?: Date;
1067
+ /** Upper bound on `createDate`. */
1068
+ endDate?: Date;
1069
+ }
1070
+
594
1071
  interface ListOrdersParams extends CursorPaginationParams {
595
1072
  status?: ShipmentPackageStatus;
596
1073
  orderNumber?: string;
@@ -599,6 +1076,16 @@ interface ListOrdersParams extends CursorPaginationParams {
599
1076
  /** Filter packages updated on or before this date. */
600
1077
  endDate?: Date;
601
1078
  }
1079
+ /**
1080
+ * Normalize one raw Trendyol shipment-package node into the public
1081
+ * `ShipmentPackage` shape. Exported so consumers handling Trendyol
1082
+ * webhooks can reuse the SDK's normalization logic on the event body
1083
+ * (Trendyol POSTs the same shape it returns from `getShipmentPackages`).
1084
+ *
1085
+ * For full-webhook parsing use `parseWebhookEvent(rawBody)` from the
1086
+ * top-level package, which calls this internally per item.
1087
+ */
1088
+ declare function normalizeShipmentPackage(rawNode: unknown): ShipmentPackage;
602
1089
  /**
603
1090
  * Trendyol order (shipment-package) endpoints.
604
1091
  *
@@ -782,6 +1269,43 @@ declare class OrdersResource {
782
1269
  * Page-based pagination internally (cursor encodes the page index).
783
1270
  */
784
1271
  getCargoInvoiceItems(invoiceSerialNumber: string, params?: CursorPaginationParams): Promise<CursorPage<CargoInvoiceItem>>;
1272
+ /**
1273
+ * Notify Trendyol that a shipped package was returned to you (manual
1274
+ * return flow, e.g. customer dropped it at your address or you got the
1275
+ * package back without going through Trendyol's return cargo).
1276
+ *
1277
+ * No body; Trendyol responds with 200 + empty body on success.
1278
+ */
1279
+ manualReturnByPackageId(packageId: string | number): Promise<void>;
1280
+ /**
1281
+ * Manual-return variant that takes the cargo tracking number instead of
1282
+ * the package ID. Useful when the cargo provider's webhook only carries
1283
+ * the tracking number.
1284
+ *
1285
+ * Sibling path (not under `/{packageId}/...`).
1286
+ */
1287
+ manualReturnByTrackingNumber(cargoTrackingNumber: string | number): Promise<void>;
1288
+ /**
1289
+ * Fetch Trendyol Express compensation tickets (claims filed when a
1290
+ * shipment is lost or damaged in transit). Page-based pagination
1291
+ * internally; the SDK exposes the cursor convention.
1292
+ *
1293
+ * Note the different base path — `/integration/tex/compensation/...`,
1294
+ * not the regular `/integration/order/...`.
1295
+ *
1296
+ * @example
1297
+ * ```ts
1298
+ * import { paginate } from '@lonca/core';
1299
+ * const tickets = await client.orders.getCompensationTickets({
1300
+ * startDate: new Date('2026-01-01'),
1301
+ * endDate: new Date('2026-02-01'),
1302
+ * });
1303
+ * for (const t of tickets.items) {
1304
+ * console.log(t.orderNumber, t.currentState, t.stateMessage);
1305
+ * }
1306
+ * ```
1307
+ */
1308
+ getCompensationTickets(params?: ListCompensationTicketsParams): Promise<CursorPage<CompensationTicket>>;
785
1309
  private packagePath;
786
1310
  }
787
1311
 
@@ -1345,6 +1869,86 @@ declare class ProductsResource {
1345
1869
  unlock(barcodes: string[]): Promise<BatchAcceptedResponse>;
1346
1870
  }
1347
1871
 
1872
+ /**
1873
+ * Trendyol customer Q&A types.
1874
+ *
1875
+ * Customers can post product questions on Trendyol; sellers reply via
1876
+ * `questions.answer()`. Status lifecycle:
1877
+ * `WAITING_FOR_ANSWER` → seller replies → `ANSWERED`
1878
+ * → reported by another seller / Trendyol → `REPORTED`
1879
+ * → rejected by Trendyol moderation → `REJECTED`
1880
+ */
1881
+
1882
+ type QuestionStatus = 'WAITING_FOR_ANSWER' | 'ANSWERED' | 'REJECTED' | 'REPORTED' | (string & {});
1883
+ interface QuestionAnswer {
1884
+ text?: string;
1885
+ /** ISO 8601 UTC (converted from `creationDate` ms-epoch). */
1886
+ createdAt?: string;
1887
+ status?: string;
1888
+ }
1889
+ interface Question {
1890
+ id: string;
1891
+ text?: string;
1892
+ customerId?: string;
1893
+ /** Masked customer display name. */
1894
+ userName?: string;
1895
+ showUserName?: boolean;
1896
+ status?: QuestionStatus;
1897
+ /** Whether the question is visible publicly. */
1898
+ public?: boolean;
1899
+ productMainId?: string;
1900
+ productName?: string;
1901
+ imageUrl?: string;
1902
+ webUrl?: string;
1903
+ /** ISO 8601 UTC (from ms-epoch). */
1904
+ createdAt?: string;
1905
+ /** Trendyol's pre-formatted "answered on ..." message (Turkish). */
1906
+ answeredDateMessage?: string;
1907
+ answer?: QuestionAnswer;
1908
+ rejectedAnswer?: QuestionAnswer;
1909
+ /** ISO 8601 UTC if the question was rejected. */
1910
+ rejectedAt?: string;
1911
+ reason?: string;
1912
+ reportReason?: string;
1913
+ /** ISO 8601 UTC if the question was reported. */
1914
+ reportedAt?: string;
1915
+ /** Untouched raw response. */
1916
+ raw: Record<string, unknown>;
1917
+ }
1918
+ interface ListQuestionsParams extends CursorPaginationParams {
1919
+ /** Filter to questions about a specific product barcode. */
1920
+ barcode?: string;
1921
+ startDate?: Date;
1922
+ endDate?: Date;
1923
+ /** Filter by current status. */
1924
+ status?: QuestionStatus;
1925
+ }
1926
+
1927
+ /**
1928
+ * Trendyol customer Q&A management. Customers post product questions on
1929
+ * Trendyol; sellers reply with `questions.answer()`.
1930
+ */
1931
+ declare class QuestionsResource {
1932
+ private readonly transport;
1933
+ private readonly sellerId;
1934
+ private readonly limiter;
1935
+ constructor(transport: TrendyolTransport, sellerId: number, limiter?: TokenBucketRateLimiter);
1936
+ /** Fetch a single question by its numeric ID. */
1937
+ get(questionId: string | number): Promise<Question>;
1938
+ /**
1939
+ * Filter questions by barcode / date range / status. Page-based
1940
+ * pagination internally; SDK exposes the opaque-cursor convention.
1941
+ */
1942
+ list(params?: ListQuestionsParams): Promise<CursorPage<Question>>;
1943
+ /**
1944
+ * Reply to a question. Trendyol enforces 10–2000 characters on the
1945
+ * answer text; the SDK pre-validates client-side.
1946
+ *
1947
+ * @throws {ValidationError} when `text` is outside the 10–2000 char range.
1948
+ */
1949
+ answer(questionId: string | number, text: string): Promise<unknown>;
1950
+ }
1951
+
1348
1952
  /**
1349
1953
  * The role an address plays in the seller's logistics flow.
1350
1954
  *
@@ -1417,6 +2021,127 @@ declare class SuppliersResource {
1417
2021
  private fetchFresh;
1418
2022
  }
1419
2023
 
2024
+ /**
2025
+ * STAGE-only helper endpoints for creating + driving test orders /
2026
+ * test claims through their state machine. **Do not use in PROD** —
2027
+ * Trendyol's test endpoints are scoped to the test environment.
2028
+ */
2029
+ declare class TestOrdersResource {
2030
+ private readonly transport;
2031
+ private readonly sellerId;
2032
+ private readonly limiter;
2033
+ constructor(transport: TrendyolTransport, sellerId: number, limiter?: TokenBucketRateLimiter);
2034
+ /**
2035
+ * Create a test order with the given customer / addresses / lines. The
2036
+ * SDK forwards the typed payload verbatim — drill into Trendyol's
2037
+ * `createTestOrder` doc for inner field rules.
2038
+ *
2039
+ * @throws {ValidationError} when required top-level fields are missing.
2040
+ */
2041
+ create(input: CreateTestOrderInput): Promise<unknown>;
2042
+ /** Push a test shipment package to the given status. */
2043
+ updateStatus(packageId: string | number, status: TestOrderStatus): Promise<unknown>;
2044
+ /** Move test claims to the `WaitingInAction` state. */
2045
+ setClaimsWaitingInAction(): Promise<unknown>;
2046
+ }
2047
+
2048
+ /**
2049
+ * Trendyol webhook subscription types.
2050
+ *
2051
+ * Webhooks let Trendyol push shipment-package status events to a URL you
2052
+ * own instead of polling. Max 15 active webhooks per seller. Trendyol
2053
+ * itself authenticates against your endpoint (you don't sign Trendyol's
2054
+ * request) — pick `BASIC_AUTHENTICATION` (username+password) or `API_KEY`
2055
+ * (rotatable; recommended).
2056
+ */
2057
+
2058
+ /** Auth method Trendyol uses when calling your webhook URL. */
2059
+ type WebhookAuthenticationType = 'BASIC_AUTHENTICATION' | 'API_KEY';
2060
+ /**
2061
+ * Payload for `webhooks.create` / `webhooks.update`. Same shape for both.
2062
+ */
2063
+ interface WebhookInput {
2064
+ /** Your endpoint URL (must accept POST JSON from Trendyol). */
2065
+ url: string;
2066
+ /** Auth scheme Trendyol will use to call your endpoint. */
2067
+ authenticationType: WebhookAuthenticationType;
2068
+ /** Username (only when `authenticationType === 'BASIC_AUTHENTICATION'`). */
2069
+ username?: string;
2070
+ /** Password (only when `authenticationType === 'BASIC_AUTHENTICATION'`). */
2071
+ password?: string;
2072
+ /** API key (only when `authenticationType === 'API_KEY'`). */
2073
+ apiKey?: string;
2074
+ /**
2075
+ * Order statuses you want events for. Empty/omitted = all statuses.
2076
+ * Trendyol accepts the same vocabulary as `ShipmentPackageStatus`
2077
+ * (the upper-snake-case variants — `'CREATED'`, `'PICKING'`, etc. — see
2078
+ * Trendyol docs for the exact wire spelling, which sometimes differs
2079
+ * from the read-side `'Created'`/`'Picking'`).
2080
+ */
2081
+ subscribedStatuses?: string[];
2082
+ }
2083
+ /** A registered webhook subscription as returned by `webhooks.list`. */
2084
+ interface Webhook {
2085
+ id: string;
2086
+ url?: string;
2087
+ authenticationType?: WebhookAuthenticationType;
2088
+ username?: string;
2089
+ apiKey?: string;
2090
+ subscribedStatuses?: string[];
2091
+ /** Active vs deactivated. */
2092
+ active?: boolean;
2093
+ /** Untouched raw webhook entry. */
2094
+ raw: Record<string, unknown>;
2095
+ }
2096
+
2097
+ /**
2098
+ * Trendyol webhook subscription management.
2099
+ *
2100
+ * Max **15 active webhooks per seller** (Trendyol-enforced). Webhooks
2101
+ * fire on shipment-package status events only — there is no webhook
2102
+ * support for product / stock changes.
2103
+ *
2104
+ * Trendyol's gateway authenticates **against your endpoint** with the
2105
+ * `authenticationType` you configure. Pick `API_KEY` over
2106
+ * `BASIC_AUTHENTICATION` so you can rotate the secret without redeploying.
2107
+ *
2108
+ * No HMAC signature — security relies entirely on the auth method you
2109
+ * pick + the secret you store with Trendyol.
2110
+ */
2111
+ declare class WebhooksResource {
2112
+ private readonly transport;
2113
+ private readonly sellerId;
2114
+ private readonly limiter;
2115
+ constructor(transport: TrendyolTransport, sellerId: number, limiter?: TokenBucketRateLimiter);
2116
+ /**
2117
+ * Create a new webhook subscription. Trendyol caps subscriptions at 15
2118
+ * per seller — the SDK does NOT pre-check (you'd need to call `list()`
2119
+ * first), but Trendyol returns 400 when the cap is exceeded.
2120
+ *
2121
+ * @throws {ValidationError} when `url` or `authenticationType` is missing.
2122
+ */
2123
+ create(input: WebhookInput): Promise<unknown>;
2124
+ /** List all registered webhook subscriptions. */
2125
+ list(): Promise<Webhook[]>;
2126
+ /**
2127
+ * Update a webhook subscription. Same input shape as `create`; replaces
2128
+ * the whole subscription (Trendyol does NOT partially update).
2129
+ */
2130
+ update(webhookId: string | number, input: WebhookInput): Promise<unknown>;
2131
+ /** Permanently delete a webhook subscription. */
2132
+ delete(webhookId: string | number): Promise<unknown>;
2133
+ /** Re-activate a previously-deactivated webhook subscription. */
2134
+ activate(webhookId: string | number): Promise<unknown>;
2135
+ /**
2136
+ * Deactivate a webhook subscription. Trendyol automatically deactivates
2137
+ * a subscription after persistent delivery failures (and sends 2 emails);
2138
+ * use `activate()` to bring it back online once your endpoint is healthy.
2139
+ */
2140
+ deactivate(webhookId: string | number): Promise<unknown>;
2141
+ private validateInput;
2142
+ private webhookPath;
2143
+ }
2144
+
1420
2145
  interface CreateClientOptions {
1421
2146
  /** Trendyol seller (supplier) ID — visible in Partner Panel → Account Info. */
1422
2147
  sellerId: number;
@@ -1450,6 +2175,14 @@ interface TrendyolClient {
1450
2175
  products: ProductsResource;
1451
2176
  inventory: InventoryResource;
1452
2177
  orders: OrdersResource;
2178
+ claims: ClaimsResource;
2179
+ webhooks: WebhooksResource;
2180
+ questions: QuestionsResource;
2181
+ invoices: InvoicesResource;
2182
+ finance: FinanceResource;
2183
+ labels: LabelsResource;
2184
+ testOrders: TestOrdersResource;
2185
+ locations: LocationsResource;
1453
2186
  }
1454
2187
  /**
1455
2188
  * Create a Trendyol Marketplace SDK client.
@@ -1470,4 +2203,92 @@ interface TrendyolClient {
1470
2203
  */
1471
2204
  declare function createTrendyolClient(opts: CreateClientOptions): TrendyolClient;
1472
2205
 
1473
- export { type BarcodeCategoryLookup, type BatchAcceptedResponse, type BatchRequestItemResult, type BatchRequestResult, type BatchRequestStatus, type Brand, BrandsResource, type BuyboxInfo, type CancelPackageItemInput, type CargoInvoiceItem, CategoriesResource, type Category, type CategoryAttribute, type CategoryAttributeValue, type CreateClientOptions, type CreateProductV2Input, type DeliveryOptionInput, InventoryResource, type LaborCostInput, type ListCategoryAttributeValuesParams, type ListOrdersParams, type ListOrdersStreamParams, type ListProductsParams, type ListUnapprovedProductsParams, type NamedRef, type OrderAddress, type OrderAddressLines, type OrderCustomer, type OrderLine, type OrderLineDiscountDetail, OrdersResource, type PackageDetail, type PackageHistoryEntry, type PackageLineUpdate, type PriceInventoryUpdate, type ProcessAlternativeDeliveryInput, type Product, type ProductAttribute, type ProductAttributeV2Input, type ProductBase, type ProductImageInput, type ProductVariant, ProductsResource, type QuantitySplit, type ShipmentPackage, type ShipmentPackageStatus, type SplitGroup, type SplitPackagePlan, type SupplierAddress, type SupplierAddressType, SuppliersResource, type SuppliersResourceOptions, type TrendyolCargoProvider, type TrendyolClient, type TrendyolEnvironment, type UnapprovedDateQueryType, type UnapprovedProduct, type UnapprovedProductRejectReason, type UnapprovedProductStatus, type UpdateBoxInfoInput, type UpdateContentInput, type UpdateDeliveryInfoInput, type UpdatePackageStatusInput, type UpdatePriceInventoryResponse, type UpdateUnapprovedInput, type UpdateVariantInput, createTrendyolClient };
2206
+ /**
2207
+ * Inbound webhook event payloads — what Trendyol POSTs to YOUR endpoint
2208
+ * when a subscribed shipment-package status event fires.
2209
+ *
2210
+ * Per Trendyol's "Webhook Model" doc:
2211
+ * - Method: POST, body: JSON
2212
+ * - Wire shape: identical to `getShipmentPackages` response envelope
2213
+ * (`{ totalElements, totalPages, page, size, content: [...] }`)
2214
+ * - Sent on every status transition for a subscribed status (see
2215
+ * `WebhookEventStatus` below) — the full order data is delivered
2216
+ * each time, not a delta.
2217
+ *
2218
+ * Trendyol authenticates against YOUR endpoint using the method you
2219
+ * configured on the subscription (BASIC_AUTHENTICATION or API_KEY). The
2220
+ * SDK does NOT validate auth on its end — handle that in your request
2221
+ * middleware before passing the body to `parseWebhookEvent`.
2222
+ *
2223
+ * Retry: on a non-2xx response, Trendyol retries every 5 minutes; after
2224
+ * persistent failures the subscription is auto-deactivated (you'll get
2225
+ * 2 emails). Reactivate via `client.webhooks.activate(id)` once your
2226
+ * endpoint is healthy again.
2227
+ */
2228
+
2229
+ /**
2230
+ * Status values Trendyol sends as the event trigger. Note the
2231
+ * **upper-snake-case** spelling here, distinct from `ShipmentPackageStatus`
2232
+ * (which uses PascalCase on the API read responses).
2233
+ */
2234
+ type WebhookEventStatus = 'CREATED' | 'PICKING' | 'INVOICED' | 'SHIPPED' | 'CANCELLED' | 'DELIVERED' | 'UNDELIVERED' | 'RETURNED' | 'UNSUPPLIED' | 'AWAITING' | 'UNPACKED' | 'AT_COLLECTION_POINT' | 'VERIFIED' | (string & {});
2235
+ /**
2236
+ * Origin of a package, surfaced as `ShipmentPackage.createdBy` on the
2237
+ * normalized event payload. Useful for routing logic (e.g. trigger a
2238
+ * different flow for `'split'` packages than `'order-creation'`).
2239
+ */
2240
+ type PackageCreatedBy = 'order-creation' | 'cancel' | 'split' | 'transfer' | (string & {});
2241
+ /**
2242
+ * The parsed webhook event body. `packages` is the normalized
2243
+ * `content[]` from the inbound JSON; `pageInfo` carries Trendyol's
2244
+ * pagination envelope verbatim so you can log / surface it.
2245
+ *
2246
+ * In practice `packages.length === 1` for status-change events, but the
2247
+ * model is defined as a page so the same handler can absorb future
2248
+ * batch events without breaking.
2249
+ */
2250
+ interface WebhookEvent {
2251
+ packages: ShipmentPackage[];
2252
+ pageInfo: {
2253
+ totalElements?: number;
2254
+ totalPages?: number;
2255
+ page?: number;
2256
+ size?: number;
2257
+ };
2258
+ /** Raw inbound body — fall back here for fields the SDK doesn't surface. */
2259
+ raw: Record<string, unknown>;
2260
+ }
2261
+
2262
+ /**
2263
+ * Top-level helper for parsing incoming Trendyol webhook event bodies
2264
+ * into the SDK's typed shape.
2265
+ *
2266
+ * Usage in an Express route:
2267
+ *
2268
+ * ```ts
2269
+ * import { parseWebhookEvent } from '@lonca/trendyol';
2270
+ *
2271
+ * app.post('/trendyol/webhook', express.json(), (req, res) => {
2272
+ * const event = parseWebhookEvent(req.body);
2273
+ * for (const pkg of event.packages) {
2274
+ * // pkg: typed ShipmentPackage — same shape as orders.list()
2275
+ * await myQueue.enqueue({ packageId: pkg.id, status: pkg.status });
2276
+ * }
2277
+ * res.sendStatus(200);
2278
+ * });
2279
+ * ```
2280
+ */
2281
+
2282
+ /**
2283
+ * Parse an inbound webhook body into a typed `WebhookEvent`.
2284
+ *
2285
+ * Accepts either an already-parsed object or a JSON string. Returns
2286
+ * normalized `ShipmentPackage[]` (the same shape `orders.list()`
2287
+ * produces), plus the page envelope and the raw body for fallthrough.
2288
+ *
2289
+ * @throws {ValidationError} when the body isn't an object / valid JSON,
2290
+ * or when `content` is missing or not an array.
2291
+ */
2292
+ declare function parseWebhookEvent(rawBody: unknown): WebhookEvent;
2293
+
2294
+ export { type ApproveClaimLineItemsInput, type BarcodeCategoryLookup, type BatchAcceptedResponse, type BatchRequestItemResult, type BatchRequestResult, type BatchRequestStatus, type Brand, BrandsResource, type BuyboxInfo, type CancelPackageItemInput, type CargoInvoiceItem, CategoriesResource, type Category, type CategoryAttribute, type CategoryAttributeValue, type City, type Claim, type ClaimIssueReason, type ClaimItemAudit, type ClaimItemStatus, ClaimsResource, type CommonLabel, type CommonLabelEntry, type CompensationItemDetail, type CompensationTicket, type CompensationTicketState, type Country, type CreateClaimInput, type CreateClaimIssueInput, type CreateClaimItemInput, type CreateClientOptions, type CreateCommonLabelInput, type CreateProductV2Input, type CreateTestOrderInput, type DeleteInvoiceLinkInput, type DeliveryOptionInput, type District, FinanceResource, type FinancialTransaction, InventoryResource, InvoicesResource, LabelsResource, type LaborCostInput, type ListCategoryAttributeValuesParams, type ListClaimsParams, type ListCompensationTicketsParams, type ListFinanceParams, type ListOrdersParams, type ListOrdersStreamParams, type ListProductsParams, type ListQuestionsParams, type ListUnapprovedProductsParams, LocationsResource, type NamedRef, type Neighborhood, type OrderAddress, type OrderAddressLines, type OrderCustomer, type OrderLine, type OrderLineDiscountDetail, OrdersResource, type OtherFinancialRow, type PackageCreatedBy, type PackageDetail, type PackageHistoryEntry, type PackageLineUpdate, type PriceInventoryUpdate, type ProcessAlternativeDeliveryInput, type Product, type ProductAttribute, type ProductAttributeV2Input, type ProductBase, type ProductImageInput, type ProductVariant, ProductsResource, type QuantitySplit, type Question, type QuestionAnswer, type QuestionStatus, QuestionsResource, type SendInvoiceLinkInput, type SettlementRow, type ShipmentPackage, type ShipmentPackageStatus, type SplitGroup, type SplitPackagePlan, type SupplierAddress, type SupplierAddressType, SuppliersResource, type SuppliersResourceOptions, type TestOrderStatus, TestOrdersResource, type TrendyolCargoProvider, type TrendyolClient, type TrendyolEnvironment, type UnapprovedDateQueryType, type UnapprovedProduct, type UnapprovedProductRejectReason, type UnapprovedProductStatus, type UpdateBoxInfoInput, type UpdateContentInput, type UpdateDeliveryInfoInput, type UpdatePackageStatusInput, type UpdatePriceInventoryResponse, type UpdateUnapprovedInput, type UpdateVariantInput, type UploadInvoiceFileInput, type Webhook, type WebhookAuthenticationType, type WebhookEvent, type WebhookEventStatus, type WebhookInput, WebhooksResource, createTrendyolClient, normalizeShipmentPackage, parseWebhookEvent };