ebay-mcp-remote-edition 1.0.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/LICENSE +21 -0
- package/README.md +755 -0
- package/build/api/account-management/account.js +301 -0
- package/build/api/analytics-and-report/analytics.js +102 -0
- package/build/api/client-trading.js +96 -0
- package/build/api/client.js +173 -0
- package/build/api/communication/feedback.js +119 -0
- package/build/api/communication/message.js +131 -0
- package/build/api/communication/negotiation.js +97 -0
- package/build/api/communication/notification.js +373 -0
- package/build/api/developer/developer.js +81 -0
- package/build/api/index.js +109 -0
- package/build/api/listing-management/inventory.js +640 -0
- package/build/api/listing-metadata/metadata.js +485 -0
- package/build/api/listing-metadata/taxonomy.js +58 -0
- package/build/api/marketing-and-promotions/marketing.js +768 -0
- package/build/api/marketing-and-promotions/recommendation.js +32 -0
- package/build/api/order-management/dispute.js +69 -0
- package/build/api/order-management/fulfillment.js +89 -0
- package/build/api/other/compliance.js +47 -0
- package/build/api/other/edelivery.js +219 -0
- package/build/api/other/identity.js +24 -0
- package/build/api/other/translation.js +22 -0
- package/build/api/other/vero.js +48 -0
- package/build/api/trading/trading.js +78 -0
- package/build/auth/kv-store.js +40 -0
- package/build/auth/multi-user-store.js +120 -0
- package/build/auth/oauth-metadata.js +59 -0
- package/build/auth/oauth-middleware.js +99 -0
- package/build/auth/oauth-types.js +4 -0
- package/build/auth/oauth.js +235 -0
- package/build/auth/scope-utils.js +304 -0
- package/build/auth/token-store.js +46 -0
- package/build/auth/token-verifier.js +172 -0
- package/build/config/environment.js +297 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +129 -0
- package/build/schemas/account-management/account.js +375 -0
- package/build/schemas/analytics/analytics.js +191 -0
- package/build/schemas/communication/messages.js +345 -0
- package/build/schemas/fulfillment/orders.js +338 -0
- package/build/schemas/index.js +68 -0
- package/build/schemas/inventory-management/inventory.js +471 -0
- package/build/schemas/marketing/marketing.js +1103 -0
- package/build/schemas/metadata/metadata.js +618 -0
- package/build/schemas/other/other-apis.js +390 -0
- package/build/schemas/taxonomy/taxonomy.js +575 -0
- package/build/scripts/auto-setup.js +364 -0
- package/build/scripts/dev-sync.js +512 -0
- package/build/scripts/diagnostics.js +301 -0
- package/build/scripts/download-specs.js +116 -0
- package/build/scripts/interactive-setup.js +757 -0
- package/build/scripts/setup.js +1515 -0
- package/build/scripts/update-api-status-doc.js +44 -0
- package/build/server-http.d.ts +1 -0
- package/build/server-http.js +581 -0
- package/build/tools/definitions/account-with-schemas.js +170 -0
- package/build/tools/definitions/account.js +428 -0
- package/build/tools/definitions/analytics.js +66 -0
- package/build/tools/definitions/communication.js +394 -0
- package/build/tools/definitions/developer.js +195 -0
- package/build/tools/definitions/fulfillment.js +326 -0
- package/build/tools/definitions/index.js +41 -0
- package/build/tools/definitions/inventory.js +464 -0
- package/build/tools/definitions/marketing.js +1486 -0
- package/build/tools/definitions/metadata.js +188 -0
- package/build/tools/definitions/other.js +309 -0
- package/build/tools/definitions/taxonomy.js +64 -0
- package/build/tools/definitions/token-management.js +148 -0
- package/build/tools/definitions/trading.js +71 -0
- package/build/tools/index.js +1200 -0
- package/build/tools/schemas.js +667 -0
- package/build/tools/tool-definitions.js +3534 -0
- package/build/types/application-settings/developerAnalyticsV1BetaOas3.js +5 -0
- package/build/types/application-settings/developerClientRegistrationV1Oas3.js +5 -0
- package/build/types/application-settings/developerKeyManagementV1Oas3.js +5 -0
- package/build/types/ebay-enums.js +1330 -0
- package/build/types/ebay.js +123 -0
- package/build/types/index.js +10 -0
- package/build/types/sell-apps/account-management/sellAccountV1Oas3.js +5 -0
- package/build/types/sell-apps/analytics-and-report/sellAnalyticsV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/commerceFeedbackV1BetaOas3.js +5 -0
- package/build/types/sell-apps/communication/commerceMessageV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/commerceNotificationV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/sellNegotiationV1Oas3.js +5 -0
- package/build/types/sell-apps/listing-management/sellInventoryV1Oas3.js +5 -0
- package/build/types/sell-apps/listing-metadata/sellMetadataV1Oas3.js +5 -0
- package/build/types/sell-apps/markeitng-and-promotions/sellMarketingV1Oas3.js +5 -0
- package/build/types/sell-apps/markeitng-and-promotions/sellRecommendationV1Oas3.js +5 -0
- package/build/types/sell-apps/order-management/sellFulfillmentV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceIdentityV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceTranslationV1BetaOas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceVeroV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellComplianceV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellEdeliveryInternationalShippingOas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellMarketingV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellRecommendationV1Oas3.js +5 -0
- package/build/utils/account-management/account.js +831 -0
- package/build/utils/api-status-feed.js +83 -0
- package/build/utils/communication/feedback.js +216 -0
- package/build/utils/communication/message.js +242 -0
- package/build/utils/communication/negotiation.js +150 -0
- package/build/utils/communication/notification.js +369 -0
- package/build/utils/date-converter.js +160 -0
- package/build/utils/llm-client-detector.js +758 -0
- package/build/utils/logger.js +198 -0
- package/build/utils/oauth-helper.js +315 -0
- package/build/utils/order-management/dispute.js +369 -0
- package/build/utils/order-management/fulfillment.js +205 -0
- package/build/utils/other/compliance.js +76 -0
- package/build/utils/other/edelivery.js +241 -0
- package/build/utils/other/identity.js +13 -0
- package/build/utils/other/translation.js +41 -0
- package/build/utils/other/vero.js +90 -0
- package/build/utils/scope-helper.js +207 -0
- package/build/utils/security-checker.js +248 -0
- package/build/utils/setup-validator.js +305 -0
- package/build/utils/token-utils.js +40 -0
- package/build/utils/version.js +56 -0
- package/docs/auth/production_scopes.json +111 -0
- package/docs/auth/sandbox_scopes.json +142 -0
- package/package.json +122 -0
- package/public/icons/1024x1024.png +0 -0
- package/public/icons/128x128.png +0 -0
- package/public/icons/16x16.png +0 -0
- package/public/icons/256x256.png +0 -0
- package/public/icons/32x32.png +0 -0
- package/public/icons/48x48.png +0 -0
- package/public/icons/512x512.png +0 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account API - Seller account configuration, policies, programs
|
|
3
|
+
* Based on: docs/sell-apps/account-management/sell_account_v1_oas3.json
|
|
4
|
+
*/
|
|
5
|
+
export class AccountApi {
|
|
6
|
+
client;
|
|
7
|
+
basePath = '/sell/account/v1';
|
|
8
|
+
constructor(client) {
|
|
9
|
+
this.client = client;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get custom policies for the seller
|
|
13
|
+
*/
|
|
14
|
+
async getCustomPolicies(policyTypes) {
|
|
15
|
+
const params = policyTypes ? { policy_types: policyTypes } : undefined;
|
|
16
|
+
return await this.client.get(`${this.basePath}/custom_policy`, params);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get a specific custom policy
|
|
20
|
+
*/
|
|
21
|
+
async getCustomPolicy(customPolicyId) {
|
|
22
|
+
return await this.client.get(`${this.basePath}/custom_policy/${customPolicyId}`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get fulfillment policies
|
|
26
|
+
* @param marketplaceId - Required: The eBay marketplace ID
|
|
27
|
+
*/
|
|
28
|
+
async getFulfillmentPolicies(marketplaceId) {
|
|
29
|
+
return await this.client.get(`${this.basePath}/fulfillment_policy`, {
|
|
30
|
+
marketplace_id: marketplaceId,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get payment policies
|
|
35
|
+
* @param marketplaceId - Required: The eBay marketplace ID
|
|
36
|
+
*/
|
|
37
|
+
async getPaymentPolicies(marketplaceId) {
|
|
38
|
+
return await this.client.get(`${this.basePath}/payment_policy`, {
|
|
39
|
+
marketplace_id: marketplaceId,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get return policies
|
|
44
|
+
* @param marketplaceId - Required: The eBay marketplace ID
|
|
45
|
+
*/
|
|
46
|
+
async getReturnPolicies(marketplaceId) {
|
|
47
|
+
return await this.client.get(`${this.basePath}/return_policy`, {
|
|
48
|
+
marketplace_id: marketplaceId,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get seller account privileges
|
|
53
|
+
*/
|
|
54
|
+
async getPrivileges() {
|
|
55
|
+
return await this.client.get(`${this.basePath}/privilege`);
|
|
56
|
+
}
|
|
57
|
+
// ============================================================
|
|
58
|
+
// Fulfillment Policy Methods
|
|
59
|
+
// ============================================================
|
|
60
|
+
/**
|
|
61
|
+
* Create a new fulfillment policy
|
|
62
|
+
*/
|
|
63
|
+
async createFulfillmentPolicy(policy) {
|
|
64
|
+
return await this.client.post(`${this.basePath}/fulfillment_policy`, policy);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get a specific fulfillment policy by ID
|
|
68
|
+
*/
|
|
69
|
+
async getFulfillmentPolicy(fulfillmentPolicyId) {
|
|
70
|
+
return await this.client.get(`${this.basePath}/fulfillment_policy/${fulfillmentPolicyId}`);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get a fulfillment policy by name
|
|
74
|
+
*/
|
|
75
|
+
async getFulfillmentPolicyByName(marketplaceId, name) {
|
|
76
|
+
return await this.client.get(`${this.basePath}/fulfillment_policy_by_name`, {
|
|
77
|
+
marketplace_id: marketplaceId,
|
|
78
|
+
name,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Update a fulfillment policy
|
|
83
|
+
*/
|
|
84
|
+
async updateFulfillmentPolicy(fulfillmentPolicyId, policy) {
|
|
85
|
+
return await this.client.put(`${this.basePath}/fulfillment_policy/${fulfillmentPolicyId}`, policy);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Delete a fulfillment policy
|
|
89
|
+
*/
|
|
90
|
+
async deleteFulfillmentPolicy(fulfillmentPolicyId) {
|
|
91
|
+
return await this.client.delete(`${this.basePath}/fulfillment_policy/${fulfillmentPolicyId}`);
|
|
92
|
+
}
|
|
93
|
+
// ============================================================
|
|
94
|
+
// Payment Policy Methods
|
|
95
|
+
// ============================================================
|
|
96
|
+
/**
|
|
97
|
+
* Create a new payment policy
|
|
98
|
+
*/
|
|
99
|
+
async createPaymentPolicy(policy) {
|
|
100
|
+
return await this.client.post(`${this.basePath}/payment_policy`, policy);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get a specific payment policy by ID
|
|
104
|
+
*/
|
|
105
|
+
async getPaymentPolicy(paymentPolicyId) {
|
|
106
|
+
return await this.client.get(`${this.basePath}/payment_policy/${paymentPolicyId}`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get a payment policy by name
|
|
110
|
+
*/
|
|
111
|
+
async getPaymentPolicyByName(marketplaceId, name) {
|
|
112
|
+
return await this.client.get(`${this.basePath}/payment_policy_by_name`, {
|
|
113
|
+
marketplace_id: marketplaceId,
|
|
114
|
+
name,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Update a payment policy
|
|
119
|
+
*/
|
|
120
|
+
async updatePaymentPolicy(paymentPolicyId, policy) {
|
|
121
|
+
return await this.client.put(`${this.basePath}/payment_policy/${paymentPolicyId}`, policy);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Delete a payment policy
|
|
125
|
+
*/
|
|
126
|
+
async deletePaymentPolicy(paymentPolicyId) {
|
|
127
|
+
return await this.client.delete(`${this.basePath}/payment_policy/${paymentPolicyId}`);
|
|
128
|
+
}
|
|
129
|
+
// ============================================================
|
|
130
|
+
// Return Policy Methods
|
|
131
|
+
// ============================================================
|
|
132
|
+
/**
|
|
133
|
+
* Create a new return policy
|
|
134
|
+
*/
|
|
135
|
+
async createReturnPolicy(policy) {
|
|
136
|
+
return await this.client.post(`${this.basePath}/return_policy`, policy);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get a specific return policy by ID
|
|
140
|
+
*/
|
|
141
|
+
async getReturnPolicy(returnPolicyId) {
|
|
142
|
+
return await this.client.get(`${this.basePath}/return_policy/${returnPolicyId}`);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get a return policy by name
|
|
146
|
+
*/
|
|
147
|
+
async getReturnPolicyByName(marketplaceId, name) {
|
|
148
|
+
return await this.client.get(`${this.basePath}/return_policy_by_name`, {
|
|
149
|
+
marketplace_id: marketplaceId,
|
|
150
|
+
name,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Update a return policy
|
|
155
|
+
*/
|
|
156
|
+
async updateReturnPolicy(returnPolicyId, policy) {
|
|
157
|
+
return await this.client.put(`${this.basePath}/return_policy/${returnPolicyId}`, policy);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Delete a return policy
|
|
161
|
+
*/
|
|
162
|
+
async deleteReturnPolicy(returnPolicyId) {
|
|
163
|
+
return await this.client.delete(`${this.basePath}/return_policy/${returnPolicyId}`);
|
|
164
|
+
}
|
|
165
|
+
// ============================================================
|
|
166
|
+
// Custom Policy Methods
|
|
167
|
+
// ============================================================
|
|
168
|
+
/**
|
|
169
|
+
* Create a new custom policy
|
|
170
|
+
*/
|
|
171
|
+
async createCustomPolicy(policy) {
|
|
172
|
+
return await this.client.post(`${this.basePath}/custom_policy`, policy);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Update a custom policy
|
|
176
|
+
*/
|
|
177
|
+
async updateCustomPolicy(customPolicyId, policy) {
|
|
178
|
+
return await this.client.put(`${this.basePath}/custom_policy/${customPolicyId}`, policy);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Delete a custom policy
|
|
182
|
+
*/
|
|
183
|
+
async deleteCustomPolicy(customPolicyId) {
|
|
184
|
+
return await this.client.delete(`${this.basePath}/custom_policy/${customPolicyId}`);
|
|
185
|
+
}
|
|
186
|
+
// ============================================================
|
|
187
|
+
// KYC, Payments Program, Rate Tables, Sales Tax, Subscription, Programs
|
|
188
|
+
// ============================================================
|
|
189
|
+
/**
|
|
190
|
+
* Get KYC status
|
|
191
|
+
*/
|
|
192
|
+
async getKyc() {
|
|
193
|
+
return await this.client.get(`${this.basePath}/kyc`);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Opt-in to a payments program
|
|
197
|
+
*/
|
|
198
|
+
async optInToPaymentsProgram(marketplaceId, paymentsProgramType) {
|
|
199
|
+
return await this.client.post(`${this.basePath}/payments_program/${marketplaceId}/${paymentsProgramType}`, {});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get payments program status
|
|
203
|
+
*/
|
|
204
|
+
async getPaymentsProgramStatus(marketplaceId, paymentsProgramType) {
|
|
205
|
+
return await this.client.get(`${this.basePath}/payments_program/${marketplaceId}/${paymentsProgramType}`);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get rate tables
|
|
209
|
+
*/
|
|
210
|
+
async getRateTables() {
|
|
211
|
+
return await this.client.get(`${this.basePath}/rate_table`);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Create or replace sales tax table
|
|
215
|
+
*/
|
|
216
|
+
async createOrReplaceSalesTax(countryCode, jurisdictionId, salesTaxBase) {
|
|
217
|
+
return await this.client.put(`${this.basePath}/sales_tax/${countryCode}/${jurisdictionId}`, salesTaxBase);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Bulk create or replace sales tax tables
|
|
221
|
+
*/
|
|
222
|
+
async bulkCreateOrReplaceSalesTax(requests) {
|
|
223
|
+
return await this.client.post(`${this.basePath}/sales_tax/bulk_create_or_replace`, {
|
|
224
|
+
requests,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Delete sales tax table
|
|
229
|
+
*/
|
|
230
|
+
async deleteSalesTax(countryCode, jurisdictionId) {
|
|
231
|
+
return await this.client.delete(`${this.basePath}/sales_tax/${countryCode}/${jurisdictionId}`);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get sales tax table
|
|
235
|
+
*/
|
|
236
|
+
async getSalesTax(countryCode, jurisdictionId) {
|
|
237
|
+
return await this.client.get(`${this.basePath}/sales_tax/${countryCode}/${jurisdictionId}`);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get all sales tax tables
|
|
241
|
+
* @param countryCode - Required: Two-letter ISO 3166-1 country code
|
|
242
|
+
*/
|
|
243
|
+
async getSalesTaxes(countryCode) {
|
|
244
|
+
return await this.client.get(`${this.basePath}/sales_tax`, {
|
|
245
|
+
country_code: countryCode,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get subscription information
|
|
250
|
+
*/
|
|
251
|
+
async getSubscription(limitType) {
|
|
252
|
+
const params = limitType ? { limit: limitType } : undefined;
|
|
253
|
+
return await this.client.get(`${this.basePath}/subscription`, params);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Opt-in to a program
|
|
257
|
+
*/
|
|
258
|
+
async optInToProgram(request) {
|
|
259
|
+
return await this.client.post(`${this.basePath}/program/opt_in`, request);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Opt-out of a program
|
|
263
|
+
*/
|
|
264
|
+
async optOutOfProgram(request) {
|
|
265
|
+
return await this.client.post(`${this.basePath}/program/opt_out`, request);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Get opted-in programs
|
|
269
|
+
*/
|
|
270
|
+
async getOptedInPrograms() {
|
|
271
|
+
return await this.client.get(`${this.basePath}/program`);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Get seller eligibility for advertising programs
|
|
275
|
+
* This method allows developers to check the seller eligibility status for eBay advertising programs.
|
|
276
|
+
* @param programTypes - Optional comma-separated list of program types to check
|
|
277
|
+
* @param marketplaceId - Required eBay marketplace ID (passed in X-EBAY-C-MARKETPLACE-ID header)
|
|
278
|
+
*/
|
|
279
|
+
async getAdvertisingEligibility(marketplaceId, programTypes) {
|
|
280
|
+
const params = programTypes ? { program_types: programTypes } : undefined;
|
|
281
|
+
return await this.client.get(`${this.basePath}/advertising_eligibility`, params);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get payments program status for a marketplace
|
|
285
|
+
* Note: This method is deprecated as all seller accounts globally have been enabled for the new eBay payment and checkout flow.
|
|
286
|
+
* @param marketplaceId - The eBay marketplace ID
|
|
287
|
+
* @param paymentsProgramType - The type of payments program
|
|
288
|
+
*/
|
|
289
|
+
async getPaymentsProgram(marketplaceId, paymentsProgramType) {
|
|
290
|
+
return await this.client.get(`${this.basePath}/payments_program/${marketplaceId}/${paymentsProgramType}`);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Get payments program onboarding information
|
|
294
|
+
* Note: This method is deprecated as all seller accounts globally have been enabled for the new eBay payment and checkout flow.
|
|
295
|
+
* @param marketplaceId - The eBay marketplace ID
|
|
296
|
+
* @param paymentsProgramType - The type of payments program
|
|
297
|
+
*/
|
|
298
|
+
async getPaymentsProgramOnboarding(marketplaceId, paymentsProgramType) {
|
|
299
|
+
return await this.client.get(`${this.basePath}/payments_program/${marketplaceId}/${paymentsProgramType}/onboarding`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics API - Sales and traffic analytics
|
|
3
|
+
* Based on: docs/sell-apps/analytics-and-report/sell_analytics_v1_oas3.json
|
|
4
|
+
*/
|
|
5
|
+
export class AnalyticsApi {
|
|
6
|
+
client;
|
|
7
|
+
basePath = '/sell/analytics/v1';
|
|
8
|
+
constructor(client) {
|
|
9
|
+
this.client = client;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get traffic report for listings
|
|
13
|
+
* @throws Error if required parameters are missing or invalid
|
|
14
|
+
*/
|
|
15
|
+
async getTrafficReport(dimension, filter, metric, sort) {
|
|
16
|
+
// Input validation
|
|
17
|
+
if (!dimension || typeof dimension !== 'string') {
|
|
18
|
+
throw new Error('dimension is required and must be a string');
|
|
19
|
+
}
|
|
20
|
+
if (!filter || typeof filter !== 'string') {
|
|
21
|
+
throw new Error('filter is required and must be a string');
|
|
22
|
+
}
|
|
23
|
+
if (!metric || typeof metric !== 'string') {
|
|
24
|
+
throw new Error('metric is required and must be a string');
|
|
25
|
+
}
|
|
26
|
+
if (sort !== undefined && typeof sort !== 'string') {
|
|
27
|
+
throw new Error('sort must be a string when provided');
|
|
28
|
+
}
|
|
29
|
+
const params = {
|
|
30
|
+
dimension,
|
|
31
|
+
filter,
|
|
32
|
+
metric,
|
|
33
|
+
};
|
|
34
|
+
if (sort)
|
|
35
|
+
params.sort = sort;
|
|
36
|
+
try {
|
|
37
|
+
return await this.client.get(`${this.basePath}/traffic_report`, params);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new Error(`Failed to get traffic report: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Find all seller standards profiles
|
|
45
|
+
* Endpoint: GET /seller_standards_profile
|
|
46
|
+
* @throws Error if the request fails
|
|
47
|
+
*/
|
|
48
|
+
async findSellerStandardsProfiles() {
|
|
49
|
+
try {
|
|
50
|
+
return await this.client.get(`${this.basePath}/seller_standards_profile`);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
throw new Error(`Failed to find seller standards profiles: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get a specific seller standards profile
|
|
58
|
+
* Endpoint: GET /seller_standards_profile/{program}/{cycle}
|
|
59
|
+
* @throws Error if required parameters are missing or invalid
|
|
60
|
+
*/
|
|
61
|
+
async getSellerStandardsProfile(program, cycle) {
|
|
62
|
+
// Input validation
|
|
63
|
+
if (!program || typeof program !== 'string') {
|
|
64
|
+
throw new Error('program is required and must be a string');
|
|
65
|
+
}
|
|
66
|
+
if (!cycle || typeof cycle !== 'string') {
|
|
67
|
+
throw new Error('cycle is required and must be a string');
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
return await this.client.get(`${this.basePath}/seller_standards_profile/${program}/${cycle}`);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
throw new Error(`Failed to get seller standards profile: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get customer service metrics
|
|
78
|
+
* Endpoint: GET /customer_service_metric/{customer_service_metric_type}/{evaluation_type}
|
|
79
|
+
* @throws Error if required parameters are missing or invalid
|
|
80
|
+
*/
|
|
81
|
+
async getCustomerServiceMetric(customerServiceMetricType, evaluationType, evaluationMarketplaceId) {
|
|
82
|
+
// Input validation
|
|
83
|
+
if (!customerServiceMetricType || typeof customerServiceMetricType !== 'string') {
|
|
84
|
+
throw new Error('customerServiceMetricType is required and must be a string');
|
|
85
|
+
}
|
|
86
|
+
if (!evaluationType || typeof evaluationType !== 'string') {
|
|
87
|
+
throw new Error('evaluationType is required and must be a string');
|
|
88
|
+
}
|
|
89
|
+
if (!evaluationMarketplaceId || typeof evaluationMarketplaceId !== 'string') {
|
|
90
|
+
throw new Error('evaluationMarketplaceId is required and must be a string');
|
|
91
|
+
}
|
|
92
|
+
const params = {
|
|
93
|
+
evaluation_marketplace_id: evaluationMarketplaceId,
|
|
94
|
+
};
|
|
95
|
+
try {
|
|
96
|
+
return await this.client.get(`${this.basePath}/customer_service_metric/${customerServiceMetricType}/${evaluationType}`, params);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
throw new Error(`Failed to get customer service metric: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { XMLBuilder, XMLParser } from 'fast-xml-parser';
|
|
3
|
+
import { apiLogger } from '../utils/logger.js';
|
|
4
|
+
const COMPAT_LEVEL = '1451';
|
|
5
|
+
const SITE_ID = '0';
|
|
6
|
+
export class TradingApiClient {
|
|
7
|
+
restClient;
|
|
8
|
+
baseUrl;
|
|
9
|
+
parser;
|
|
10
|
+
builder;
|
|
11
|
+
constructor(restClient) {
|
|
12
|
+
this.restClient = restClient;
|
|
13
|
+
const env = restClient.getConfig().environment;
|
|
14
|
+
this.baseUrl = env === 'sandbox' ? 'https://api.sandbox.ebay.com' : 'https://api.ebay.com';
|
|
15
|
+
this.parser = new XMLParser({
|
|
16
|
+
ignoreAttributes: false,
|
|
17
|
+
removeNSPrefix: true,
|
|
18
|
+
parseTagValue: true,
|
|
19
|
+
isArray: (_name) => {
|
|
20
|
+
const arrayTags = [
|
|
21
|
+
'Item',
|
|
22
|
+
'Errors',
|
|
23
|
+
'Error',
|
|
24
|
+
'NameValueList',
|
|
25
|
+
'Value',
|
|
26
|
+
'ShippingServiceOptions',
|
|
27
|
+
'InternationalShippingServiceOption',
|
|
28
|
+
'PaymentMethods',
|
|
29
|
+
'PictureURL',
|
|
30
|
+
'CompatibilityList',
|
|
31
|
+
'Variation',
|
|
32
|
+
];
|
|
33
|
+
return arrayTags.includes(_name);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
this.builder = new XMLBuilder({
|
|
37
|
+
ignoreAttributes: false,
|
|
38
|
+
format: true,
|
|
39
|
+
suppressEmptyNode: true,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
getBaseUrl() {
|
|
43
|
+
return this.baseUrl;
|
|
44
|
+
}
|
|
45
|
+
async execute(callName, params) {
|
|
46
|
+
const token = await this.restClient.getOAuthClient().getAccessToken();
|
|
47
|
+
const requestTag = `${callName}Request`;
|
|
48
|
+
const responseTag = `${callName}Response`;
|
|
49
|
+
const xmlObj = {};
|
|
50
|
+
xmlObj[requestTag] = {
|
|
51
|
+
'@_xmlns': 'urn:ebay:apis:eBLBaseComponents',
|
|
52
|
+
...params,
|
|
53
|
+
};
|
|
54
|
+
const xmlBody = `<?xml version="1.0" encoding="utf-8"?>\n${this.builder.build(xmlObj)}`;
|
|
55
|
+
apiLogger.debug(`Trading API ${callName}`, { xmlBody });
|
|
56
|
+
let response;
|
|
57
|
+
try {
|
|
58
|
+
response = await axios.post(`${this.baseUrl}/ws/api.dll`, xmlBody, {
|
|
59
|
+
headers: {
|
|
60
|
+
'X-EBAY-API-SITEID': SITE_ID,
|
|
61
|
+
'X-EBAY-API-COMPATIBILITY-LEVEL': COMPAT_LEVEL,
|
|
62
|
+
'X-EBAY-API-CALL-NAME': callName,
|
|
63
|
+
'X-EBAY-API-IAF-TOKEN': token,
|
|
64
|
+
'Content-Type': 'text/xml',
|
|
65
|
+
},
|
|
66
|
+
timeout: 30000,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const message = error instanceof Error ? error.message : 'Unknown HTTP error';
|
|
71
|
+
throw new Error(`Trading API ${callName} request failed: ${message}`);
|
|
72
|
+
}
|
|
73
|
+
let parsed;
|
|
74
|
+
try {
|
|
75
|
+
parsed = this.parser.parse(response.data);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
throw new Error(`Failed to parse Trading API ${callName} response: ${e instanceof Error ? e.message : String(e)}`);
|
|
79
|
+
}
|
|
80
|
+
const result = (parsed[responseTag] || parsed);
|
|
81
|
+
// Log warnings without failing
|
|
82
|
+
if (result.Ack === 'Warning') {
|
|
83
|
+
apiLogger.warn(`Trading API ${callName} returned warnings`, {
|
|
84
|
+
errors: result.Errors,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Check for eBay errors
|
|
88
|
+
if (result.Ack === 'Failure' || result.Ack === 'PartialFailure') {
|
|
89
|
+
const errors = result.Errors;
|
|
90
|
+
const firstError = Array.isArray(errors) ? errors[0] : errors;
|
|
91
|
+
const message = firstError?.ShortMessage || firstError?.LongMessage || 'Unknown Trading API error';
|
|
92
|
+
throw new Error(message);
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { EbayOAuthClient } from '../auth/oauth.js';
|
|
2
|
+
import { getBaseUrl } from '../config/environment.js';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
import { logRequest, logResponse, logErrorResponse } from '../utils/logger.js';
|
|
5
|
+
class RateLimitTracker {
|
|
6
|
+
requestTimestamps = [];
|
|
7
|
+
windowMs = 60000;
|
|
8
|
+
maxRequests = 5000;
|
|
9
|
+
canMakeRequest() {
|
|
10
|
+
const now = Date.now();
|
|
11
|
+
this.requestTimestamps = this.requestTimestamps.filter((timestamp) => now - timestamp < this.windowMs);
|
|
12
|
+
return this.requestTimestamps.length < this.maxRequests;
|
|
13
|
+
}
|
|
14
|
+
recordRequest() {
|
|
15
|
+
this.requestTimestamps.push(Date.now());
|
|
16
|
+
}
|
|
17
|
+
getStats() {
|
|
18
|
+
const now = Date.now();
|
|
19
|
+
this.requestTimestamps = this.requestTimestamps.filter((timestamp) => now - timestamp < this.windowMs);
|
|
20
|
+
return {
|
|
21
|
+
current: this.requestTimestamps.length,
|
|
22
|
+
max: this.maxRequests,
|
|
23
|
+
windowMs: this.windowMs,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class EbayApiClient {
|
|
28
|
+
httpClient;
|
|
29
|
+
authClient;
|
|
30
|
+
baseUrl;
|
|
31
|
+
rateLimitTracker;
|
|
32
|
+
config;
|
|
33
|
+
getDefaultHeaders() {
|
|
34
|
+
const headers = {
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
Accept: 'application/json',
|
|
37
|
+
};
|
|
38
|
+
if (this.config.contentLanguage) {
|
|
39
|
+
headers['Content-Language'] = this.config.contentLanguage;
|
|
40
|
+
}
|
|
41
|
+
if (this.config.marketplaceId) {
|
|
42
|
+
headers['X-EBAY-C-MARKETPLACE-ID'] = this.config.marketplaceId;
|
|
43
|
+
}
|
|
44
|
+
return headers;
|
|
45
|
+
}
|
|
46
|
+
constructor(config, context) {
|
|
47
|
+
this.config = config;
|
|
48
|
+
this.authClient = new EbayOAuthClient(config, context);
|
|
49
|
+
this.baseUrl = getBaseUrl(config.environment);
|
|
50
|
+
this.rateLimitTracker = new RateLimitTracker();
|
|
51
|
+
this.httpClient = axios.create({
|
|
52
|
+
baseURL: this.baseUrl,
|
|
53
|
+
timeout: 30000,
|
|
54
|
+
headers: this.getDefaultHeaders(),
|
|
55
|
+
});
|
|
56
|
+
this.httpClient.interceptors.request.use(async (config) => {
|
|
57
|
+
if (!this.rateLimitTracker.canMakeRequest()) {
|
|
58
|
+
const stats = this.rateLimitTracker.getStats();
|
|
59
|
+
throw new Error(`Rate limit exceeded: ${stats.current}/${stats.max} requests in ${stats.windowMs}ms window.`);
|
|
60
|
+
}
|
|
61
|
+
const token = await this.authClient.getAccessToken();
|
|
62
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
63
|
+
this.rateLimitTracker.recordRequest();
|
|
64
|
+
logRequest(config.method || 'GET', `${config.baseURL}${config.url}`, config.params, config.data);
|
|
65
|
+
return config;
|
|
66
|
+
});
|
|
67
|
+
this.httpClient.interceptors.response.use((response) => {
|
|
68
|
+
const remaining = response.headers['x-ebay-c-ratelimit-remaining'];
|
|
69
|
+
const limit = response.headers['x-ebay-c-ratelimit-limit'];
|
|
70
|
+
logResponse(response.status, response.statusText, response.data, remaining, limit);
|
|
71
|
+
return response;
|
|
72
|
+
}, async (error) => {
|
|
73
|
+
const config = error.config;
|
|
74
|
+
if (error.response) {
|
|
75
|
+
logErrorResponse(error.response.status, error.response.statusText, `${config?.baseURL}${config?.url}`, error.response.data);
|
|
76
|
+
}
|
|
77
|
+
if (error.response?.status === 401 && config) {
|
|
78
|
+
const retryCount = config.__authRetryCount || 0;
|
|
79
|
+
if (retryCount === 0) {
|
|
80
|
+
config.__authRetryCount = 1;
|
|
81
|
+
await this.authClient.refreshUserToken();
|
|
82
|
+
const newToken = await this.authClient.getAccessToken();
|
|
83
|
+
if (config.headers) {
|
|
84
|
+
config.headers.Authorization = `Bearer ${newToken}`;
|
|
85
|
+
}
|
|
86
|
+
return await this.httpClient.request(config);
|
|
87
|
+
}
|
|
88
|
+
const ebayError = error.response?.data;
|
|
89
|
+
const errorMessage = ebayError.errors?.[0]?.longMessage ||
|
|
90
|
+
ebayError.errors?.[0]?.message ||
|
|
91
|
+
'Invalid access token';
|
|
92
|
+
throw new Error(`${errorMessage}. Automatic token refresh failed.`);
|
|
93
|
+
}
|
|
94
|
+
if (error.response?.status === 429) {
|
|
95
|
+
const retryAfter = error.response.headers['retry-after'];
|
|
96
|
+
const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : 60000;
|
|
97
|
+
throw new Error(`eBay API rate limit exceeded. Retry after ${waitTime / 1000} seconds.`);
|
|
98
|
+
}
|
|
99
|
+
if (error.response?.status && error.response.status >= 500 && config) {
|
|
100
|
+
const retryCount = config.__retryCount || 0;
|
|
101
|
+
if (retryCount < 3) {
|
|
102
|
+
config.__retryCount = retryCount + 1;
|
|
103
|
+
const delay = Math.pow(2, retryCount) * 1000;
|
|
104
|
+
await new Promise((resolve) => {
|
|
105
|
+
setTimeout(resolve, Math.min(delay, 5000));
|
|
106
|
+
});
|
|
107
|
+
return await this.httpClient.request(config);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (axios.isAxiosError(error) && error.response?.data) {
|
|
111
|
+
const ebayError = error.response.data;
|
|
112
|
+
const errorMessage = ebayError.errors?.[0]?.longMessage || ebayError.errors?.[0]?.message || error.message;
|
|
113
|
+
throw new Error(`eBay API Error: ${errorMessage}`);
|
|
114
|
+
}
|
|
115
|
+
throw error;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
async initialize() {
|
|
119
|
+
await this.authClient.initialize();
|
|
120
|
+
}
|
|
121
|
+
isAuthenticated() {
|
|
122
|
+
return this.authClient.isAuthenticated();
|
|
123
|
+
}
|
|
124
|
+
hasUserTokens() {
|
|
125
|
+
return this.authClient.hasUserTokens();
|
|
126
|
+
}
|
|
127
|
+
async setUserTokens(accessToken, refreshToken, accessTokenExpiry, refreshTokenExpiry) {
|
|
128
|
+
await this.authClient.setUserTokens(accessToken, refreshToken, accessTokenExpiry, refreshTokenExpiry);
|
|
129
|
+
}
|
|
130
|
+
getTokenInfo() {
|
|
131
|
+
return this.authClient.getTokenInfo();
|
|
132
|
+
}
|
|
133
|
+
getOAuthClient() {
|
|
134
|
+
return this.authClient;
|
|
135
|
+
}
|
|
136
|
+
getRateLimitStats() {
|
|
137
|
+
return this.rateLimitTracker.getStats();
|
|
138
|
+
}
|
|
139
|
+
getConfig() {
|
|
140
|
+
return this.config;
|
|
141
|
+
}
|
|
142
|
+
async refreshUserToken() {
|
|
143
|
+
await this.authClient.refreshUserToken();
|
|
144
|
+
}
|
|
145
|
+
async get(url, params) {
|
|
146
|
+
const response = await this.httpClient.get(url, { params });
|
|
147
|
+
return response.data;
|
|
148
|
+
}
|
|
149
|
+
async post(url, data, params) {
|
|
150
|
+
const response = await this.httpClient.post(url, data, { params });
|
|
151
|
+
return response.data;
|
|
152
|
+
}
|
|
153
|
+
async put(url, data, params) {
|
|
154
|
+
const response = await this.httpClient.put(url, data, { params });
|
|
155
|
+
return response.data;
|
|
156
|
+
}
|
|
157
|
+
async delete(url, params) {
|
|
158
|
+
const response = await this.httpClient.delete(url, { params });
|
|
159
|
+
return response.data;
|
|
160
|
+
}
|
|
161
|
+
async getWithFullUrl(fullUrl, params) {
|
|
162
|
+
const token = await this.authClient.getAccessToken();
|
|
163
|
+
const response = await axios.get(fullUrl, {
|
|
164
|
+
params,
|
|
165
|
+
headers: {
|
|
166
|
+
Authorization: `Bearer ${token}`,
|
|
167
|
+
...this.getDefaultHeaders(),
|
|
168
|
+
},
|
|
169
|
+
timeout: 30000,
|
|
170
|
+
});
|
|
171
|
+
return response.data;
|
|
172
|
+
}
|
|
173
|
+
}
|