ebay-mcp 1.4.7 → 1.5.1
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/README.md +55 -99
- package/build/api/developer/developer.js +81 -0
- package/build/api/index.js +4 -0
- package/build/api/listing-management/inventory.js +36 -1
- package/build/api/marketing-and-promotions/marketing.js +211 -8
- package/build/auth/oauth.js +4 -3
- package/build/config/environment.js +3 -2
- package/build/schemas/account-management/account.js +26 -17
- package/build/schemas/communication/messages.js +78 -81
- package/build/schemas/fulfillment/orders.js +98 -77
- package/build/schemas/inventory-management/inventory.js +81 -60
- package/build/schemas/marketing/marketing.js +35 -20
- package/build/schemas/metadata/metadata.js +6 -2
- package/build/schemas/other/other-apis.js +36 -18
- package/build/schemas/taxonomy/taxonomy.js +6 -2
- package/build/scripts/auto-setup.js +3 -3
- package/build/scripts/dev-sync.js +351 -0
- package/build/scripts/diagnostics.js +6 -6
- package/build/scripts/interactive-setup.js +46 -17
- package/build/scripts/setup.js +567 -0
- package/build/server-http.js +1 -1
- package/build/tools/definitions/communication.js +245 -2
- package/build/tools/definitions/developer.js +152 -0
- package/build/tools/definitions/index.js +3 -1
- package/build/tools/definitions/inventory.js +38 -3
- package/build/tools/definitions/marketing.js +391 -0
- package/build/tools/index.js +116 -4
- package/build/tools/tool-definitions.js +715 -715
- package/build/utils/oauth-helper.js +146 -146
- package/package.json +11 -32
package/README.md
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/ebay-mcp)
|
|
6
6
|
[](https://www.npmjs.com/package/ebay-mcp)
|
|
7
|
-
[](tests/)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
|
|
10
10
|
[](https://mseep.ai/app/yosefhayim-ebay-api-mcp-server)
|
|
11
11
|
<a href="https://www.buymeacoffee.com/yosefhayim" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
|
|
12
12
|
|
|
13
|
-
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server providing AI assistants with comprehensive access to eBay's Sell APIs. Includes
|
|
13
|
+
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server providing AI assistants with comprehensive access to eBay's Sell APIs. Includes **339 tools** for inventory management, order fulfillment, marketing campaigns, analytics, developer tools, and more.
|
|
14
14
|
|
|
15
|
-
**API Coverage:**
|
|
15
|
+
**API Coverage:** 82.5% (293 of 355 eBay API endpoints)
|
|
16
16
|
|
|
17
17
|
</div>
|
|
18
18
|
|
|
@@ -75,12 +75,13 @@ For official eBay API support, please refer to the [eBay Developer Program](http
|
|
|
75
75
|
|
|
76
76
|
## Features
|
|
77
77
|
|
|
78
|
-
- **
|
|
78
|
+
- **339 eBay API Tools** - Comprehensive coverage of eBay Sell APIs across inventory, orders, marketing, analytics, developer tools, and more
|
|
79
79
|
- **OAuth 2.0 Support** - Full user token management with automatic refresh
|
|
80
80
|
- **Type Safety** - Built with TypeScript, Zod validation, and OpenAPI-generated types
|
|
81
81
|
- **MCP Integration** - STDIO transport for direct integration with AI assistants
|
|
82
82
|
- **Smart Authentication** - Automatic fallback from user tokens (10k-50k req/day) to client credentials (1k req/day)
|
|
83
|
-
- **Well Tested** -
|
|
83
|
+
- **Well Tested** - 914+ tests with comprehensive coverage
|
|
84
|
+
- **Developer Analytics** - Rate limit monitoring and signing key management
|
|
84
85
|
|
|
85
86
|
## Quick Start
|
|
86
87
|
|
|
@@ -115,13 +116,7 @@ Run the interactive setup wizard:
|
|
|
115
116
|
npm run setup
|
|
116
117
|
```
|
|
117
118
|
|
|
118
|
-
Or manually
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
cp .env.example .env
|
|
122
|
-
# Edit .env with your credentials
|
|
123
|
-
npm run auto-setup
|
|
124
|
-
```
|
|
119
|
+
Or configure manually by copying `.env.example` to `.env` and editing your credentials.
|
|
125
120
|
|
|
126
121
|
### 4. Configure MCP Client
|
|
127
122
|
|
|
@@ -284,15 +279,16 @@ Monitor your API usage in the [eBay Developer Portal](https://developer.ebay.com
|
|
|
284
279
|
|
|
285
280
|
## Available Tools
|
|
286
281
|
|
|
287
|
-
The server provides
|
|
282
|
+
The server provides **339 tools** organized into the following categories:
|
|
288
283
|
|
|
289
284
|
- **Account Management** - Policies, programs, subscriptions, sales tax
|
|
290
|
-
- **Inventory Management** - Items, offers, locations, bulk operations
|
|
291
|
-
- **Order Fulfillment** - Orders, shipping, refunds, disputes
|
|
292
|
-
- **Marketing & Promotions** - Campaigns, ads, promotions, bidding
|
|
285
|
+
- **Inventory Management** - Items, offers, locations, bulk operations, SKU location mapping
|
|
286
|
+
- **Order Fulfillment** - Orders, shipping, refunds, disputes, payment dispute evidence
|
|
287
|
+
- **Marketing & Promotions** - Campaigns, ads, promotions, bidding, bulk operations
|
|
293
288
|
- **Analytics** - Traffic reports, seller standards, metrics
|
|
294
|
-
- **Communication** - Buyer-seller messaging, negotiations
|
|
289
|
+
- **Communication** - Buyer-seller messaging, negotiations, notifications, feedback
|
|
295
290
|
- **Metadata & Taxonomy** - Categories, item aspects, policies
|
|
291
|
+
- **Developer Tools** - Rate limits, signing keys, client registration
|
|
296
292
|
- **Token Management** - OAuth URL generation, token management
|
|
297
293
|
|
|
298
294
|
**Example Tools:**
|
|
@@ -357,103 +353,54 @@ Here are some common tasks you can accomplish with the eBay MCP server:
|
|
|
357
353
|
- npm or pnpm
|
|
358
354
|
- eBay Developer Account
|
|
359
355
|
|
|
360
|
-
###
|
|
356
|
+
### Quick Start for Contributors
|
|
361
357
|
|
|
362
358
|
```bash
|
|
363
|
-
# Fork and clone the repository
|
|
364
359
|
git clone https://github.com/YOUR_USERNAME/ebay-mcp.git
|
|
365
360
|
cd ebay-mcp
|
|
366
|
-
|
|
367
|
-
# Install dependencies
|
|
368
361
|
npm install
|
|
369
|
-
|
|
370
|
-
# Set up environment
|
|
371
|
-
cp .env.example .env
|
|
372
|
-
# Edit .env with your credentials
|
|
373
|
-
|
|
374
|
-
# Build and test
|
|
362
|
+
npm run setup # Interactive setup wizard
|
|
375
363
|
npm run build
|
|
376
364
|
npm test
|
|
377
365
|
```
|
|
378
366
|
|
|
379
|
-
###
|
|
367
|
+
### Commands Reference
|
|
380
368
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
npm run
|
|
384
|
-
npm
|
|
385
|
-
npm run
|
|
386
|
-
npm
|
|
387
|
-
npm run
|
|
388
|
-
npm run
|
|
389
|
-
|
|
369
|
+
| Command | Description |
|
|
370
|
+
| ------------------ | -------------------------------------------------- |
|
|
371
|
+
| `npm run build` | Compile TypeScript to JavaScript |
|
|
372
|
+
| `npm start` | Run the MCP server |
|
|
373
|
+
| `npm run dev` | Run server with hot reload |
|
|
374
|
+
| `npm test` | Run test suite |
|
|
375
|
+
| `npm run setup` | Interactive setup wizard |
|
|
376
|
+
| `npm run sync` | Sync specs, generate types, find missing endpoints |
|
|
377
|
+
| `npm run diagnose` | Check configuration and connectivity |
|
|
378
|
+
| `npm run check` | Run typecheck + lint + format check |
|
|
379
|
+
| `npm run fix` | Auto-fix lint and format issues |
|
|
390
380
|
|
|
391
|
-
###
|
|
381
|
+
### Adding New API Endpoints
|
|
392
382
|
|
|
393
|
-
|
|
383
|
+
When eBay releases new API endpoints, use the sync tool to identify what's missing:
|
|
394
384
|
|
|
395
385
|
```bash
|
|
396
|
-
|
|
397
|
-
npm run docker:build
|
|
398
|
-
|
|
399
|
-
# Start the container
|
|
400
|
-
npm run docker:up
|
|
401
|
-
|
|
402
|
-
# View logs
|
|
403
|
-
npm run docker:logs
|
|
404
|
-
|
|
405
|
-
# Stop the container
|
|
406
|
-
npm run docker:down
|
|
407
|
-
|
|
408
|
-
# Restart the container
|
|
409
|
-
npm run docker:restart
|
|
386
|
+
npm run sync
|
|
410
387
|
```
|
|
411
388
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
The server can be run with Docker Compose for easy deployment:
|
|
415
|
-
|
|
416
|
-
```bash
|
|
417
|
-
docker-compose up -d
|
|
418
|
-
```
|
|
389
|
+
This single command will:
|
|
419
390
|
|
|
420
|
-
|
|
391
|
+
1. Download latest OpenAPI specs from eBay
|
|
392
|
+
2. Generate TypeScript types from specs
|
|
393
|
+
3. Analyze which endpoints are implemented
|
|
394
|
+
4. Report missing endpoints that need tools
|
|
421
395
|
|
|
422
|
-
**
|
|
396
|
+
**Workflow for adding a new endpoint:**
|
|
423
397
|
|
|
424
|
-
|
|
425
|
-
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
In addition to the default STDIO transport for MCP clients, the server can run in HTTP mode for testing and debugging:
|
|
432
|
-
|
|
433
|
-
```bash
|
|
434
|
-
# Development
|
|
435
|
-
npm run dev:http
|
|
436
|
-
|
|
437
|
-
# Production
|
|
438
|
-
npm run start:http
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
**HTTP Mode Features:**
|
|
442
|
-
|
|
443
|
-
- RESTful API endpoints for all tools
|
|
444
|
-
- Interactive API documentation
|
|
445
|
-
- Useful for testing tools without an MCP client
|
|
446
|
-
- CORS support for web applications
|
|
447
|
-
- Helmet security headers
|
|
448
|
-
|
|
449
|
-
**When to Use HTTP Mode:**
|
|
450
|
-
|
|
451
|
-
- Testing individual tools during development
|
|
452
|
-
- Building custom integrations
|
|
453
|
-
- Debugging API responses
|
|
454
|
-
- Creating web-based interfaces
|
|
455
|
-
|
|
456
|
-
**Note:** STDIO mode (default) is recommended for MCP client integration (Claude Desktop, etc.). HTTP mode is primarily for development and custom integrations.
|
|
398
|
+
1. Run `npm run sync` to identify missing endpoints
|
|
399
|
+
2. Check `dev-sync-report.json` for the full list
|
|
400
|
+
3. Create a new tool in `src/tools/definitions/`
|
|
401
|
+
4. Add the API method in `src/api/`
|
|
402
|
+
5. Write tests in `tests/`
|
|
403
|
+
6. Run `npm run check && npm test`
|
|
457
404
|
|
|
458
405
|
### Project Structure
|
|
459
406
|
|
|
@@ -464,13 +411,22 @@ ebay-mcp/
|
|
|
464
411
|
│ ├── api/ # eBay API implementations
|
|
465
412
|
│ ├── auth/ # OAuth & token management
|
|
466
413
|
│ ├── tools/ # MCP tool definitions
|
|
467
|
-
│ ├── types/ # TypeScript types
|
|
468
|
-
│
|
|
414
|
+
│ ├── types/ # TypeScript types (auto-generated)
|
|
415
|
+
│ ├── scripts/ # CLI tools (setup, sync, diagnose)
|
|
416
|
+
│ └── utils/ # Shared utilities
|
|
417
|
+
├── docs/ # OpenAPI specs (auto-downloaded)
|
|
469
418
|
├── tests/ # Test suite
|
|
470
|
-
├── docs/ # Documentation
|
|
471
419
|
└── build/ # Compiled output
|
|
472
420
|
```
|
|
473
421
|
|
|
422
|
+
### Docker Support
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
docker-compose up -d # Start container
|
|
426
|
+
docker-compose logs -f # View logs
|
|
427
|
+
docker-compose down # Stop container
|
|
428
|
+
```
|
|
429
|
+
|
|
474
430
|
For detailed contribution guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
475
431
|
|
|
476
432
|
## Contributing
|
|
@@ -541,7 +497,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
|
|
|
541
497
|
1. Verify you're using the correct environment (sandbox vs production)
|
|
542
498
|
2. Ensure you have proper permissions/scopes for the operation
|
|
543
499
|
3. Check eBay API status: https://developer.ebay.com/support/api-status
|
|
544
|
-
4. Run `npm run diagnose
|
|
500
|
+
4. Run `npm run diagnose` to check your configuration
|
|
545
501
|
5. Review the [eBay API documentation](https://developer.ebay.com/docs) for endpoint requirements
|
|
546
502
|
|
|
547
503
|
### Diagnostic Tools
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Developer API - Rate limits, client registration, and signing keys
|
|
3
|
+
* Based on:
|
|
4
|
+
* - docs/sell-apps/application-settings/developer_analytics_v1_beta_oas3.json
|
|
5
|
+
* - docs/sell-apps/application-settings/developer_client_registration_v1_oas3.json
|
|
6
|
+
* - docs/sell-apps/application-settings/developer_key_management_v1_oas3.json
|
|
7
|
+
*/
|
|
8
|
+
export class DeveloperApi {
|
|
9
|
+
client;
|
|
10
|
+
analyticsBasePath = '/developer/analytics/v1_beta';
|
|
11
|
+
clientBasePath = '/developer/client_registration/v1';
|
|
12
|
+
keyBasePath = '/developer/key_management/v1';
|
|
13
|
+
constructor(client) {
|
|
14
|
+
this.client = client;
|
|
15
|
+
}
|
|
16
|
+
// ========================================
|
|
17
|
+
// RATE LIMITS (Analytics API)
|
|
18
|
+
// ========================================
|
|
19
|
+
/**
|
|
20
|
+
* Get application rate limits
|
|
21
|
+
* Endpoint: GET /rate_limit/
|
|
22
|
+
*/
|
|
23
|
+
async getRateLimits(apiContext, apiName) {
|
|
24
|
+
const params = {};
|
|
25
|
+
if (apiContext)
|
|
26
|
+
params.api_context = apiContext;
|
|
27
|
+
if (apiName)
|
|
28
|
+
params.api_name = apiName;
|
|
29
|
+
return await this.client.get(`${this.analyticsBasePath}/rate_limit/`, Object.keys(params).length > 0 ? params : undefined);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get user rate limits
|
|
33
|
+
* Endpoint: GET /user_rate_limit/
|
|
34
|
+
*/
|
|
35
|
+
async getUserRateLimits(apiContext, apiName) {
|
|
36
|
+
const params = {};
|
|
37
|
+
if (apiContext)
|
|
38
|
+
params.api_context = apiContext;
|
|
39
|
+
if (apiName)
|
|
40
|
+
params.api_name = apiName;
|
|
41
|
+
return await this.client.get(`${this.analyticsBasePath}/user_rate_limit/`, Object.keys(params).length > 0 ? params : undefined);
|
|
42
|
+
}
|
|
43
|
+
// ========================================
|
|
44
|
+
// CLIENT REGISTRATION
|
|
45
|
+
// ========================================
|
|
46
|
+
/**
|
|
47
|
+
* Register a new third party financial application with eBay
|
|
48
|
+
* Endpoint: POST /client/register
|
|
49
|
+
* Note: This is primarily for Open Banking / PSD2 compliance
|
|
50
|
+
*/
|
|
51
|
+
async registerClient(clientSettings) {
|
|
52
|
+
return await this.client.post(`${this.clientBasePath}/client/register`, clientSettings);
|
|
53
|
+
}
|
|
54
|
+
// ========================================
|
|
55
|
+
// SIGNING KEY MANAGEMENT
|
|
56
|
+
// ========================================
|
|
57
|
+
/**
|
|
58
|
+
* Get all signing keys for the application
|
|
59
|
+
* Endpoint: GET /signing_key
|
|
60
|
+
*/
|
|
61
|
+
async getSigningKeys() {
|
|
62
|
+
return await this.client.get(`${this.keyBasePath}/signing_key`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a new signing key
|
|
66
|
+
* Endpoint: POST /signing_key
|
|
67
|
+
*/
|
|
68
|
+
async createSigningKey(request) {
|
|
69
|
+
return await this.client.post(`${this.keyBasePath}/signing_key`, request || {});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get a specific signing key by ID
|
|
73
|
+
* Endpoint: GET /signing_key/{signing_key_id}
|
|
74
|
+
*/
|
|
75
|
+
async getSigningKey(signingKeyId) {
|
|
76
|
+
if (!signingKeyId || typeof signingKeyId !== 'string') {
|
|
77
|
+
throw new Error('signingKeyId is required and must be a string');
|
|
78
|
+
}
|
|
79
|
+
return await this.client.get(`${this.keyBasePath}/signing_key/${signingKeyId}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
package/build/api/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { FeedbackApi } from '../api/communication/feedback.js';
|
|
|
5
5
|
import { MessageApi } from '../api/communication/message.js';
|
|
6
6
|
import { NegotiationApi } from '../api/communication/negotiation.js';
|
|
7
7
|
import { NotificationApi } from '../api/communication/notification.js';
|
|
8
|
+
import { DeveloperApi } from '../api/developer/developer.js';
|
|
8
9
|
import { InventoryApi } from '../api/listing-management/inventory.js';
|
|
9
10
|
import { MetadataApi } from '../api/listing-metadata/metadata.js';
|
|
10
11
|
import { TaxonomyApi } from '../api/listing-metadata/taxonomy.js';
|
|
@@ -41,6 +42,7 @@ export class EbaySellerApi {
|
|
|
41
42
|
vero;
|
|
42
43
|
translation;
|
|
43
44
|
edelivery;
|
|
45
|
+
developer;
|
|
44
46
|
constructor(config) {
|
|
45
47
|
this.client = new EbayApiClient(config);
|
|
46
48
|
// Initialize API category handlers
|
|
@@ -62,6 +64,7 @@ export class EbaySellerApi {
|
|
|
62
64
|
this.vero = new VeroApi(this.client);
|
|
63
65
|
this.translation = new TranslationApi(this.client);
|
|
64
66
|
this.edelivery = new EDeliveryApi(this.client);
|
|
67
|
+
this.developer = new DeveloperApi(this.client);
|
|
65
68
|
}
|
|
66
69
|
/**
|
|
67
70
|
* Initialize the API (load tokens from storage)
|
|
@@ -119,3 +122,4 @@ export * from '../api/other/edelivery.js';
|
|
|
119
122
|
export * from '../api/other/identity.js';
|
|
120
123
|
export * from '../api/other/translation.js';
|
|
121
124
|
export * from '../api/other/vero.js';
|
|
125
|
+
export * from '../api/developer/developer.js';
|
|
@@ -580,7 +580,7 @@ export class InventoryApi {
|
|
|
580
580
|
}
|
|
581
581
|
}
|
|
582
582
|
/**
|
|
583
|
-
* Get listing's inventory locations
|
|
583
|
+
* Get listing's inventory locations (SKU location mapping)
|
|
584
584
|
* Endpoint: GET /listing/{listingId}/sku/{sku}/locations
|
|
585
585
|
* @throws Error if required parameters are missing or invalid
|
|
586
586
|
*/
|
|
@@ -598,6 +598,41 @@ export class InventoryApi {
|
|
|
598
598
|
throw new Error(`Failed to get listing locations: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
599
599
|
}
|
|
600
600
|
}
|
|
601
|
+
async createOrReplaceSkuLocationMapping(listingId, sku, locationMapping) {
|
|
602
|
+
if (!listingId || typeof listingId !== 'string') {
|
|
603
|
+
throw new Error('listingId is required and must be a string');
|
|
604
|
+
}
|
|
605
|
+
if (!sku || typeof sku !== 'string') {
|
|
606
|
+
throw new Error('sku is required and must be a string');
|
|
607
|
+
}
|
|
608
|
+
if (!locationMapping || typeof locationMapping !== 'object') {
|
|
609
|
+
throw new Error('locationMapping is required and must be an object');
|
|
610
|
+
}
|
|
611
|
+
try {
|
|
612
|
+
return await this.client.put(`${this.basePath}/listing/${listingId}/sku/${sku}/locations`, locationMapping, {
|
|
613
|
+
headers: {
|
|
614
|
+
'Content-Type': 'application/json',
|
|
615
|
+
},
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
catch (error) {
|
|
619
|
+
throw new Error(`Failed to create or replace SKU location mapping: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
async deleteSkuLocationMapping(listingId, sku) {
|
|
623
|
+
if (!listingId || typeof listingId !== 'string') {
|
|
624
|
+
throw new Error('listingId is required and must be a string');
|
|
625
|
+
}
|
|
626
|
+
if (!sku || typeof sku !== 'string') {
|
|
627
|
+
throw new Error('sku is required and must be a string');
|
|
628
|
+
}
|
|
629
|
+
try {
|
|
630
|
+
return await this.client.delete(`${this.basePath}/listing/${listingId}/sku/${sku}/locations`);
|
|
631
|
+
}
|
|
632
|
+
catch (error) {
|
|
633
|
+
throw new Error(`Failed to delete SKU location mapping: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
601
636
|
/**
|
|
602
637
|
* Publish offer by inventory item group
|
|
603
638
|
* Endpoint: POST /offer/publish_by_inventory_item_group
|
|
@@ -155,15 +155,12 @@ export class MarketingApi {
|
|
|
155
155
|
async bulkCreateAdsByListingId(campaignId, body) {
|
|
156
156
|
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/bulk_create_ads_by_listing_id`, body);
|
|
157
157
|
}
|
|
158
|
-
/**
|
|
159
|
-
* Bulk delete ads by inventory reference
|
|
160
|
-
*/
|
|
161
158
|
async bulkDeleteAdsByInventoryReference(campaignId, body) {
|
|
162
159
|
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/bulk_delete_ads_by_inventory_reference`, body);
|
|
163
160
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
161
|
+
async deleteAdsByInventoryReference(campaignId, body) {
|
|
162
|
+
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/delete_ads_by_inventory_reference`, body);
|
|
163
|
+
}
|
|
167
164
|
async bulkDeleteAdsByListingId(campaignId, body) {
|
|
168
165
|
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/bulk_delete_ads_by_listing_id`, body);
|
|
169
166
|
}
|
|
@@ -430,13 +427,13 @@ export class MarketingApi {
|
|
|
430
427
|
* Get promotion summary (alias for getPromotionSummaryReport)
|
|
431
428
|
*/
|
|
432
429
|
async getPromotionSummary(marketplaceId) {
|
|
433
|
-
return this.getPromotionSummaryReport(marketplaceId);
|
|
430
|
+
return await this.getPromotionSummaryReport(marketplaceId);
|
|
434
431
|
}
|
|
435
432
|
/**
|
|
436
433
|
* Get promotion reports (alias for getPromotionReport)
|
|
437
434
|
*/
|
|
438
435
|
async getPromotionReports(marketplaceId, promotionStatus, limit, offset) {
|
|
439
|
-
return this.getPromotionReport(marketplaceId, promotionStatus, limit, offset);
|
|
436
|
+
return await this.getPromotionReport(marketplaceId, promotionStatus, limit, offset);
|
|
440
437
|
}
|
|
441
438
|
/**
|
|
442
439
|
* Get targeting for a campaign
|
|
@@ -562,4 +559,210 @@ export class MarketingApi {
|
|
|
562
559
|
async updateNegativeKeywordForAdGroup(adGroupId, negativeKeywordId, body) {
|
|
563
560
|
return await this.client.put(`${this.basePath}/ad_group/${adGroupId}/negative_keyword/${negativeKeywordId}`, body);
|
|
564
561
|
}
|
|
562
|
+
/**
|
|
563
|
+
* Delete a campaign
|
|
564
|
+
*/
|
|
565
|
+
async deleteCampaign(campaignId) {
|
|
566
|
+
return await this.client.delete(`${this.basePath}/ad_campaign/${campaignId}`);
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Launch a campaign
|
|
570
|
+
*/
|
|
571
|
+
async launchCampaign(campaignId) {
|
|
572
|
+
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/launch`, {});
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Find campaign by ad reference
|
|
576
|
+
*/
|
|
577
|
+
async findCampaignByAdReference(inventoryReferenceId, inventoryReferenceType, listingId) {
|
|
578
|
+
const params = {};
|
|
579
|
+
if (inventoryReferenceId)
|
|
580
|
+
params.inventory_reference_id = inventoryReferenceId;
|
|
581
|
+
if (inventoryReferenceType)
|
|
582
|
+
params.inventory_reference_type = inventoryReferenceType;
|
|
583
|
+
if (listingId)
|
|
584
|
+
params.listing_id = listingId;
|
|
585
|
+
return await this.client.get(`${this.basePath}/ad_campaign/find_campaign_by_ad_reference`, params);
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Setup quick campaign
|
|
589
|
+
*/
|
|
590
|
+
async setupQuickCampaign(body) {
|
|
591
|
+
return await this.client.post(`${this.basePath}/ad_campaign/setup_quick_campaign`, body);
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Suggest budget for a campaign
|
|
595
|
+
*/
|
|
596
|
+
async suggestBudget(campaignId) {
|
|
597
|
+
const params = {};
|
|
598
|
+
if (campaignId)
|
|
599
|
+
params.campaign_id = campaignId;
|
|
600
|
+
return await this.client.get(`${this.basePath}/ad_campaign/suggest_budget`, params);
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Suggest items for a campaign
|
|
604
|
+
*/
|
|
605
|
+
async suggestItems(campaignId) {
|
|
606
|
+
return await this.client.get(`${this.basePath}/ad_campaign/${campaignId}/suggest_items`);
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Suggest max CPC for ads
|
|
610
|
+
*/
|
|
611
|
+
async suggestMaxCpc(body) {
|
|
612
|
+
return await this.client.post(`${this.basePath}/ad_campaign/suggest_max_cpc`, body);
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Update ad rate strategy for a campaign
|
|
616
|
+
*/
|
|
617
|
+
async updateAdRateStrategy(campaignId, body) {
|
|
618
|
+
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/update_ad_rate_strategy`, body);
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Update bidding strategy for a campaign
|
|
622
|
+
*/
|
|
623
|
+
async updateBiddingStrategy(campaignId, body) {
|
|
624
|
+
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/update_bidding_strategy`, body);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Update campaign budget
|
|
628
|
+
*/
|
|
629
|
+
async updateCampaignBudget(campaignId, body) {
|
|
630
|
+
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/update_campaign_budget`, body);
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Update an ad group
|
|
634
|
+
*/
|
|
635
|
+
async updateAdGroup(campaignId, adGroupId, body) {
|
|
636
|
+
return await this.client.put(`${this.basePath}/ad_campaign/${campaignId}/ad_group/${adGroupId}`, body);
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Update a keyword
|
|
640
|
+
*/
|
|
641
|
+
async updateKeyword(campaignId, keywordId, body) {
|
|
642
|
+
return await this.client.put(`${this.basePath}/ad_campaign/${campaignId}/keyword/${keywordId}`, body);
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Bulk create keywords (campaign level)
|
|
646
|
+
*/
|
|
647
|
+
async bulkCreateKeyword(campaignId, body) {
|
|
648
|
+
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/bulk_create_keyword`, body);
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Bulk update keywords (campaign level)
|
|
652
|
+
*/
|
|
653
|
+
async bulkUpdateKeyword(campaignId, body) {
|
|
654
|
+
return await this.client.post(`${this.basePath}/ad_campaign/${campaignId}/bulk_update_keyword`, body);
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Get a report by ID
|
|
658
|
+
*/
|
|
659
|
+
async getReport(reportId) {
|
|
660
|
+
return await this.client.get(`${this.basePath}/ad_report/${reportId}`);
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Delete a report task
|
|
664
|
+
*/
|
|
665
|
+
async deleteReportTask(reportTaskId) {
|
|
666
|
+
return await this.client.delete(`${this.basePath}/ad_report_task/${reportTaskId}`);
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Create an item price markdown promotion
|
|
670
|
+
*/
|
|
671
|
+
async createItemPriceMarkdownPromotion(body) {
|
|
672
|
+
return await this.client.post(`${this.basePath}/item_price_markdown`, body);
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Get an item price markdown promotion
|
|
676
|
+
*/
|
|
677
|
+
async getItemPriceMarkdownPromotion(promotionId) {
|
|
678
|
+
return await this.client.get(`${this.basePath}/item_price_markdown/${promotionId}`);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Update an item price markdown promotion
|
|
682
|
+
*/
|
|
683
|
+
async updateItemPriceMarkdownPromotion(promotionId, body) {
|
|
684
|
+
return await this.client.put(`${this.basePath}/item_price_markdown/${promotionId}`, body);
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Delete an item price markdown promotion
|
|
688
|
+
*/
|
|
689
|
+
async deleteItemPriceMarkdownPromotion(promotionId) {
|
|
690
|
+
return await this.client.delete(`${this.basePath}/item_price_markdown/${promotionId}`);
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Get listing set for a promotion
|
|
694
|
+
*/
|
|
695
|
+
async getListingSet(promotionId) {
|
|
696
|
+
return await this.client.get(`${this.basePath}/promotion/${promotionId}/get_listing_set`);
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Pause a promotion
|
|
700
|
+
*/
|
|
701
|
+
async pausePromotion(promotionId) {
|
|
702
|
+
return await this.client.post(`${this.basePath}/promotion/${promotionId}/pause`, {});
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Resume a promotion
|
|
706
|
+
*/
|
|
707
|
+
async resumePromotion(promotionId) {
|
|
708
|
+
return await this.client.post(`${this.basePath}/promotion/${promotionId}/resume`, {});
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Get email campaigns
|
|
712
|
+
*/
|
|
713
|
+
async getEmailCampaigns(limit, offset) {
|
|
714
|
+
const params = {};
|
|
715
|
+
if (limit)
|
|
716
|
+
params.limit = limit;
|
|
717
|
+
if (offset)
|
|
718
|
+
params.offset = offset;
|
|
719
|
+
return await this.client.get(`${this.basePath}/email_campaign`, params);
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Create an email campaign
|
|
723
|
+
*/
|
|
724
|
+
async createEmailCampaign(body) {
|
|
725
|
+
return await this.client.post(`${this.basePath}/email_campaign`, body);
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Get an email campaign
|
|
729
|
+
*/
|
|
730
|
+
async getEmailCampaign(emailCampaignId) {
|
|
731
|
+
return await this.client.get(`${this.basePath}/email_campaign/${emailCampaignId}`);
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Update an email campaign
|
|
735
|
+
*/
|
|
736
|
+
async updateEmailCampaign(emailCampaignId, body) {
|
|
737
|
+
return await this.client.put(`${this.basePath}/email_campaign/${emailCampaignId}`, body);
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Delete an email campaign
|
|
741
|
+
*/
|
|
742
|
+
async deleteEmailCampaign(emailCampaignId) {
|
|
743
|
+
return await this.client.delete(`${this.basePath}/email_campaign/${emailCampaignId}`);
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Get email campaign audiences
|
|
747
|
+
*/
|
|
748
|
+
async getAudiences() {
|
|
749
|
+
return await this.client.get(`${this.basePath}/email_campaign/audience`);
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Get email preview for a campaign
|
|
753
|
+
*/
|
|
754
|
+
async getEmailPreview(emailCampaignId) {
|
|
755
|
+
return await this.client.get(`${this.basePath}/email_campaign/${emailCampaignId}/email_preview`);
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Get email campaign report
|
|
759
|
+
*/
|
|
760
|
+
async getEmailReport(limit, offset) {
|
|
761
|
+
const params = {};
|
|
762
|
+
if (limit)
|
|
763
|
+
params.limit = limit;
|
|
764
|
+
if (offset)
|
|
765
|
+
params.offset = offset;
|
|
766
|
+
return await this.client.get(`${this.basePath}/email_campaign/report`, params);
|
|
767
|
+
}
|
|
565
768
|
}
|
package/build/auth/oauth.js
CHANGED
|
@@ -160,8 +160,8 @@ export class EbayOAuthClient {
|
|
|
160
160
|
userAccessToken: accessToken,
|
|
161
161
|
userRefreshToken: refreshToken,
|
|
162
162
|
tokenType: 'Bearer',
|
|
163
|
-
userAccessTokenExpiry: accessTokenExpiry ??
|
|
164
|
-
userRefreshTokenExpiry: refreshTokenExpiry ??
|
|
163
|
+
userAccessTokenExpiry: accessTokenExpiry ?? now + 7200 * 1000, // Default 2 hours
|
|
164
|
+
userRefreshTokenExpiry: refreshTokenExpiry ?? now + 18 * 30 * 24 * 60 * 60 * 1000, // Default 18 months
|
|
165
165
|
};
|
|
166
166
|
// Update .env file with new tokens
|
|
167
167
|
updateEnvFile({
|
|
@@ -303,7 +303,8 @@ export class EbayOAuthClient {
|
|
|
303
303
|
EBAY_USER_ACCESS_TOKEN: tokenData.access_token,
|
|
304
304
|
};
|
|
305
305
|
// If eBay provided a new refresh token, update it too
|
|
306
|
-
if (tokenData.refresh_token &&
|
|
306
|
+
if (tokenData.refresh_token &&
|
|
307
|
+
tokenData.refresh_token !== process.env.EBAY_USER_REFRESH_TOKEN) {
|
|
307
308
|
envUpdates.EBAY_USER_REFRESH_TOKEN = tokenData.refresh_token;
|
|
308
309
|
// New refresh token updated silently
|
|
309
310
|
}
|