├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── stale.yml ├── .gitignore ├── .mocharc.json ├── .npmignore ├── .travis.yml ├── .versionrc.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SUMMARY.md ├── examples ├── README.md ├── restful │ ├── authFlow.ts │ ├── buy │ │ ├── browse.getShoppingCart.ts │ │ ├── browse.search.ts │ │ ├── items.getItem.ts │ │ └── marketing.getAlsoBoughtProducts.ts │ ├── developer │ │ ├── analytics.ts │ │ └── keyManagement.ts │ ├── postOrder │ │ ├── inquiry.getInquiry.ts │ │ └── return.getReturn.ts │ └── sell │ │ ├── account.getPrivileges.ts │ │ ├── finances.ts │ │ ├── fullfillment.getOrder.ts │ │ ├── getOrders.ts │ │ └── metadata.getItemConditionPolicies.ts └── traditional │ ├── authNAuth.ts │ ├── clientAlerts.GetPublicAlerts.ts │ ├── finding.findItemsAdvanced.ts │ ├── merchandising.getMostWatchedItems.ts │ ├── shopping.GetSingleItem.ts │ ├── shopping.GetUserProfile.ts │ ├── trading.GetAccount.ts │ ├── trading.GetMultipleItems.ts │ ├── trading.GetMyMessages.ts │ ├── trading.GetMyeBaySelling.ts │ ├── trading.GeteBayOfficialTime.ts │ ├── trading.UploadSiteHostedPictures.ts │ ├── upload_bad_quality.jpg │ └── upload_ok.png ├── index.html ├── package-lock.json ├── package.json ├── proxy └── worker.js ├── rollup.config.js ├── scripts └── update-readme-release.cjs ├── specs ├── buy_browse_v1_oas3.json ├── buy_deal_v1_oas3.json ├── buy_feed_v1_beta_oas3.json ├── buy_marketing_v1_beta_oas3.json ├── buy_marketplace_insights_v1_beta_oas3.json ├── buy_offer_v1_beta_oas3.json ├── buy_order_v1_beta_oas3.json ├── cancellation_oas3.json ├── case_oas3.json ├── commerce_catalog_v1_beta_oas3.json ├── commerce_charity_v1_oas3.json ├── commerce_identity_v1_oas3.json ├── commerce_media_v1_beta_oas3.json ├── commerce_notification_v1_oas3.json ├── commerce_taxonomy_v1_oas3.json ├── commerce_translation_v1_beta_oas3.json ├── developer_analytics_v1_beta_oas3.json ├── developer_key_management_v1_oas3.json ├── inquiry_oas3.json ├── return_oas3.json ├── sell_account_v1_oas3.json ├── sell_analytics_v1_oas3.json ├── sell_compliance_v1_oas3.json ├── sell_feed_v1_oas3.json ├── sell_finances_v1_oas3.json ├── sell_fulfillment_v1_oas3.json ├── sell_inventory_v1_oas3.json ├── sell_listing_v1_beta_oas3.json ├── sell_logistics_v1_oas3.json ├── sell_marketing_v1_oas3.json ├── sell_metadata_v1_oas3.json ├── sell_negotiation_v1_oas3.json └── sell_recommendation_v1_oas3.json ├── src ├── api │ ├── apiFactory.ts │ ├── base.ts │ ├── digitalSignature.ts │ ├── index.ts │ ├── restful │ │ ├── buy │ │ │ ├── browse │ │ │ │ └── index.ts │ │ │ ├── deal │ │ │ │ └── index.ts │ │ │ ├── feed │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── marketing │ │ │ │ └── index.ts │ │ │ ├── marketplaceInsights │ │ │ │ └── index.ts │ │ │ ├── offer │ │ │ │ └── index.ts │ │ │ └── order │ │ │ │ └── index.ts │ │ ├── commerce │ │ │ ├── catalog │ │ │ │ └── index.ts │ │ │ ├── charity │ │ │ │ └── index.ts │ │ │ ├── identity │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── media │ │ │ │ └── index.ts │ │ │ ├── notification │ │ │ │ └── index.ts │ │ │ ├── taxonomy │ │ │ │ └── index.ts │ │ │ └── translation │ │ │ │ └── index.ts │ │ ├── developer │ │ │ ├── analytics │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── keyManagement │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── postOrder │ │ │ ├── cancellation │ │ │ │ └── index.ts │ │ │ ├── case │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── inquiry │ │ │ │ └── index.ts │ │ │ └── return │ │ │ │ └── index.ts │ │ └── sell │ │ │ ├── account │ │ │ ├── v1.ts │ │ │ └── v2.ts │ │ │ ├── analytics │ │ │ └── index.ts │ │ │ ├── compliance │ │ │ └── index.ts │ │ │ ├── feed │ │ │ └── index.ts │ │ │ ├── finances │ │ │ └── index.ts │ │ │ ├── fulfillment │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── inventory │ │ │ └── index.ts │ │ │ ├── listing │ │ │ └── index.ts │ │ │ ├── logistics │ │ │ └── index.ts │ │ │ ├── marketing │ │ │ └── index.ts │ │ │ ├── metadata │ │ │ └── index.ts │ │ │ ├── negotiation │ │ │ └── index.ts │ │ │ └── recommendation │ │ │ └── index.ts │ └── traditional │ │ ├── XMLRequest.ts │ │ ├── clientAlerts │ │ ├── index.ts │ │ └── types.ts │ │ ├── fields.ts │ │ ├── finding │ │ └── index.ts │ │ ├── index.ts │ │ ├── merchandising │ │ └── index.ts │ │ ├── shopping │ │ └── index.ts │ │ └── trading │ │ └── index.ts ├── auth │ ├── authNAuth.ts │ ├── index.ts │ └── oAuth2.ts ├── eBayApi.ts ├── enums │ ├── apiEnums.ts │ ├── index.ts │ └── restfulEnums.ts ├── errors │ └── index.ts ├── index.ts ├── nanoevents.ts ├── request.ts └── types │ ├── apiTypes.ts │ ├── index.ts │ ├── restful │ └── specs │ │ ├── buy_browse_v1_oas3.ts │ │ ├── buy_deal_v1_oas3.ts │ │ ├── buy_feed_v1_beta_oas3.ts │ │ ├── buy_marketing_v1_beta_oas3.ts │ │ ├── buy_marketplace_insights_v1_beta_oas3.ts │ │ ├── buy_offer_v1_beta_oas3.ts │ │ ├── buy_order_v1_beta_oas3.ts │ │ ├── cancellation_oas3.ts │ │ ├── case_oas3.ts │ │ ├── commerce_catalog_v1_beta_oas3.ts │ │ ├── commerce_charity_v1_oas3.ts │ │ ├── commerce_identity_v1_oas3.ts │ │ ├── commerce_media_v1_beta_oas3.ts │ │ ├── commerce_notification_v1_oas3.ts │ │ ├── commerce_taxonomy_v1_oas3.ts │ │ ├── commerce_translation_v1_beta_oas3.ts │ │ ├── developer_analytics_v1_beta_oas3.ts │ │ ├── developer_key_management_v1_oas3.ts │ │ ├── inquiry_oas3.ts │ │ ├── return_oas3.ts │ │ ├── sell_account_v1_oas3.ts │ │ ├── sell_analytics_v1_oas3.ts │ │ ├── sell_compliance_v1_oas3.ts │ │ ├── sell_feed_v1_oas3.ts │ │ ├── sell_finances_v1_oas3.ts │ │ ├── sell_fulfillment_v1_oas3.ts │ │ ├── sell_inventory_v1_oas3.ts │ │ ├── sell_listing_v1_beta_oas3.ts │ │ ├── sell_logistics_v1_oas3.ts │ │ ├── sell_marketing_v1_oas3.ts │ │ ├── sell_metadata_v1_oas3.ts │ │ ├── sell_negotiation_v1_oas3.ts │ │ └── sell_recommendation_v1_oas3.ts │ ├── restfulTypes.ts │ └── traditonalTypes.ts ├── test └── api │ ├── authNAuth.spec.ts │ ├── digitalSignature.spec.ts │ ├── errors │ ├── errors.json │ └── errors.spec.ts │ ├── factory.spec.ts │ ├── jsonfile.ts │ ├── oAuth2.spec.ts │ ├── restful │ ├── buy │ │ └── index.ts │ ├── commerce │ │ └── index.ts │ ├── developer │ │ └── index.ts │ ├── oas.spec.ts │ ├── postOrder │ │ └── index.ts │ ├── restful.spec.ts │ └── sell │ │ └── index.ts │ └── traditional │ ├── traditional.spec.ts │ └── xmlRequest.spec.ts ├── tsconfig.cjs.json ├── tsconfig.json └── tslint.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: dantio 7 | 8 | --- 9 | 10 | * [ ] Are you running the latest version? 11 | * [ ] Have you included sample input, output, error, and expected output? 12 | * [ ] Have you checked if you are using correct configuration? 13 | 14 | **Describe the bug** 15 | A clear and concise description of what the bug is. 16 | 17 | ### Code 18 | ```js 19 | Include the code being used 20 | ``` 21 | 22 | ### Output 23 | 24 | 25 | ### expected data 26 | 27 | 28 | **Would you like to work on this issue?** 29 | 30 | - [ ] Yes 31 | - [ ] No 32 | - [ ] Maybe 33 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | dist 4 | *.sublime* 5 | *.log 6 | *.iml 7 | .idea 8 | ebay-api.iml 9 | .nyc_output 10 | coverage -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": [ 3 | "ts" 4 | ], 5 | "spec": "test/**/*.spec.ts", 6 | "loader": "ts-node/esm" 7 | } -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.log 3 | *.enc 4 | src 5 | tsconfig.json 6 | tslint.json 7 | test 8 | examples 9 | *.iml 10 | .nyc_output 11 | coverage 12 | scripts 13 | proxy 14 | specs 15 | .github 16 | index.html 17 | .travis.yml 18 | rollup.config.js 19 | .babelrc 20 | .mocharc.json 21 | .versionrc.json 22 | tsconfig.cjs.json 23 | CHANGELOG.md 24 | SUMMARY.md 25 | CONTRIBUTING.md -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 14 4 | before_install: 5 | - npm install -g codecov 6 | script: 7 | - npm run report:summary 8 | - codecov -------------------------------------------------------------------------------- /.versionrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": "# eBay API Changelog", 3 | "repository": { 4 | "host": "https://github.com/hendt/ebay-api.git", 5 | "url": "https://github.com/hendt/ebay-api.git" 6 | }, 7 | "bumpFiles": [ 8 | { 9 | "filename": "package.json", 10 | "type": "json" 11 | }, 12 | { 13 | "filename": "package-lock.json", 14 | "type": "json" 15 | }, 16 | { 17 | "filename": "README.md", 18 | "updater": "./scripts/update-readme-release.cjs" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for being willing to contribute! 4 | 5 | ## Project setup 6 | 7 | 1. Fork and clone the repo 8 | 2. `$ npm install` to install dependencies 9 | 3. `$ npm run test` to test all scenario's 10 | 4. Create a branch for your PR 11 | 5. Try to include test cases for your code 12 | 6. Follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) for commit messages 13 | 14 | ## Commit and Push 15 | 16 | Once you completed making the change, Please make sure to run the tests before you commit your changes. You can run 17 | `npm run test` which will test your code. 18 | 19 | **Working on your first Pull Request?** 20 | [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github). 21 | Thanks to @kentcdodds for this amazing tutorial. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Daniil Tomilow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [eBay TypeScript/JavaScript API for Browser and Node](README.md) 4 | * [eBay API on Github](https://github.com/hendt/ebay-api) 5 | 6 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # How to run the examples 2 | 3 | ## Node 20 4 | ```bash 5 | node --loader ts-node/esm examples/restful/buy/items.getItem.ts 6 | ``` 7 | 8 | ## Set the environments variables: 9 | EBAY_APP_ID= 10 | EBAY_CERT_ID= 11 | EBAY_DEV_ID= 12 | EBAY_RU_NAME= 13 | DEBUGX=ebay:*; 14 | 15 | ## Run 16 | ```bash 17 | ts-node examples/restful/buy/items.getItem.ts 18 | ``` -------------------------------------------------------------------------------- /examples/restful/authFlow.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import readline from 'readline'; 3 | import eBayApi from '../../src/eBayApi.js'; 4 | 5 | const eBay = eBayApi.fromEnv(); 6 | eBay.OAuth2.setScope([ 7 | 'https://api.ebay.com/oauth/api_scope', 8 | 'https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly', 9 | 'https://api.ebay.com/oauth/api_scope/sell.fulfillment' 10 | ]); 11 | 12 | const url = eBay.OAuth2.generateAuthUrl(); 13 | 14 | console.log('Authorize this app by visiting this url:', url); 15 | 16 | const rl = readline.createInterface({ 17 | input: process.stdin, 18 | output: process.stdout, 19 | }); 20 | 21 | rl.question('Enter the code from that page here (from the url query ?code=) : ', async (code: string) => { 22 | rl.close(); 23 | code = decodeURIComponent(code); 24 | console.log('Enter code', code); 25 | const token = await eBay.OAuth2.getToken(code); 26 | console.log('Token: ', token); 27 | eBay.OAuth2.setCredentials(token); 28 | 29 | eBay.sell.fulfillment.getOrder('12-12345-12345').then(order => { 30 | console.log('order', JSON.stringify(order, null, 2)); 31 | }).catch(e => { 32 | console.log('error', {error: e.message}); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /examples/restful/buy/browse.getShoppingCart.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.buy.browse.getShoppingCart().then(cart => { 7 | console.log(cart); 8 | }).catch(e => { 9 | console.log(e); 10 | }); 11 | -------------------------------------------------------------------------------- /examples/restful/buy/browse.search.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.buy.browse.search({ 7 | q: 'shirt', 8 | category_ids: '15724', 9 | aspect_filter: 'categoryId:15724,Color:{Red}' 10 | }) 11 | .then(result => { 12 | console.log(JSON.stringify(result, null, 2)); 13 | }) 14 | .catch(e => { 15 | console.log(e); 16 | }); -------------------------------------------------------------------------------- /examples/restful/buy/items.getItem.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.buy.browse.getItem('v1|382282567190|651094235351') 7 | .then(item => { 8 | console.log(JSON.stringify(item, null, 2)); 9 | }) 10 | .catch(e => { 11 | console.log(e); 12 | }); -------------------------------------------------------------------------------- /examples/restful/buy/marketing.getAlsoBoughtProducts.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | // Check OAuth Scope if this really works for you: https://developer.ebay.com/my/keys 7 | eBay.OAuth2.setScope([ 8 | 'https://api.ebay.com/oauth/api_scope', 9 | 'https://api.ebay.com/oauth/api_scope/buy.marketing' 10 | ]); 11 | 12 | eBay.buy.marketing.getAlsoBoughtByProduct({ 13 | gtin: '8806088687681' 14 | }).then(products => { 15 | console.log(JSON.stringify(products, null, 2)); 16 | }).catch(e => { 17 | console.log(e); 18 | }); 19 | -------------------------------------------------------------------------------- /examples/restful/developer/analytics.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | (async () => { 7 | try { 8 | const rateLimits = await eBay.developer.analytics.getRateLimits(); 9 | console.log(JSON.stringify(rateLimits, null, 2)); 10 | } catch (error) { 11 | console.error(error); 12 | } 13 | })(); 14 | -------------------------------------------------------------------------------- /examples/restful/developer/keyManagement.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | (async () => { 7 | try { 8 | const signingKey = await eBay.developer.keyManagement.createSigningKey('ED25519'); 9 | console.log(JSON.stringify(signingKey, null, 2)); 10 | } catch (error) { 11 | console.error(error); 12 | } 13 | })(); 14 | -------------------------------------------------------------------------------- /examples/restful/postOrder/inquiry.getInquiry.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | (async () => { 7 | try { 8 | const summary = await eBay.postOrder.inquiry.getInquiry('5222222222'); 9 | console.log(JSON.stringify(summary, null, 2)); 10 | } catch (error) { 11 | console.error(error); 12 | } 13 | })(); 14 | -------------------------------------------------------------------------------- /examples/restful/postOrder/return.getReturn.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | (async () => { 7 | try { 8 | const summary = await eBay.postOrder.return.getReturn('5132021997'); 9 | console.log(summary); 10 | } catch (error) { 11 | console.error(error); 12 | } 13 | })(); -------------------------------------------------------------------------------- /examples/restful/sell/account.getPrivileges.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.sell.account.getPrivileges().then(order => { 7 | console.log('privileges', JSON.stringify(order, null, 2)); 8 | }).catch(e => { 9 | console.error(e); 10 | }); 11 | -------------------------------------------------------------------------------- /examples/restful/sell/finances.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.sell.finances.sign.getSellerFundsSummary().then(result => { 7 | console.log('result', JSON.stringify(result, null, 2)); 8 | }).catch(e => { 9 | console.error(JSON.stringify(e, null, 2)); 10 | }); 11 | -------------------------------------------------------------------------------- /examples/restful/sell/fullfillment.getOrder.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.sell.fulfillment.getOrder('11-06241-16499').then(order => { 7 | console.log('order', JSON.stringify(order, null, 2)); 8 | }).catch(e => { 9 | console.error(JSON.stringify(e, null, 2)); 10 | }); 11 | -------------------------------------------------------------------------------- /examples/restful/sell/getOrders.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.OAuth2.setScope([ 7 | 'https://api.ebay.com/oauth/api_scope', 8 | 'https://api.ebay.com/oauth/api_scope/sell.fulfillment', 9 | 'https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly' 10 | ]) 11 | 12 | eBay.sell.fulfillment.getOrders({ 13 | limit: 5 14 | }).then(order => { 15 | console.log('order', JSON.stringify(order, null, 2)); 16 | }).catch(e => { 17 | console.error(JSON.stringify(e, null, 2)); 18 | }); 19 | -------------------------------------------------------------------------------- /examples/restful/sell/metadata.getItemConditionPolicies.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.sell.metadata.getItemConditionPolicies('EBAY_US', 'categoryId:{95672}').then(result => { 7 | console.log('result', JSON.stringify(result, null, 2)); 8 | }).catch(e => { 9 | console.error(JSON.stringify(e, null, 2)); 10 | }); 11 | -------------------------------------------------------------------------------- /examples/traditional/authNAuth.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | // @ts-ignore 3 | import readline from 'readline'; 4 | import eBayApi from '../../src/eBayApi.js'; 5 | 6 | const eBay = eBayApi.fromEnv(); 7 | // DOCS: https://developer.ebay.com/devzone/xml/docs/howto/tokens/gettingtokens.html 8 | 9 | const rl = readline.createInterface({ 10 | input: process.stdin, 11 | output: process.stdout 12 | }); 13 | 14 | eBay.authNAuth.getSessionIdAndAuthUrl().then(({url, sessionId}) => { 15 | console.log('Authorize this app by visiting this url: ', url); 16 | 17 | rl.question('Press Enter after grant access', async () => { 18 | await eBay.authNAuth.obtainToken(sessionId); 19 | 20 | try { 21 | const time = await eBay.trading.GeteBayOfficialTime(); 22 | console.log(time); 23 | } catch (error) { 24 | console.error(error) 25 | } finally { 26 | rl.close(); 27 | } 28 | 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /examples/traditional/clientAlerts.GetPublicAlerts.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../src/eBayApi.js'; 3 | 4 | import {EventType} from '../../src/api/traditional/clientAlerts'; 5 | 6 | const eBay = eBayApi.fromEnv(); 7 | 8 | eBay.clientAlerts.GetPublicAlerts({ 9 | ChannelDescriptor: [ 10 | { 11 | ChannelType: 'Item', 12 | ChannelID: 174028462015, 13 | EventType: [EventType.ItemEnded] 14 | }, 15 | { 16 | ChannelType: 'Item', 17 | ChannelID: 180434053857, 18 | EventType: [EventType.ItemEnded] 19 | } 20 | ] 21 | }).then(result => { 22 | console.log(JSON.stringify(result, null, 2)); 23 | }).catch(e => { 24 | console.log(e); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/traditional/finding.findItemsAdvanced.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | // @ts-ignore 3 | import eBayApi from '../../src/eBayApi.js'; 4 | 5 | const eBay = eBayApi.fromEnv(); 6 | 7 | eBay.finding.findItemsAdvanced({ 8 | itemFilter: [{ 9 | name: 'Seller', 10 | value: 'hendt_de' 11 | }] 12 | }).then(result => { 13 | console.log(JSON.stringify(result, null, 2)); 14 | }).catch(e => { 15 | console.log(e); 16 | }) -------------------------------------------------------------------------------- /examples/traditional/merchandising.getMostWatchedItems.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.merchandising.getMostWatchedItems().then(result => { 7 | console.log(JSON.stringify(result, null, 2)); 8 | }).catch(e => { 9 | console.log(e); 10 | }); 11 | -------------------------------------------------------------------------------- /examples/traditional/shopping.GetSingleItem.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.shopping.GetSingleItem({ 7 | ItemID: '255734197431', 8 | IncludeSelector: 'Details' 9 | }).then(result => { 10 | console.log(JSON.stringify(result, null, 2)); 11 | }).catch(e => { 12 | console.error(e); 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /examples/traditional/shopping.GetUserProfile.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | // @ts-ignore 3 | import eBayApi from '../../src/eBayApi.js'; 4 | 5 | const eBay = eBayApi.fromEnv(); 6 | 7 | (async () => { 8 | const result = await eBay.shopping.GetUserProfile({ 9 | UserID: 'userId', 10 | IncludeSelector: 'Details' 11 | }); 12 | 13 | console.log(result); 14 | })() -------------------------------------------------------------------------------- /examples/traditional/trading.GetAccount.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | eBay.trading.GetAccount(null, { 6 | sign: true 7 | }).then(result => { 8 | console.log(JSON.stringify(result, null, 2)); 9 | }).catch(e => { 10 | console.error(e); 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /examples/traditional/trading.GetMultipleItems.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.shopping.GetMultipleItems({ 7 | ItemID: '256186199138' 8 | }).then(result => { 9 | console.log(JSON.stringify(result, null, 2)); 10 | }).catch(e => { 11 | console.error(e); 12 | }); 13 | 14 | -------------------------------------------------------------------------------- /examples/traditional/trading.GetMyMessages.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.trading.GetMyMessages({ 7 | Folder: 0, 8 | DetailLevel: 'ReturnHeaders' 9 | }).then(result => { 10 | console.log(JSON.stringify(result, null, 2)); 11 | }).catch(e => { 12 | console.error(e); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/traditional/trading.GetMyeBaySelling.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | eBay.trading.GetMyeBaySelling({ 7 | SoldList: { 8 | Include: true, 9 | OrderStatusFilter: 'AwaitingPayment', 10 | Pagination: { 11 | EntriesPerPage: 20, 12 | PageNumber: 1 13 | } 14 | } 15 | }).then(result => { 16 | console.log(JSON.stringify(result, null, 2)); 17 | }).catch(e => { 18 | console.error(e); 19 | }); 20 | -------------------------------------------------------------------------------- /examples/traditional/trading.GeteBayOfficialTime.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import eBayApi from '../../src/eBayApi.js'; 3 | 4 | const eBay = eBayApi.fromEnv(); 5 | 6 | (async () => { 7 | try { 8 | const time = await eBay.trading.GeteBayOfficialTime(); 9 | console.log(time); 10 | } catch (error) { 11 | console.log(error); 12 | } 13 | })(); -------------------------------------------------------------------------------- /examples/traditional/trading.UploadSiteHostedPictures.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-console 2 | import FormData from 'form-data'; 3 | import * as fs from 'fs'; 4 | import * as path from 'path'; 5 | import eBayApi from '../../src/eBayApi.js'; 6 | 7 | const eBay = eBayApi.fromEnv(); 8 | 9 | (async () => { 10 | try { 11 | const image = fs.readFileSync(path.resolve(__dirname, 'upload_ok.png')); 12 | 13 | // const image = fs.readFileSync(path.resolve(__dirname, 'upload_bad_quality.jpg')); 14 | // --> To reduce possible issues with picture display quality, eBay recommends that pictures you upload have a JPEG quality value of 90 or greater. 15 | const response = await eBay.trading.UploadSiteHostedPictures({ 16 | ExtensionInDays: 1, 17 | }, { 18 | hook: (xml: string) => { 19 | const form = new FormData(); 20 | // XML should be always first 21 | form.append('XML Payload', xml, 'payload.xml'); 22 | form.append('dummy', image) 23 | return { 24 | body: form, 25 | headers: form.getHeaders() 26 | } 27 | } 28 | }); 29 | 30 | console.log(response); 31 | } catch (error) { 32 | console.log(JSON.stringify(error, null, 2)); 33 | } 34 | })(); -------------------------------------------------------------------------------- /examples/traditional/upload_bad_quality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendt/ebay-api/f90d063fbca34039549e1edec564bb12bf56a989/examples/traditional/upload_bad_quality.jpg -------------------------------------------------------------------------------- /examples/traditional/upload_ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendt/ebay-api/f90d063fbca34039549e1edec564bb12bf56a989/examples/traditional/upload_ok.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ebay-api", 3 | "author": "Daniil Tomilow", 4 | "version": "9.2.0", 5 | "description": "eBay API for Node and Browser", 6 | "type": "module", 7 | "main": "./lib/index.js", 8 | "types": "./lib/index.d.ts", 9 | "module": "./dist/eBayApi.js", 10 | "browser": "./lib/ebay-api.min.js", 11 | "browser:esm": "./dist/ebay-api.min.mjs", 12 | "exports": { 13 | ".": { 14 | "require": { 15 | "types": "./lib/index.d.ts", 16 | "default": "./lib/index.js" 17 | }, 18 | "import": { 19 | "types": "./dist/eBayApi.d.ts", 20 | "default": "./dist/eBayApi.js" 21 | } 22 | }, 23 | "./*": { 24 | "require": { 25 | "types": "./lib/*", 26 | "default": "./lib/*" 27 | }, 28 | "import": { 29 | "types": "./dist/*", 30 | "default": "./dist/*" 31 | } 32 | }, 33 | "./lib/*": { 34 | "require": { 35 | "types": "./lib/*", 36 | "default": "./lib/*" 37 | }, 38 | "import": { 39 | "types": "./dist/*", 40 | "default": "./dist/*" 41 | } 42 | }, 43 | "./lib/enums": { 44 | "require": { 45 | "types": "./lib/enums/index.d.ts", 46 | "default": "./lib/enums/index.js" 47 | }, 48 | "import": { 49 | "types": "./dist/enums/index.d.ts", 50 | "default": "./dist/enums/index.js" 51 | } 52 | }, 53 | "./lib/errors": { 54 | "require": { 55 | "types": "./lib/errors/index.d.ts", 56 | "default": "./lib/errors/index.js" 57 | }, 58 | "import": { 59 | "types": "./dist/errors/index.d.ts", 60 | "default": "./dist/errors/index.js" 61 | } 62 | }, 63 | "./lib/types": { 64 | "require": { 65 | "types": "./lib/types/index.d.ts", 66 | "default": "./lib/types/index.js" 67 | }, 68 | "import": { 69 | "types": "./dist/types/index.d.ts", 70 | "default": "./dist/types/index.js" 71 | } 72 | }, 73 | "./package.json": "./package.json" 74 | }, 75 | "scripts": { 76 | "cjs:fix": "node -e \"require('fs').writeFileSync('lib/package.json', JSON.stringify({type: 'commonjs'}, null, 2))\"", 77 | "build": "rimraf lib dist && tsc && tsc --project tsconfig.cjs.json && rollup -c --bundleConfigAsCjs && npm run cjs:fix", 78 | "prepare": "npm run build", 79 | "tslint": "tslint -c tslint.json '{src,test,examples}/**/*.ts'", 80 | "test": "mocha --reporter=dot", 81 | "report": "c8 npm run test", 82 | "report:summary": "c8 --reporter=lcov --reporter=text-summary npm run test", 83 | "prerelease": "npm run tslint && npm run test && npm run build", 84 | "release": "standard-version", 85 | "rc": "npm run release -- --prerelease RC && git push --follow-tags origin next", 86 | "gen-openapi": "npx openapi-typescript \"specs/*.json\" --output src/types/restful/" 87 | }, 88 | "dependencies": { 89 | "axios": "^1.6.8", 90 | "debug": "^4.3.4", 91 | "fast-xml-parser": "^4.4.0", 92 | "qs": "^6.11.0" 93 | }, 94 | "devDependencies": { 95 | "@rollup/plugin-commonjs": "^23.0.4", 96 | "@rollup/plugin-json": "^6.1.0", 97 | "@rollup/plugin-node-resolve": "^15.0.1", 98 | "@rollup/plugin-terser": "^0.2.0", 99 | "@rollup/plugin-virtual": "^3.0.1", 100 | "@types/chai": "^4.3.4", 101 | "@types/debug": "^4.1.7", 102 | "@types/mocha": "^10.0.1", 103 | "@types/node": "^18.11.10", 104 | "@types/qs": "^6.9.7", 105 | "@types/sinon": "^10.0.13", 106 | "c8": "^7.11.3", 107 | "chai": "^4.3.7", 108 | "form-data": "^4.0.0", 109 | "mocha": "^10.1.0", 110 | "openapi-typescript": "^6.3.4", 111 | "readline": "^1.3.0", 112 | "rimraf": "^5.0.5", 113 | "rollup": "^3.7.0", 114 | "rollup-plugin-bundle-size": "^1.0.3", 115 | "sinon": "^17.0.1", 116 | "standard-version": "^9.0.0", 117 | "ts-node": "^10.9.2", 118 | "tslint": "^6.1.0", 119 | "typescript": "^5.1.6" 120 | }, 121 | "repository": { 122 | "type": "git", 123 | "url": "git+ssh://git@github.com/hendt/ebay-api.git" 124 | }, 125 | "keywords": [ 126 | "api", 127 | "eBay", 128 | "Shopping", 129 | "Searching", 130 | "products", 131 | "Browse", 132 | "Category", 133 | "FindingApi", 134 | "node-api", 135 | "eBay Traditional API", 136 | "eBay Full API", 137 | "eBay Account API", 138 | "eBay Inventory API", 139 | "eBay Compliance API", 140 | "eBay Marketing API", 141 | "eBay Fulfillment API", 142 | "eBay Marketing API", 143 | "eBay Analytics API", 144 | "eBay Metadata API", 145 | "eBay Browse API", 146 | "eBay Feed API", 147 | "eBay Order API", 148 | "eBay Marketplace Insights API", 149 | "eBay Taxonomy API", 150 | "eBay Catalog API", 151 | "eBay Translation API", 152 | "eBay Analytics API", 153 | "eBay Finding API", 154 | "eBay Shopping API", 155 | "eBay Merchandising API", 156 | "eBay Trading API", 157 | "eBay Product Services", 158 | "eBay Client Alerts API", 159 | "ebay-node", 160 | "eBay-node-api", 161 | "eBay-node-client", 162 | "eBay-typescript", 163 | "eBay-await", 164 | "eBay-async", 165 | "eBay-promises", 166 | "eBay-products", 167 | "eBay-sellers", 168 | "eBay-orders", 169 | "eBay-finances", 170 | "eBay-inventory", 171 | "eBay-shipment", 172 | "eBay-api", 173 | "eBay-sdk", 174 | "eBay-client", 175 | "eBay-node-api", 176 | "eBay-node" 177 | ], 178 | "license": "MIT", 179 | "bugs": { 180 | "url": "https://github.com/hendt/ebay-api/issues" 181 | }, 182 | "homepage": "https://github.com/hendt/ebay-api#readme", 183 | "directories": { 184 | "test": "test" 185 | }, 186 | "engines": { 187 | "node": ">= 14.0.0" 188 | }, 189 | "files": [ 190 | "lib", 191 | "dist" 192 | ] 193 | } 194 | -------------------------------------------------------------------------------- /proxy/worker.js: -------------------------------------------------------------------------------- 1 | /* 2 | CORS Anywhere as a Cloudflare Worker 3 | */ 4 | 5 | const blacklist = []; // regexp for blacklisted urls 6 | const whitelist = [".*"]; // regexp for whitelisted origins 7 | const whitelistFetch = ["hendt.de", "ebay.com/"]; // regexp for whitelisted fetch url 8 | const logUrl = ''; // e.g. from https://requestbin.com 9 | 10 | const responseBody = ` 11 | HENDT eBay API Proxy
12 | Usage: https://ebay.hendt.workers.dev/https://hendt.de
or 13 | https://ebay.hendt.workers.dev/?url=https%3A%2F%2Fhendt.de 14 | eBay API
\n 15 | `; 16 | 17 | function isListed(uri, listing) { 18 | let ret = false; 19 | if (typeof uri == "string") { 20 | listing.forEach((m) => { 21 | if (uri.match(m) != null) ret = true; 22 | }); 23 | } else { // decide what to do when Origin is null 24 | ret = true; // true accepts null origins false rejects them. 25 | } 26 | return ret; 27 | } 28 | 29 | function fixHeaders(headers, {isOptions, origin, requestMethod, accessControl}) { 30 | headers.set("Access-Control-Allow-Origin", origin); 31 | 32 | if (isOptions) { 33 | headers.set("Access-Control-Allow-Methods", requestMethod); 34 | if (accessControl) { 35 | headers.set("Access-Control-Allow-Headers", accessControl); 36 | } 37 | 38 | headers.delete("X-Content-Type-Options"); 39 | } 40 | return headers; 41 | } 42 | 43 | const log = (data) => { 44 | if (!logUrl) { 45 | console.log(JSON.stringify(data, null, 2)); 46 | return Promise.resolve(); 47 | } 48 | return fetch(logUrl, { 49 | method: 'POST', 50 | headers: { 51 | 'Accept': 'application/json', 52 | 'Content-Type': 'application/json' 53 | }, 54 | body: JSON.stringify(data) 55 | }); 56 | }; 57 | 58 | const handleRequest = async (event) => { 59 | try { 60 | const isOptions = (event.request.method === "OPTIONS"); 61 | const origin = event.request.headers.get("Origin"); 62 | const originUrl = new URL(event.request.url); 63 | let fetchUrl = originUrl.pathname.substr(1); 64 | 65 | if (fetchUrl) { 66 | fetchUrl = fetchUrl 67 | .replace('https:/', 'https://') 68 | .replace('http:/', 'http://'); 69 | fetchUrl = decodeURIComponent(fetchUrl) + originUrl.search; 70 | } else { 71 | const urlParams = new URLSearchParams(originUrl.search); 72 | fetchUrl = urlParams.get('url'); 73 | } 74 | 75 | if (!fetchUrl) { 76 | return new Response(responseBody, 77 | { 78 | status: 403, 79 | statusText: 'Forbidden', 80 | headers: { 81 | "Content-Type": "text/html" 82 | } 83 | }); 84 | } 85 | 86 | if (!isListed(fetchUrl, whitelistFetch) || isListed(fetchUrl, blacklist) || !isListed(origin, whitelist)) { 87 | return new Response(responseBody, 88 | { 89 | status: 403, 90 | statusText: 'Forbidden', 91 | headers: { 92 | "Content-Type": "text/html" 93 | } 94 | }); 95 | } 96 | 97 | const accessControl = event.request.headers.get("access-control-request-headers"); 98 | const requestMethod = event.request.headers.get("access-control-request-method"); 99 | 100 | const recHeaders = {}; 101 | for (let pair of event.request.headers.entries()) { 102 | const key = pair[0]; 103 | if ((key.match("^origin") == null) && 104 | (key.match("eferer") == null) && 105 | (key.match("^cf-") == null) && 106 | (key.match("^x-forw") == null) && 107 | (key.match("^x-cors-headers") == null) 108 | ) { 109 | recHeaders[key] = pair[1]; 110 | } 111 | } 112 | 113 | try { 114 | const xHeaders = JSON.parse(event.request.headers.get("x-cors-headers")); 115 | Object.entries(xHeaders).forEach((c) => recHeaders[c[0]] = c[1]); 116 | } catch (e) { 117 | } 118 | 119 | try { 120 | event.waitUntil(log({ 121 | type: 'newReq', 122 | fetchUrl, 123 | headers: recHeaders 124 | })); 125 | 126 | const newReq = new Request(event.request, { 127 | "headers": recHeaders 128 | }); 129 | 130 | const response = await fetch(encodeURI(fetchUrl), newReq); 131 | let responseHeaders = new Headers(response.headers); 132 | 133 | const corsHeaders = []; 134 | const receivedHeaders = {}; 135 | 136 | for (let pair of response.headers.entries()) { 137 | corsHeaders.push(pair[0]); 138 | receivedHeaders[pair[0]] = pair[1]; 139 | } 140 | 141 | corsHeaders.push("cors-received-headers"); 142 | responseHeaders = fixHeaders(responseHeaders, {isOptions, origin, requestMethod, accessControl}); 143 | responseHeaders.set("Access-Control-Expose-Headers", corsHeaders.join(",")); 144 | responseHeaders.set("cors-received-headers", JSON.stringify(receivedHeaders)); 145 | 146 | if (isOptions) { 147 | event.waitUntil(log({ 148 | type: 'options', 149 | fetchUrl, 150 | headers: [...responseHeaders] 151 | })); 152 | return new Response(null, { 153 | headers: responseHeaders, 154 | status: 200, 155 | statusText: "OK" 156 | }); 157 | } 158 | 159 | const init = { 160 | headers: responseHeaders, 161 | status: response.status, 162 | statusText: response.statusText 163 | }; 164 | 165 | event.waitUntil(log({ 166 | type: 'response', 167 | fetchUrl, 168 | headers: [...responseHeaders] 169 | })); 170 | 171 | const body = await response.arrayBuffer(); 172 | return new Response(body, init); 173 | } catch (e) { 174 | event.waitUntil(log({ 175 | type: 'error', 176 | fetchUrl, 177 | message: e.message, 178 | error: e.stack || e 179 | })); 180 | 181 | return new Response(null, 182 | { 183 | status: 400, 184 | statusText: 'Bad request', 185 | headers: { 186 | "Content-Type": "text/html" 187 | } 188 | }); 189 | } 190 | } catch (err) { 191 | // Return the error stack as the response 192 | return new Response(err.stack || err.message, { 193 | status: 400, 194 | statusText: 'Bad Request', 195 | headers: { 196 | "Content-Type": "text/html" 197 | } 198 | }); 199 | } 200 | }; 201 | 202 | addEventListener("fetch", async event => { 203 | event.passThroughOnException(); 204 | event.respondWith(handleRequest(event)); 205 | }); 206 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import terser from '@rollup/plugin-terser'; 2 | import resolve from '@rollup/plugin-node-resolve'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import json from '@rollup/plugin-json'; 5 | import bundleSize from 'rollup-plugin-bundle-size'; 6 | import virtual from '@rollup/plugin-virtual'; 7 | 8 | const pkg = require('./package.json'); 9 | 10 | const plugins = [ 11 | virtual({ 12 | crypto: `export function createHash() { throw Error('crypto.createHash is not supported in browser.'); }; export function sign() { throw Error('crypto.sign is not supported in browser.'); };`, 13 | }), 14 | bundleSize(), 15 | resolve({ 16 | browser: true 17 | }), 18 | json(), 19 | commonjs(), 20 | terser({ 21 | keep_fnames: true 22 | }), 23 | ] 24 | 25 | export default [{ 26 | input: './lib/index.js', 27 | output: [ 28 | { 29 | file: pkg.browser, 30 | format: 'umd', 31 | name: 'eBayApi', 32 | exports: 'default', 33 | sourcemap: false, 34 | }, 35 | ], 36 | plugins 37 | }, { 38 | input: './dist/eBayApi.js', 39 | output: [ 40 | { 41 | file: pkg['browser:esm'], 42 | format: 'esm', 43 | exports: 'named' 44 | }, 45 | ], 46 | context: 'window', 47 | plugins 48 | }] 49 | -------------------------------------------------------------------------------- /scripts/update-readme-release.cjs: -------------------------------------------------------------------------------- 1 | const regex = /`(v\d+\.\d+\.\d+)` is the latest release\./ 2 | 3 | module.exports.readVersion = function(contents) { 4 | return contents.match(regex)[1] 5 | } 6 | 7 | module.exports.writeVersion = function(contents, version) { 8 | return contents.replace(regex, "`v" + version + "` is the latest release.") 9 | } 10 | -------------------------------------------------------------------------------- /specs/cancellation_oas3.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.0", 3 | "info": { 4 | "version": "0.1", 5 | "title": "Post Order Cancellation API", 6 | "description": "Custom Cancellation API OAS definition." 7 | }, 8 | "servers": [ 9 | { 10 | "url": "https://api.ebay.com{basePath}", 11 | "description": "Cancellation", 12 | "variables": { 13 | "basePath": { 14 | "default": "/post-order/v2" 15 | } 16 | } 17 | } 18 | ], 19 | "paths": { 20 | "/cancellation/{cancelId}/approve": { 21 | "post": { 22 | "description": "Seller approves a cancellation request", 23 | "operationId": "approveCancellationRequest", 24 | "parameters": [ 25 | { 26 | "name": "cancelId", 27 | "in": "path", 28 | "description": "The unique eBay-assigned identifier of the cancellation request to be approved.", 29 | "required": true, 30 | "schema": { 31 | "type": "string" 32 | } 33 | } 34 | ], 35 | "responses": { 36 | "200": { 37 | "description": "OK" 38 | } 39 | } 40 | } 41 | }, 42 | "/cancellation/check_eligibility": { 43 | "post": { 44 | "description": "Check the eligibility of an order cancellation", 45 | "operationId": "checkCancellationEligibility", 46 | "responses": { 47 | "200": { 48 | "description": "OK" 49 | } 50 | } 51 | } 52 | }, 53 | "/cancellation/{cancelId}/confirm": { 54 | "post": { 55 | "description": "Buyer confirms the refund from a cancellation was received", 56 | "operationId": "confirmRefundReceived", 57 | "parameters": [ 58 | { 59 | "name": "cancelId", 60 | "in": "path", 61 | "description": "The unique eBay-assigned identifier of the cancellation request to be approved.", 62 | "required": true, 63 | "schema": { 64 | "type": "string" 65 | } 66 | } 67 | ], 68 | "responses": { 69 | "200": { 70 | "description": "OK" 71 | } 72 | } 73 | } 74 | }, 75 | "/cancellation": { 76 | "post": { 77 | "description": "Request or perform an order cancellation", 78 | "operationId": "createCancellation", 79 | "responses": { 80 | "200": { 81 | "description": "OK" 82 | } 83 | } 84 | } 85 | }, 86 | "/cancellation/{cancelId}": { 87 | "get": { 88 | "description": "Request or perform an order cancellation", 89 | "operationId": "getCancellation", 90 | "parameters": [ 91 | { 92 | "name": "cancelId", 93 | "in": "path", 94 | "description": "The unique eBay-assigned identifier of the cancellation request to be approved.", 95 | "required": true, 96 | "schema": { 97 | "type": "string" 98 | } 99 | } 100 | ], 101 | "responses": { 102 | "200": { 103 | "description": "OK" 104 | } 105 | } 106 | } 107 | }, 108 | "/cancellation/{cancelId}/reject": { 109 | "post": { 110 | "description": "Seller rejects a cancellation request", 111 | "operationId": "rejectCancellationRequest", 112 | "parameters": [ 113 | { 114 | "name": "cancelId", 115 | "in": "path", 116 | "description": "The unique eBay-assigned identifier of the cancellation request to be approved.", 117 | "required": true, 118 | "schema": { 119 | "type": "string" 120 | } 121 | } 122 | ], 123 | "responses": { 124 | "200": { 125 | "description": "OK" 126 | } 127 | } 128 | } 129 | }, 130 | "/cancellation/search": { 131 | "get": { 132 | "description": "Search for cancellations", 133 | "operationId": "search", 134 | "responses": { 135 | "200": { 136 | "description": "OK" 137 | } 138 | } 139 | } 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /specs/case_oas3.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.o", 3 | "info": { 4 | "version": "0.1", 5 | "title": "Post Order Case Management API", 6 | "description": "Custom Case Management API OAS definition." 7 | }, 8 | "servers": [ 9 | { 10 | "url": "https://api.ebay.com{basePath}", 11 | "description": "Case management", 12 | "variables": { 13 | "basePath": { 14 | "default": "/post-order/v2" 15 | } 16 | } 17 | } 18 | ], 19 | "paths": { 20 | "/casemanagement/{caseId}/appeal": { 21 | "post": { 22 | "description": "Buyer or seller appeals a case decision", 23 | "operationId": "appealCaseDecision", 24 | "parameters": [ 25 | { 26 | "name": "caseId", 27 | "in": "path", 28 | "description": "The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI.", 29 | "required": true, 30 | "schema": { 31 | "type": "string" 32 | } 33 | } 34 | ], 35 | "responses": { 36 | "200": { 37 | "description": "OK" 38 | } 39 | } 40 | } 41 | }, 42 | "/casemanagement/{caseId}/close": { 43 | "post": { 44 | "description": "Buyer closes a case", 45 | "operationId": "closeCase", 46 | "parameters": [ 47 | { 48 | "name": "caseId", 49 | "in": "path", 50 | "description": "The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI.", 51 | "required": true, 52 | "schema": { 53 | "type": "string" 54 | } 55 | } 56 | ], 57 | "responses": { 58 | "200": { 59 | "description": "OK" 60 | } 61 | } 62 | } 63 | }, 64 | "/casemanagement/{caseId}": { 65 | "get": { 66 | "description": "Retrieve the details related to a specific case", 67 | "operationId": "getCase", 68 | "parameters": [ 69 | { 70 | "name": "caseId", 71 | "in": "path", 72 | "description": "The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI.", 73 | "required": true, 74 | "schema": { 75 | "type": "string" 76 | } 77 | } 78 | ], 79 | "responses": { 80 | "200": { 81 | "description": "OK" 82 | } 83 | } 84 | } 85 | }, 86 | "/casemanagement/{caseId}/issue_refund": { 87 | "post": { 88 | "description": "Seller issues a refund for a case", 89 | "operationId": "issueCaseRefund", 90 | "parameters": [ 91 | { 92 | "name": "caseId", 93 | "in": "path", 94 | "description": "The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI.", 95 | "required": true, 96 | "schema": { 97 | "type": "string" 98 | } 99 | } 100 | ], 101 | "responses": { 102 | "200": { 103 | "description": "OK" 104 | } 105 | } 106 | } 107 | }, 108 | "/casemanagement/{caseId}/provide_shipment_info": { 109 | "post": { 110 | "description": "Buyer provides return shipment information", 111 | "operationId": "provideReturnShipmentInfo", 112 | "parameters": [ 113 | { 114 | "name": "caseId", 115 | "in": "path", 116 | "description": "The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI.", 117 | "required": true, 118 | "schema": { 119 | "type": "string" 120 | } 121 | }, 122 | { 123 | "name": "shippingCarrierName", 124 | "in": "body", 125 | "required": true, 126 | "schema": { 127 | "type": "string" 128 | } 129 | }, 130 | { 131 | "name": "trackingNumber", 132 | "in": "body", 133 | "required": true, 134 | "schema": { 135 | "type": "string" 136 | } 137 | } 138 | ], 139 | "responses": { 140 | "200": { 141 | "description": "OK" 142 | } 143 | } 144 | } 145 | }, 146 | "/casemanagement/{caseId}/provide_return_address": { 147 | "post": { 148 | "description": "Seller provides a return address to the buyer", 149 | "operationId": "providesReturnAddress", 150 | "parameters": [ 151 | { 152 | "name": "caseId", 153 | "in": "path", 154 | "description": "The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI.", 155 | "required": true, 156 | "schema": { 157 | "type": "string" 158 | } 159 | } 160 | ], 161 | "responses": { 162 | "200": { 163 | "description": "OK" 164 | } 165 | } 166 | } 167 | }, 168 | "/casemanagement/search": { 169 | "get": { 170 | "description": "This call is used to search for cases using multiple filter types.", 171 | "operationId": "search", 172 | "responses": { 173 | "200": { 174 | "description": "OK" 175 | } 176 | } 177 | } 178 | } 179 | } 180 | } -------------------------------------------------------------------------------- /src/api/apiFactory.ts: -------------------------------------------------------------------------------- 1 | import {ClientAlerts, Finding, Merchandising, Shopping, Trading} from '../types/index.js'; 2 | import Api from './index.js'; 3 | import { 4 | Browse, 5 | Buy, 6 | Deal, 7 | Feed, 8 | Marketing as BuyMarketing, 9 | MarketplaceInsights, 10 | Offer, 11 | Order 12 | } from './restful/buy/index.js'; 13 | import { 14 | Catalog, 15 | Charity, 16 | Commerce, 17 | Identity, 18 | Media, 19 | Notification, 20 | Taxonomy, 21 | Translation 22 | } from './restful/commerce/index.js'; 23 | import {Analytics as DeveloperAnalytics, Developer, KeyManagement} from './restful/developer/index.js'; 24 | import RestfulApi, {IRestful} from './restful/index.js'; 25 | import {Cancellation, Case, Inquiry, PostOrder, Return,} from './restful/postOrder/index.js'; 26 | import { 27 | AccountV1, 28 | AccountV2, 29 | Analytics as SellAnalytics, 30 | Compliance, 31 | Feed as SellFeed, 32 | Finances, 33 | Fulfillment, 34 | Inventory, 35 | Listing, 36 | Logistics, 37 | Marketing as SellMarketing, 38 | Metadata, 39 | Negotiation, 40 | Recommendation, 41 | Sell 42 | } from './restful/sell/index.js'; 43 | import Traditional from './traditional/index.js'; 44 | 45 | /** 46 | * Factory class to create RESTFul API or Traditional API. 47 | */ 48 | export default class ApiFactory extends Api { 49 | private _traditional?: Traditional; 50 | private _restful: any = {}; 51 | 52 | public createBuyApi(): Buy { 53 | return { 54 | browse: this.createRestfulApi(Browse), 55 | feed: this.createRestfulApi(Feed), 56 | marketing: this.createRestfulApi(BuyMarketing), 57 | offer: this.createRestfulApi(Offer), 58 | order: this.createRestfulApi(Order), 59 | deal: this.createRestfulApi(Deal), 60 | marketplaceInsights: this.createRestfulApi(MarketplaceInsights), 61 | }; 62 | } 63 | 64 | public createCommerceApi(): Commerce { 65 | return { 66 | catalog: this.createRestfulApi(Catalog), 67 | charity: this.createRestfulApi(Charity), 68 | identity: this.createRestfulApi(Identity), 69 | notification: this.createRestfulApi(Notification), 70 | media: this.createRestfulApi(Media), 71 | translation: this.createRestfulApi(Translation), 72 | taxonomy: this.createRestfulApi(Taxonomy), 73 | }; 74 | } 75 | 76 | public createDeveloperApi(): Developer { 77 | return { 78 | analytics: this.createRestfulApi(DeveloperAnalytics), 79 | keyManagement: this.createRestfulApi(KeyManagement), 80 | }; 81 | } 82 | 83 | public createPostOrderApi(): PostOrder { 84 | return { 85 | cancellation: this.createRestfulApi(Cancellation), 86 | case: this.createRestfulApi(Case), 87 | inquiry: this.createRestfulApi(Inquiry), 88 | return: this.createRestfulApi(Return), 89 | }; 90 | } 91 | 92 | public createSellApi(): Sell { 93 | return { 94 | account: this.createRestfulApi(AccountV1), 95 | accountV2: this.createRestfulApi(AccountV2), 96 | analytics: this.createRestfulApi(SellAnalytics), 97 | compliance: this.createRestfulApi(Compliance), 98 | fulfillment: this.createRestfulApi(Fulfillment), 99 | inventory: this.createRestfulApi(Inventory), 100 | marketing: this.createRestfulApi(SellMarketing), 101 | metadata: this.createRestfulApi(Metadata), 102 | recommendation: this.createRestfulApi(Recommendation), 103 | finances: this.createRestfulApi(Finances), 104 | feed: this.createRestfulApi(SellFeed), 105 | logistics: this.createRestfulApi(Logistics), 106 | negotiation: this.createRestfulApi(Negotiation), 107 | listing: this.createRestfulApi(Listing), 108 | }; 109 | } 110 | 111 | get traditional() { 112 | if (this._traditional) { 113 | return this._traditional; 114 | } 115 | 116 | return (this._traditional = new Traditional(this.config, this.req, this.auth)); 117 | } 118 | 119 | public createTradingApi(): Trading { 120 | return this.traditional.createTradingApi(); 121 | } 122 | 123 | public createShoppingApi(): Shopping { 124 | return this.traditional.createShoppingApi(); 125 | } 126 | 127 | public createFindingApi(): Finding { 128 | return this.traditional.createFindingApi(); 129 | } 130 | 131 | public createClientAlertsApi(): ClientAlerts { 132 | return this.traditional.createClientAlertsApi(); 133 | } 134 | 135 | public createMerchandisingApi(): Merchandising { 136 | return this.traditional.createMerchandisingApi(); 137 | } 138 | 139 | // tslint:disable-next-line:variable-name 140 | private createRestfulApi(RestfulApiClass: IRestful): T { 141 | const id = RestfulApiClass.id; 142 | return ( 143 | this._restful[id] || (this._restful[id] = new RestfulApiClass(this.config, this.req, this.auth)) 144 | ); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/api/base.ts: -------------------------------------------------------------------------------- 1 | import {AxiosRequest, IEBayApiRequest} from '../request.js'; 2 | import {AppConfig} from '../types/index.js'; 3 | 4 | /** 5 | * Abstract superclass. 6 | */ 7 | export default abstract class Base { 8 | protected constructor(public readonly config: AppConfig, public readonly req: IEBayApiRequest = new AxiosRequest(config.axiosConfig)) { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/api/digitalSignature.ts: -------------------------------------------------------------------------------- 1 | import {createHash, sign} from 'crypto'; 2 | import {EBayError} from '../errors/index.js'; 3 | import {Cipher, Headers} from '../types/index.js'; 4 | 5 | const beginPrivateKey = '-----BEGIN PRIVATE KEY-----'; 6 | const endPrivateKey = '-----END PRIVATE KEY-----'; 7 | 8 | // based on https://github.com/ebay/digital-signature-nodejs-sdk 9 | 10 | /** 11 | * Returns the current UNIX timestamp. 12 | * 13 | * @returns {number} The unix timestamp. 14 | */ 15 | export const getUnixTimestamp = (): number => Math.floor(Date.now() / 1000); 16 | 17 | const getSignatureParams = (payload: any) => [ 18 | ...payload ? ['content-digest'] : [], 19 | 'x-ebay-signature-key', 20 | '@method', 21 | '@path', 22 | '@authority' 23 | ]; 24 | 25 | const getSignatureParamsValue = (payload: any) => getSignatureParams(payload).map(param => `"${param}"`).join(' '); 26 | 27 | /** 28 | * Generates the 'Content-Digest' header value for the input payload. 29 | * 30 | * @param {any} payload The request payload. 31 | * @param {string} cipher The algorithm used to calculate the digest. 32 | * @returns {string} contentDigest The 'Content-Digest' header value. 33 | */ 34 | export const generateContentDigestValue = (payload: unknown, cipher: Cipher = 'sha256'): string => { 35 | const payloadBuffer: Buffer = Buffer.from(typeof payload === 'string' ? payload : JSON.stringify(payload)); 36 | 37 | const hash = createHash(cipher).update(payloadBuffer).digest('base64'); 38 | const algo: string = cipher === 'sha512' ? 'sha-512' : 'sha-256'; 39 | return `${algo}=:${hash}:`; 40 | }; 41 | 42 | export type SignatureComponents = { 43 | method: string 44 | authority: string // the host 45 | path: string 46 | } 47 | 48 | /** 49 | * Generates the base string. 50 | * 51 | * @param {any} headers The HTTP request headers. 52 | * @param {SignatureComponents} signatureComponents The config. 53 | * @param {any} payload The payload. 54 | * @param {number} timestamp The timestamp. 55 | * @returns {string} payload The base string. 56 | */ 57 | export function generateBaseString(headers: Headers, signatureComponents: SignatureComponents, payload: any, timestamp = getUnixTimestamp()): string { 58 | try { 59 | let baseString: string = ''; 60 | const signatureParams: string[] = getSignatureParams(payload); 61 | 62 | signatureParams.forEach(param => { 63 | baseString += `"${param.toLowerCase()}": `; 64 | 65 | if (param.startsWith('@')) { 66 | switch (param.toLowerCase()) { 67 | case '@method': 68 | baseString += signatureComponents.method; 69 | break; 70 | case '@authority': 71 | baseString += signatureComponents.authority; 72 | break; 73 | case '@path': 74 | baseString += signatureComponents.path; 75 | break; 76 | default: 77 | throw new Error('Unknown pseudo header ' + param); 78 | } 79 | } else { 80 | if (!headers[param]) { 81 | throw new Error('Header ' + param + ' not included in message'); 82 | } 83 | baseString += headers[param]; 84 | } 85 | 86 | baseString += '\n'; 87 | }); 88 | 89 | baseString += `"@signature-params": (${getSignatureParamsValue(payload)});created=${timestamp}`; 90 | 91 | return baseString; 92 | } catch (error: any) { 93 | throw new EBayError(`Error calculating signature base: ${error.message}`); 94 | } 95 | } 96 | 97 | /** 98 | * Generates the Signature-Input header value for the input payload. 99 | * 100 | * @param {any} payload The input config. 101 | * @param {number} timestamp The timestamp. 102 | * @returns {string} the 'Signature-Input' header value. 103 | */ 104 | export const generateSignatureInput = (payload: any, timestamp = getUnixTimestamp()): string => `sig1=(${getSignatureParamsValue(payload)});created=${timestamp}`; 105 | 106 | /** 107 | * Generates the 'Signature' header. 108 | * 109 | * @param {any} headers The HTTP headers. 110 | * @param {string} privateKey The HTTP headers. 111 | * @param {SignatureComponents} signatureComponents The signature components 112 | * @param {any} payload The payload 113 | * @param {number} timestamp The payload 114 | * @returns {string} the signature header value. 115 | */ 116 | export function generateSignature( 117 | headers: any, 118 | privateKey: string, 119 | signatureComponents: SignatureComponents, 120 | payload: any, 121 | timestamp = getUnixTimestamp() 122 | ): string { 123 | const baseString = generateBaseString(headers, signatureComponents, payload, timestamp); 124 | 125 | privateKey = privateKey.trim(); 126 | if (!privateKey.startsWith(beginPrivateKey)) { 127 | privateKey = beginPrivateKey + '\n' + privateKey + '\n' + endPrivateKey; 128 | } 129 | 130 | const signatureBuffer = sign( 131 | undefined, // If algorithm is undefined, then it is dependent upon the private key type. 132 | Buffer.from(baseString), 133 | privateKey 134 | ); 135 | 136 | const signature = signatureBuffer.toString('base64'); 137 | return `sig1=:${signature}:`; 138 | } 139 | 140 | -------------------------------------------------------------------------------- /src/api/index.ts: -------------------------------------------------------------------------------- 1 | import Auth from '../auth/index.js'; 2 | import {IEBayApiRequest} from '../request.js'; 3 | import {AppConfig} from '../types/index.js'; 4 | import Base from './base.js'; 5 | import { 6 | generateContentDigestValue, 7 | generateSignature, 8 | generateSignatureInput, 9 | getUnixTimestamp, 10 | SignatureComponents 11 | } from './digitalSignature.js'; 12 | 13 | /** 14 | * Superclass with Auth container. 15 | */ 16 | export default abstract class Api extends Base { 17 | public readonly auth: Auth; 18 | 19 | constructor( 20 | config: AppConfig, 21 | req?: IEBayApiRequest, 22 | auth?: Auth 23 | ) { 24 | super(config, req); 25 | this.auth = auth || new Auth(this.config, this.req); 26 | } 27 | 28 | getDigitalSignatureHeaders(signatureComponents: SignatureComponents, payload: any) { 29 | if (!this.config.signature) { 30 | return {}; 31 | } 32 | 33 | const timestamp = getUnixTimestamp() 34 | 35 | const digitalSignatureHeaders = { 36 | 'x-ebay-enforce-signature': true, // enable digital signature validation 37 | 'x-ebay-signature-key': this.config.signature.jwe, // always contains JWE 38 | ...payload ? { 39 | 'content-digest': generateContentDigestValue(payload, this.config.signature.cipher ?? 'sha256') 40 | } : {}, 41 | 'signature-input': generateSignatureInput(payload, timestamp) 42 | }; 43 | 44 | return { 45 | ...digitalSignatureHeaders, 46 | 'signature': generateSignature(digitalSignatureHeaders, this.config.signature.privateKey, signatureComponents, payload, timestamp) 47 | }; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/api/restful/buy/browse/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AddCartItemInput, 3 | BuyBrowseGetItemsParams, 4 | BuyBrowseItemByLegacyIdParams, 5 | BuyBrowseSearchByImageParams, 6 | BuyBrowseSearchParams, 7 | CompatibilityPayload, 8 | RemoveCartItemInput, 9 | SearchByImageRequest, 10 | UpdateCartItemInput 11 | } from '../../../../types/index.js'; 12 | import {operations} from '../../../../types/restful/specs/buy_browse_v1_oas3.js'; 13 | import Restful, {OpenApi} from '../../index.js'; 14 | 15 | /** 16 | * The Browse API has the following resources: item_summary: Lets shoppers search for specific items by keyword, GTIN, 17 | * category, charity, product, or item aspects and refine the results by using filters, such as aspects, compatibility, 18 | * and fields values. 19 | */ 20 | export default class Browse extends Restful implements OpenApi { 21 | 22 | static id = 'Browse'; 23 | 24 | get basePath() { 25 | return '/buy/browse/v1'; 26 | } 27 | 28 | // 29 | // Item 30 | // Client Credentials: https://api.ebay.com/oauth/api_scope 31 | // 32 | 33 | /** 34 | * This method searches for eBay items by various query parameters and retrieves summaries of the items. 35 | * 36 | * @param {BrowseSearchParams} params 37 | */ 38 | public search(params: BuyBrowseSearchParams) { 39 | return this.get(`/item_summary/search`, { 40 | params 41 | }); 42 | } 43 | 44 | /** 45 | * This is an Experimental method. This method searches for eBay items based on a image and retrieves summaries of 46 | * the items. 47 | * 48 | * @param {params} params 49 | * @param {Object} body The container for the image information fields. 50 | */ 51 | public searchByImage(params: BuyBrowseSearchByImageParams, body?: SearchByImageRequest) { 52 | return this.post(`/item_summary/search_by_image`, body, { 53 | params 54 | }); 55 | } 56 | 57 | /** 58 | * This method retrieves the details of specific items that the buyer needs to make a purchasing decision. 59 | * 60 | * @param {params} params 61 | */ 62 | public getItems(params: BuyBrowseGetItemsParams) { 63 | return this.get(`/item/`, { 64 | params 65 | }); 66 | } 67 | 68 | /** 69 | * This method retrieves the details of a specific item, such as description, price, category, all item aspects, 70 | * condition, return policies, seller feedback and score, shipping options, shipping costs, estimated delivery, 71 | * and other information the buyer needs to make a purchasing decision. 72 | * 73 | * @param {String} itemId The eBay RESTful identifier of an item. 74 | * @param {String} fieldgroups 75 | */ 76 | public getItem(itemId: string, fieldgroups?: string) { 77 | const id = encodeURIComponent(itemId); 78 | return this.get(`/item/${id}`, { 79 | params: { 80 | fieldgroups 81 | } 82 | }); 83 | } 84 | 85 | /** 86 | * This method is a bridge between the eBay legacy APIs, such as Shopping, and Finding and the eBay Api APIs. 87 | * 88 | * @param {LegacyItemParams} params 89 | */ 90 | public getItemByLegacyId(params: BuyBrowseItemByLegacyIdParams) { 91 | return this.get(`/item/get_item_by_legacy_id`, { 92 | params 93 | }); 94 | } 95 | 96 | /** 97 | * This method retrieves the details of the individual items in an item group. 98 | * 99 | * @param itemGroupId 100 | */ 101 | public getItemsByItemGroup(itemGroupId: string) { 102 | return this.get(`/item/get_items_by_item_group`, { 103 | params: { 104 | item_group_id: itemGroupId 105 | } 106 | }); 107 | } 108 | 109 | /** 110 | * This method checks if a product is compatible with the specified item. 111 | * @param {String} itemId The eBay RESTful identifier of an item (such as a part you want to check). 112 | * @param {Object} body CompatibilityPayload 113 | */ 114 | public checkCompatibility(itemId: string, body?: CompatibilityPayload) { 115 | const id = encodeURIComponent(itemId); 116 | return this.post(`/item/${id}/check_compatibility`, body); 117 | } 118 | 119 | // 120 | // Shopping Cart 121 | // 122 | 123 | /** 124 | * This is an Experimental method. This method creates an eBay cart for the eBay member, if one does not exist, and 125 | * adds items to that cart. 126 | * 127 | * @param {Object} item AddCartItemInput 128 | */ 129 | public addItem(item: AddCartItemInput) { 130 | return this.post(`/shopping_cart/add_item`, item); 131 | } 132 | 133 | /** 134 | * This is an experimental method. This method retrieves all the items in the eBay member's cart; 135 | * items added to the cart while on ebay.com as well as items added to the cart using the Browse API. 136 | */ 137 | public getShoppingCart() { 138 | return this.get(`/shopping_cart/`); 139 | } 140 | 141 | /** 142 | * This is an experimental method. This method removes a specific item from the eBay member's cart. 143 | * 144 | * @param {Object} item RemoveCartItemInput 145 | */ 146 | public removeItem(item: RemoveCartItemInput) { 147 | return this.post(`/shopping_cart/remove_item`, item); 148 | } 149 | 150 | /** 151 | * This is an experimental method. This method updates the quantity value of a specific item in the eBay member's 152 | * cart. 153 | * 154 | * @param {UpdateCartItemInput} item UpdateCartItemInput 155 | */ 156 | public updateQuantity(item: UpdateCartItemInput) { 157 | return this.post(`/shopping_cart/update_quantity`, item); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/api/restful/buy/deal/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/buy_deal_v1_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * This API allows third-party developers to search for and retrieve details about eBay deals and events, as well as the items associated with those deals and events. 6 | */ 7 | export default class Deal extends Restful implements OpenApi { 8 | 9 | static id = 'Deal'; 10 | 11 | get basePath(): string { 12 | return '/buy/deal/v1'; 13 | } 14 | 15 | /** 16 | * This method retrieves a paginated set of deal items. 17 | * 18 | * @param categoryIds The unique identifier of the eBay category for the search. 19 | * @param commissionable A filter for commissionable deals. Restriction: This filter is currently only supported for the US marketplace. 20 | * @param deliveryCountry A filter for items that can be shipped to the specified country. 21 | * @param limit The maximum number of items, from the current result set, returned on a single page. 22 | * @param offset The number of items that will be skipped in the result set. 23 | */ 24 | public getDealItems({ 25 | categoryIds, 26 | commissionable, 27 | deliveryCountry, 28 | limit, 29 | offset 30 | }: { 31 | categoryIds?: string, 32 | commissionable?: string, 33 | deliveryCountry?: string, 34 | limit?: string, 35 | offset?: string 36 | }) { 37 | return this.get(`/deal_item`, { 38 | params: { 39 | category_ids: categoryIds, 40 | commissionable, 41 | delivery_country: deliveryCountry, 42 | limit, 43 | offset 44 | } 45 | }); 46 | } 47 | 48 | /** 49 | * This method retrieves the details for an eBay event. 50 | * 51 | * @param eventId The unique identifier for the eBay event. 52 | */ 53 | public getEvent(eventId: string) { 54 | eventId = encodeURIComponent(eventId); 55 | return this.get(`/event/${eventId}`); 56 | } 57 | 58 | /** 59 | * This method returns paginated results containing all eBay events for the specified marketplace. 60 | * 61 | * @param limit The maximum number of items, from the current result set, returned on a single page. Default: 20 Maximum Value: 100 62 | * @param offset The number of items that will be skipped in the result set. 63 | */ 64 | public getEvents({limit, offset}: { limit?: string, offset?: string, }) { 65 | return this.get(`/event`, { 66 | params: { 67 | limit, 68 | offset 69 | } 70 | }); 71 | } 72 | 73 | /** 74 | * This method returns paginated results containing all eBay events for the specified marketplace. 75 | * 76 | * @param eventIds The unique identifiers for the eBay events. Maximum Value: 1 77 | * @param categoryIds The unique identifier of the eBay category for the search. Maximum Value: 1 78 | * @param deliveryCountry A filter for items that can be shipped to the specified country. 79 | * @param limit The maximum number of items, from the current result set, returned on a single page. Default: 20 Maximum Value: 100 80 | * @param offset The number of items that will be skipped in the result set. 81 | */ 82 | public getEventItems(eventIds: string, { 83 | categoryIds, 84 | deliveryCountry, 85 | limit, 86 | offset 87 | }: { categoryIds?: string, deliveryCountry?: string, limit?: string, offset?: string, } = {}) { 88 | return this.get(`/event_item`, { 89 | params: { 90 | event_ids: eventIds, 91 | limit, 92 | offset, 93 | category_ids: categoryIds, 94 | delivery_country: deliveryCountry 95 | } 96 | }); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/api/restful/buy/feed/index.ts: -------------------------------------------------------------------------------- 1 | import {BuyFeedParams} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/buy_feed_v1_beta_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | /** 6 | * The Feed API provides the ability to download TSV_GZIP feed files containing eBay items and an hourly snapshot file 7 | * of the items that have changed within an hour for a specific category, date and marketplace. 8 | */ 9 | export default class Feed extends Restful implements OpenApi { 10 | 11 | static id = 'Feed'; 12 | 13 | get basePath() { 14 | return '/buy/feed/v1_beta'; 15 | } 16 | 17 | /** 18 | * This method lets you download a TSV_GZIP (tab separated value gzip) Item feed file. 19 | * 20 | * @param {BuyFeedParams} params 21 | * @param range his header specifies the range in bytes of the chunks of the gzip file being returned. 22 | * Format: bytes=startpos-endpos For example, the following retrieves the first 10 MBs of the feed file. 23 | */ 24 | public getItemFeed(params: BuyFeedParams, range: string) { 25 | return this.get(`/item`, { 26 | params, 27 | headers: { 28 | 'Range': range 29 | } 30 | }); 31 | } 32 | 33 | /** 34 | * This method lets you download a TSV_GZIP (tab separated value gzip) Item Group feed file. 35 | * @param {BuyFeedParams} params 36 | * @param range his header specifies the range in bytes of the chunks of the gzip file being returned. 37 | * Format: bytes=startpos-endpos For example, the following retrieves the first 10 MBs of the feed file. 38 | */ 39 | public getItemGroupFeed(params: BuyFeedParams, range: string) { 40 | return this.get(`/item_group`, { 41 | params, 42 | headers: { 43 | 'Range': range 44 | } 45 | }); 46 | } 47 | 48 | /** 49 | * The Hourly Snapshot feed file is generated each hour every day for all categories. 50 | * 51 | * @param {BuyFeedParams} params 52 | * @param {String} snapshotDate 53 | * @param range his header specifies the range in bytes of the chunks of the gzip file being returned. 54 | * Format: bytes=startpos-endpos For example, the following retrieves the first 10 MBs of the feed file. 55 | */ 56 | public getItemSnapshotFeed(params: BuyFeedParams, snapshotDate: string, range: string) { 57 | return this.get(`/item_snapshot`, { 58 | params: { 59 | ...params, 60 | snapshot_date: snapshotDate 61 | }, 62 | headers: { 63 | 'Range': range 64 | } 65 | }); 66 | } 67 | 68 | /** 69 | * The Hourly Snapshot feed file is generated each hour every day for all categories. 70 | * 71 | * @param {BuyFeedParams} params 72 | * @param {String} snapshotDate 73 | * @param range his header specifies the range in bytes of the chunks of the gzip file being returned. 74 | * Format: bytes=startpos-endpos For example, the following retrieves the first 10 MBs of the feed file. 75 | */ 76 | public getProductFeed(params: BuyFeedParams, snapshotDate: string, range: string) { 77 | return this.get(`/product`, { 78 | params: { 79 | ...params, 80 | snapshot_date: snapshotDate 81 | }, 82 | headers: { 83 | 'Range': range 84 | } 85 | }); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/api/restful/buy/index.ts: -------------------------------------------------------------------------------- 1 | import Browse from './browse/index.js'; 2 | import Feed from './feed/index.js'; 3 | import Marketing from './marketing/index.js'; 4 | import Offer from './offer/index.js'; 5 | import Order from './order/index.js'; 6 | import Deal from './deal/index.js'; 7 | import MarketplaceInsights from './marketplaceInsights/index.js' 8 | 9 | export type Buy = { 10 | browse: Browse, 11 | deal: Deal 12 | feed: Feed, 13 | marketing: Marketing, 14 | marketplaceInsights: MarketplaceInsights 15 | offer: Offer, 16 | order: Order 17 | }; 18 | 19 | export { 20 | Browse, 21 | Deal, 22 | Feed, 23 | Marketing, 24 | MarketplaceInsights, 25 | Offer, 26 | Order 27 | }; 28 | -------------------------------------------------------------------------------- /src/api/restful/buy/marketing/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BuyMarketingGetAlsoBoughtByProductParams, 3 | BuyMarketingGetAlsoViewedByProductParams, 4 | BuyMarketingGetMerchandisedProductsParams 5 | } from '../../../../types/index.js'; 6 | import {operations} from '../../../../types/restful/specs/buy_marketing_v1_beta_oas3.js'; 7 | import Restful, {OpenApi} from '../../index.js'; 8 | 9 | /** 10 | * The Marketing API retrieves eBay products based on a metric, such as Best Selling, as well as products that were 11 | * also bought and also viewed. 12 | */ 13 | export default class Marketing extends Restful implements OpenApi { 14 | 15 | static id = 'Marketing'; 16 | 17 | get basePath(): string { 18 | return '/buy/marketing/v1_beta'; 19 | } 20 | 21 | // 22 | // Marketing 23 | // Client Credentials: https://api.ebay.com/oauth/api_scope/buy.marketing 24 | // 25 | 26 | /** 27 | * This call returns products that were also bought when shoppers bought the product specified in the request. 28 | * @param params 29 | */ 30 | public getAlsoBoughtByProduct(params: BuyMarketingGetAlsoBoughtByProductParams) { 31 | return this.get(`/merchandised_product/get_also_bought_products`, { 32 | params 33 | }); 34 | } 35 | 36 | /** 37 | * This call returns products that were also viewed when shoppers viewed the product specified in the request. 38 | * 39 | * @param params 40 | */ 41 | public getAlsoViewedByProduct(params: BuyMarketingGetAlsoViewedByProductParams) { 42 | return this.get(`/merchandised_product/get_also_viewed_products`, { 43 | params 44 | }); 45 | } 46 | 47 | /** 48 | * This call returns an array of products based on the category and metric specified. 49 | * 50 | * @param params 51 | */ 52 | public getMerchandisedProducts(params: BuyMarketingGetMerchandisedProductsParams) { 53 | return this.get(`/merchandised_product`, { 54 | params 55 | }); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/api/restful/buy/marketplaceInsights/index.ts: -------------------------------------------------------------------------------- 1 | import {MarketingInsightsSearchParams} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/buy_marketplace_insights_v1_beta_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | /** 6 | * (Limited Release) The Marketplace Insights API provides the ability to search for sold items on eBay by keyword, 7 | * GTIN, category, and product and returns the of sales history of those items. 8 | */ 9 | export default class MarketplaceInsights extends Restful implements OpenApi { 10 | 11 | static id = 'MarketplaceInsights'; 12 | 13 | get basePath(): string { 14 | return '/buy/marketplace_insights/v1_beta'; 15 | } 16 | 17 | /** 18 | * (Limited Release) This method searches for sold eBay items by various URI query parameters and retrieves the sales 19 | * history of the items for the last 90 days. You can search by keyword, category, eBay product ID (ePID), or GTIN, 20 | * or a combination of these. 21 | * 22 | * @param itemId 23 | * @param aspectFilter This field lets you filter by item aspects. 24 | * @param categoryIds The category ID is required and is used to limit the results. 25 | * @param epid The ePID is the eBay product identifier of a product from the eBay product catalog. 26 | * @param fieldgroups This field lets you control what is to be returned in the response and accepts a comma separated list of values. 27 | * @param filter This field supports multiple field filters that can be used to limit/customize the result set. 28 | * @param gtin This field lets you search by the Global Trade Item Number of the item as defined by https://www.gtin.info. 29 | * @param limit The number of items, from the result set, returned in a single page. 30 | * @param offset Specifies the number of items to skip in the result set. 31 | * @param q A string consisting of one or more keywords that are used to search for items on eBay. 32 | * @param sort This field specifies the order and the field name to use to sort the items. 33 | */ 34 | public search({ 35 | aspectFilter, 36 | categoryIds, 37 | epid, 38 | fieldgroups, 39 | filter, 40 | gtin, 41 | limit, 42 | offset, 43 | q, 44 | sort, 45 | }: MarketingInsightsSearchParams) { 46 | return this.get(`/item_sales/search`, { 47 | params: { 48 | aspect_filter: aspectFilter, 49 | category_ids: categoryIds, 50 | epid, 51 | fieldgroups, 52 | filter, 53 | gtin, 54 | limit, 55 | offset, 56 | q, 57 | sort, 58 | } 59 | }); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/api/restful/buy/offer/index.ts: -------------------------------------------------------------------------------- 1 | import {PlaceProxyBidRequest} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/buy_offer_v1_beta_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | /** 6 | * The Api Offer API enables Partners to place proxy bids for a buyer and retrieve the auctions where the buyer is 7 | * bidding. Client Credentials: https://api.ebay.com/oauth/api_scope/buy.offer.auction 8 | */ 9 | export default class Offer extends Restful implements OpenApi { 10 | 11 | static id = 'Offer'; 12 | 13 | get basePath(): string { 14 | return '/buy/offer/v1_beta'; 15 | } 16 | 17 | /** 18 | * This method retrieves the bidding details that are specific to the buyer of the specified auction. 19 | * 20 | * @param itemId 21 | */ 22 | public getBidding(itemId: string) { 23 | const id = encodeURIComponent(itemId); 24 | return this.get(`/bidding/${id}`); 25 | } 26 | 27 | /** 28 | * This method uses a user access token to place a proxy bid for the buyer on a specific auction item. 29 | * 30 | * @param itemId 31 | * @param {PlaceProxyBidRequest} body 32 | */ 33 | public placeProxyBid(itemId: string, body?: PlaceProxyBidRequest) { 34 | const id = encodeURIComponent(itemId); 35 | return this.post(`/bidding/${id}/place_proxy_bid`, body); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/api/restful/commerce/catalog/index.ts: -------------------------------------------------------------------------------- 1 | import {CommerceCatalogSearchParams} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/commerce_catalog_v1_beta_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | /** 6 | * Use the Catalog API to search the eBay catalog for products on which to base a seller's item listing; 7 | */ 8 | export default class Catalog extends Restful implements OpenApi> { 9 | 10 | static id = 'Catalog'; 11 | 12 | get basePath(): string { 13 | return '/commerce/catalog/v1_beta'; 14 | } 15 | 16 | /** 17 | * Note: The three catalog change request methods in the Catalog API are deprecated, and are scheduled to be 18 | * decommissioned in Q1 of 2020. 19 | * 20 | * @param changeRequestId The unique identifier of the change request being requested. 21 | */ 22 | public getChangeRequest(changeRequestId: string) { 23 | return this.get(`/change_request/${changeRequestId}`); 24 | } 25 | 26 | /** 27 | * Note: The three catalog change request methods in the Catalog API are deprecated, and are scheduled to be 28 | * decommissioned in Q1 of 2020. 29 | * 30 | * @param filter One or more comma-separated criteria for narrowing down the collection of change requests returned 31 | * by this call. 32 | * @param limit The number of change requests to return. This is the result set, a subset of the full collection of 33 | * change requests that match the filter criteria of this call. 34 | * @param offset The first change request to return based on its position in the returned collection of change 35 | * requests. 36 | */ 37 | public getChangeRequests({filter, limit, offset}: { filter?: string, limit?: number, offset?: number } = {}) { 38 | return this.get(`/change_request`, { 39 | params: { 40 | filter, 41 | limit, 42 | offset 43 | } 44 | }); 45 | } 46 | 47 | /** 48 | * This call retrieves details of the catalog product identified by the eBay product identifier (ePID) specified in 49 | * the request. 50 | * 51 | * @param epid The ePID of the product being requested. 52 | */ 53 | public getProduct(epid: string) { 54 | const e = encodeURIComponent(epid); 55 | return this.get(`/product/${e}`); 56 | } 57 | 58 | /** 59 | * This call searches for and retrieves summaries of one or more products in the eBay catalog that match the search 60 | * criteria provided by a seller. 61 | * 62 | * @param params SearchCatalogParams 63 | */ 64 | public search(params?: CommerceCatalogSearchParams) { 65 | return this.get(`/product_summary/search`, { 66 | params 67 | }); 68 | } 69 | 70 | /** 71 | * This call retrieves an array of all supported aspects, aspect constraints, and aspect values for the specified 72 | * catalog product and its associated or suggested categories, as well as the values currently associated with that 73 | * product. 74 | * 75 | * @param epid The unique eBay product identifier of the catalog product that you want to update. 76 | * @param acceptLanguage This request header sets the natural language that will be provided in the field values of 77 | * the response payload. 78 | * @param otherApplicableCategoryIds Use only if you are also including the primary_category_id parameter in the 79 | * request. 80 | * @param primaryCategoryId Use only if the seller believes this product is associated with the wrong primary 81 | * category. 82 | * @param marketplaceId Use this header to specify the eBay marketplace identifier. 83 | */ 84 | public getProductMetadata(epid: string, 85 | {otherApplicableCategoryIds, primaryCategoryId}: { 86 | otherApplicableCategoryIds?: string, 87 | primaryCategoryId?: string, 88 | } = {}) { 89 | return this.get(`/get_product_metadata`, { 90 | params: { 91 | epid, 92 | other_applicable_category_ids: otherApplicableCategoryIds, 93 | primary_category_id: primaryCategoryId 94 | } 95 | }); 96 | } 97 | 98 | /** 99 | * This call retrieves an array of all supported aspects, aspect constraints, and aspect values for the specified 100 | * eBay categories. 101 | * 102 | * @param primaryCategoryId The unique identifier of the primary eBay category for which you will retrieve product 103 | * aspects. 104 | * @param otherApplicableCategoryIds A string of comma-separated category IDs. 105 | */ 106 | public getProductMetadataForCategories(primaryCategoryId: string, otherApplicableCategoryIds?: string) { 107 | return this.get(`/get_product_metadata_for_categories`, { 108 | params: { 109 | primary_category_id: primaryCategoryId, 110 | other_applicable_category_ids: otherApplicableCategoryIds 111 | } 112 | }); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/api/restful/commerce/charity/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/commerce_charity_v1_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * The Charity API allows third-party developers to search for and access details on supported charitable organizations. 6 | */ 7 | export default class Charity extends Restful implements OpenApi { 8 | 9 | static id = 'Charity'; 10 | 11 | get basePath(): string { 12 | return '/commerce/charity/v1'; 13 | } 14 | 15 | /** 16 | * This call is used to retrieve detailed information about supported charitable organizations. 17 | * 18 | * @param charityOrgId The unique ID of the charitable organization. 19 | */ 20 | public getCharityOrg(charityOrgId: string) { 21 | charityOrgId = encodeURIComponent(charityOrgId); 22 | return this.get(`/charity_org/${charityOrgId}`); 23 | } 24 | 25 | /** 26 | * This call is used to retrieve detailed information about supported charitable organizations. 27 | * 28 | * @param limit The number of items, from the result set, returned in a single page. Valid Values: 1-100 Default: 20 29 | * @param offset The number of items that will be skipped in the result set. 30 | * @param q A query string that matches the keywords in name, mission statement, or description. 31 | * @param registrationIds A comma-separated list of charitable organization registration IDs. 32 | */ 33 | public getCharityOrgs({ 34 | limit, 35 | offset, 36 | q, 37 | registrationIds 38 | }: { limit?: string, offset?: string, q?: string, registrationIds?: string }) { 39 | return this.get(`/charity_org`, { 40 | params: { 41 | limit, 42 | offset, 43 | q, 44 | registration_ids: registrationIds 45 | } 46 | }); 47 | } 48 | 49 | /** 50 | * This call allows users to retrieve the details for a specific charitable organization using its legacy charity ID, which has also been referred to as the charity number, external ID, and PayPal Giving Fund ID. 51 | * 52 | * @param legacyCharityOrgId The legacy ID of the charitable organization. 53 | */ 54 | public getCharityOrgByLegacyId(legacyCharityOrgId: string) { 55 | return this.get(`/charity_org/get_charity_org_by_legacy_id`, { 56 | params: { 57 | legacy_charity_org_id: legacyCharityOrgId 58 | } 59 | }); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/api/restful/commerce/identity/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/commerce_identity_v1_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * Retrieves the authenticated user's account profile information. 6 | */ 7 | export default class Identity extends Restful implements OpenApi { 8 | 9 | static id = 'Identity'; 10 | 11 | get basePath(): string { 12 | return '/commerce/identity/v1'; 13 | } 14 | 15 | get subdomain(): string { 16 | return 'apiz'; 17 | } 18 | 19 | /** 20 | * This method retrieves the account profile information for an authenticated user, which requires a User access 21 | * token. What is returned is controlled by the scopes. 22 | */ 23 | public getUser() { 24 | return this.get(`/user/`); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/api/restful/commerce/index.ts: -------------------------------------------------------------------------------- 1 | import Catalog from './catalog/index.js'; 2 | import Charity from './charity/index.js'; 3 | import Identity from './identity/index.js'; 4 | import Media from './media/index.js'; 5 | import Notification from './notification/index.js'; 6 | import Taxonomy from './taxonomy/index.js'; 7 | import Translation from './translation/index.js'; 8 | 9 | export type Commerce = { 10 | catalog: Catalog; 11 | charity: Charity, 12 | identity: Identity; 13 | notification: Notification 14 | taxonomy: Taxonomy; 15 | translation: Translation; 16 | media: Media; 17 | }; 18 | 19 | export { 20 | Catalog, 21 | Charity, 22 | Identity, 23 | Notification, 24 | Taxonomy, 25 | Translation, 26 | Media 27 | }; 28 | -------------------------------------------------------------------------------- /src/api/restful/commerce/media/index.ts: -------------------------------------------------------------------------------- 1 | import {CreateVideoRequest, InputStream} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/commerce_media_v1_beta_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | /** 6 | * The Media API allows sellers to create, upload, and fetch videos. 7 | */ 8 | export default class Media extends Restful implements OpenApi { 9 | 10 | 11 | static id = 'Media'; 12 | 13 | get basePath(): string { 14 | return '/commerce/media/v1_beta'; 15 | } 16 | 17 | get subdomain(): string { 18 | return 'apim'; 19 | } 20 | 21 | /** 22 | * This method creates a video. When using this method, specify the title, size, and classification of the video to be created. 23 | * @param body the CreateVideoRequest 24 | */ 25 | async createVideo(body?: CreateVideoRequest) { 26 | return this.post('/video', body); 27 | } 28 | 29 | /** 30 | * This method retrieves a video's metadata and content given a specified video ID. 31 | * @param videoId The unique identifier of the video to be retrieved. 32 | */ 33 | async getVideo(videoId: string) { 34 | videoId = encodeURIComponent(videoId); 35 | return this.get(`/video/${videoId}`); 36 | }; 37 | 38 | /** 39 | * This method associates the specified file with the specified video ID and uploads the input file. 40 | * 41 | * @param videoId The unique identifier of the video to be uploaded. 42 | * @param body The request payload for this method is the input stream for the video source. The input source must be an .mp4 file of the type MPEG-4 Part 10 or Advanced Video Coding (MPEG-4 AVC). 43 | */ 44 | async uploadVideo(videoId: string, body?: InputStream) { 45 | videoId = encodeURIComponent(videoId); 46 | return this.post(`/video/${videoId}/upload`, body); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/api/restful/commerce/taxonomy/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/commerce_taxonomy_v1_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * Use the Taxonomy API to discover the most appropriate eBay categories under which sellers can offer inventory items 6 | * for sale, and the most likely categories under which buyers can browse or search for items to purchase. 7 | */ 8 | export default class Taxonomy extends Restful implements OpenApi { 9 | 10 | static id = 'Taxonomy'; 11 | 12 | get basePath(): string { 13 | return '/commerce/taxonomy/v1'; 14 | } 15 | 16 | /** 17 | * A given eBay marketplace might use multiple category trees, but one of those trees is considered to be the 18 | * default for that marketplace. 19 | * 20 | * @param marketplaceId The ID of the eBay marketplace for which the category tree ID is being requested. 21 | */ 22 | public getDefaultCategoryTreeId(marketplaceId: string) { 23 | return this.get(`/get_default_category_tree_id`, { 24 | params: { 25 | marketplace_id: marketplaceId 26 | } 27 | }); 28 | } 29 | 30 | /** 31 | * This call retrieves the complete category tree that is identified by the category_tree_id parameter. 32 | * 33 | * @param categoryTreeId 34 | */ 35 | public getCategoryTree(categoryTreeId: string) { 36 | const cId = encodeURIComponent(categoryTreeId); 37 | return this.get(`/category_tree/${cId}`); 38 | } 39 | 40 | /** 41 | * This call retrieves the details of all nodes of the category tree hierarchy (the subtree) below a specified 42 | * category of a category tree. 43 | * 44 | * @param categoryTreeId The unique identifier of the eBay category tree from which a category subtree is being 45 | * requested. 46 | * @param categoryId The unique identifier of the category at the top of the subtree being requested. 47 | */ 48 | public getCategorySubtree(categoryTreeId: string, categoryId: string) { 49 | categoryTreeId = encodeURIComponent(categoryTreeId); 50 | return this.get(`/category_tree/${categoryTreeId}/get_category_subtree`, { 51 | params: { 52 | category_id: categoryId 53 | } 54 | }); 55 | } 56 | 57 | /** 58 | * This call returns an array of category tree leaf nodes in the specified category tree that are considered by eBay 59 | * to most closely correspond to the query string q. 60 | * 61 | * @param categoryTreeId The unique identifier of the eBay category tree for which suggested nodes are being 62 | * requested. 63 | * @param q A quoted string that describes or characterizes the item being offered for sale. 64 | */ 65 | public getCategorySuggestions(categoryTreeId: string, q: string) { 66 | return this.get(`/category_tree/${categoryTreeId}/get_category_suggestions`, { 67 | params: { 68 | q 69 | } 70 | }); 71 | } 72 | 73 | /** 74 | * This call returns a list of aspects that are appropriate or necessary for accurately describing items in the 75 | * specified leaf category. 76 | * 77 | * @param categoryTreeId The unique identifier of the eBay category tree from which the specified category's 78 | * aspects are being requested. 79 | * @param categoryId The unique identifier of the leaf category for which aspects are being requested. 80 | */ 81 | public getItemAspectsForCategory(categoryTreeId: string, categoryId: string) { 82 | categoryTreeId = encodeURIComponent(categoryTreeId); 83 | return this.get(`/category_tree/${categoryTreeId}/get_item_aspects_for_category`, { 84 | params: { 85 | category_id: categoryId 86 | } 87 | }); 88 | } 89 | 90 | /** 91 | * This call retrieves the compatible vehicle aspects that are used to define a motor vehicle that is compatible 92 | * with a motor vehicle part or accessory. 93 | * 94 | * @param categoryTreeId This is the unique identifier of category tree. The following is the list of 95 | * category_tree_id values and the eBay marketplaces that they represent. 96 | * 97 | * @param categoryId The unique identifier of an eBay category. 98 | */ 99 | public getCompatibilityProperties(categoryTreeId: string, categoryId: string) { 100 | categoryTreeId = encodeURIComponent(categoryTreeId); 101 | return this.get(`/category_tree/${categoryTreeId}/get_compatibility_properties`, { 102 | params: { 103 | category_id: categoryId 104 | } 105 | }); 106 | } 107 | 108 | /** 109 | * This call retrieves applicable compatible vehicle property values based on the specified eBay marketplace, 110 | * specified eBay category, and filters used in the request. 111 | * 112 | * @param categoryTreeId This is the unique identifier of the category tree. 113 | * @param categoryId The unique identifier of an eBay category. 114 | * @param compatibilityProperty One compatible vehicle property applicable to the specified eBay marketplace and 115 | * eBay category is specified in this required filter. 116 | */ 117 | public getCompatibilityPropertyValues( 118 | categoryTreeId: string, 119 | categoryId: string, 120 | compatibilityProperty: string 121 | ) { 122 | categoryTreeId = encodeURIComponent(categoryTreeId); 123 | return this.get(`/category_tree/${categoryTreeId}/get_compatibility_property_values`, { 124 | params: { 125 | category_id: categoryId, 126 | compatibility_property: compatibilityProperty 127 | } 128 | }); 129 | } 130 | 131 | /** 132 | * This call returns a complete list of aspects for all of the leaf categories that belong to an eBay marketplace. 133 | * 134 | * @param categoryTreeId 135 | * 136 | * @return A JSON GZIP compressed file buffer 137 | */ 138 | public fetchItemAspects(categoryTreeId: string): Promise { 139 | categoryTreeId = encodeURIComponent(categoryTreeId); 140 | return this.get(`/category_tree/${categoryTreeId}/fetch_item_aspects`, { 141 | responseType: 'arraybuffer' 142 | }); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/api/restful/commerce/translation/index.ts: -------------------------------------------------------------------------------- 1 | import {TranslateRequest} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/commerce_translation_v1_beta_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | /** 6 | * This API allows 3rd party developers to translate item title, description, search query. 7 | */ 8 | export default class Translation extends Restful implements OpenApi { 9 | 10 | static id = 'Translation'; 11 | 12 | get basePath(): string { 13 | return '/commerce/translation/v1_beta'; 14 | } 15 | 16 | /** 17 | * Translates input text inot a given language. 18 | * 19 | * @param body TranslateRequest 20 | */ 21 | public translate(body: TranslateRequest) { 22 | return this.post(`/translate`, body); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/api/restful/developer/analytics/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/developer_analytics_v1_beta_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * This method retrieves the call limit and utilization data for an application. 6 | */ 7 | export default class Analytics extends Restful implements OpenApi { 8 | 9 | static id = 'Analytics'; 10 | 11 | get basePath(): string { 12 | return '/developer/analytics/v1_beta'; 13 | } 14 | 15 | /** 16 | * This method retrieves the call limit and utilization data for an application. 17 | * 18 | * @param apiContext This optional query parameter filters the result to include only the specified API context. 19 | * @param apiName This optional query parameter filters the result to include only the APIs specified. 20 | */ 21 | public getRateLimits(apiContext?: string, apiName?: string) { 22 | return this.get(`/rate_limit/`, { 23 | params: { 24 | api_context: apiContext, 25 | api_name: apiName 26 | } 27 | }); 28 | } 29 | 30 | /** 31 | * This method retrieves the call limit and utilization data for an application user. 32 | * 33 | * @param apiContext This optional query parameter filters the result to include only the specified API context. 34 | * @param apiName This optional query parameter filters the result to include only the APIs specified. 35 | */ 36 | public getUserRateLimits(apiContext: string, apiName: string) { 37 | return this.get(`/user_rate_limit/`, { 38 | params: { 39 | api_context: apiContext, 40 | api_name: apiName 41 | } 42 | }); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/api/restful/developer/index.ts: -------------------------------------------------------------------------------- 1 | import Analytics from './analytics/index.js'; 2 | import KeyManagement from './keyManagement/index.js'; 3 | 4 | export type Developer = { 5 | analytics: Analytics, 6 | keyManagement: KeyManagement 7 | }; 8 | 9 | export { 10 | Analytics, 11 | KeyManagement 12 | }; 13 | -------------------------------------------------------------------------------- /src/api/restful/developer/keyManagement/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/developer_key_management_v1_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * This method retrieves the call limit and utilization data for an application. 6 | */ 7 | export default class KeyManagement extends Restful implements OpenApi { 8 | 9 | static id = 'KeyManagement'; 10 | 11 | get subdomain(): string { 12 | return 'apiz'; 13 | } 14 | 15 | get basePath(): string { 16 | return '/developer/key_management/v1'; 17 | } 18 | 19 | /** 20 | * This method returns the Public Key, Public Key as JWE, 21 | * and metadata for all keypairs associated with the application key making the call. 22 | */ 23 | public getSigningKeys() { 24 | return this.get(`/signing_key`); 25 | } 26 | 27 | /** 28 | * This method creates keypairs. 29 | */ 30 | public createSigningKey(signingKeyCipher: 'ED25519' | 'RSA') { 31 | return this.post(`/signing_key`, { 32 | signingKeyCipher 33 | }); 34 | } 35 | 36 | /** 37 | * This method returns the Public Key, Public Key as JWE, 38 | * and metadata for a specified signingKeyId associated with the application key making the call. 39 | * @param signingKeyId the signin key 40 | */ 41 | public getSigningKey(signingKeyId: string) { 42 | return this.get(`/signing_key/${signingKeyId}`); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/api/restful/postOrder/cancellation/index.ts: -------------------------------------------------------------------------------- 1 | import Restful from '../../index.js'; 2 | import { 3 | CancellationSearchParams, 4 | ConfirmRefundRequest, 5 | CreateCancelRequest, 6 | RejectCancelRequest 7 | } from '../../../../types/index.js'; 8 | 9 | /** 10 | * Post-Order Cancellation API 11 | */ 12 | export default class Cancellation extends Restful { 13 | 14 | static id = 'Cancellation'; 15 | 16 | get basePath(): string { 17 | return '/post-order/v2'; 18 | } 19 | 20 | get useIaf() { 21 | return true; 22 | } 23 | 24 | /** 25 | * Seller approves a cancellation request 26 | * 27 | * @param cancelId The unique eBay-assigned identifier of the cancellation request to be approved. 28 | */ 29 | public approveCancellationRequest(cancelId: string) { 30 | cancelId = encodeURIComponent(cancelId); 31 | return this.post(`/cancellation/${cancelId}/approve`); 32 | } 33 | 34 | /** 35 | * Check the eligibility of an order cancellation 36 | * 37 | * @param legacyOrderId The unique ID of the order being canceled or the order being considered for cancellation. 38 | */ 39 | public checkCancellationEligibility(legacyOrderId: string) { 40 | return this.post(`/cancellation/check_eligibility`, { 41 | legacyOrderId 42 | }); 43 | } 44 | 45 | /** 46 | * Buyer confirms the refund from a cancellation was received 47 | * 48 | * @param cancelId The unique eBay-assigned identifier of the cancellation/refund being confirmed. 49 | * @param payload the ConfirmRefundReceivedPayload 50 | */ 51 | public confirmRefundReceived(cancelId: string, payload?: ConfirmRefundRequest) { 52 | cancelId = encodeURIComponent(cancelId); 53 | return this.post(`/cancellation/${cancelId}/confirm`, payload); 54 | } 55 | 56 | /** 57 | * Request or perform an order cancellation. 58 | * 59 | * @param payload the CreateCancelRequest 60 | */ 61 | public createCancellation(payload: CreateCancelRequest) { 62 | return this.post(`/cancellation`, payload); 63 | } 64 | 65 | /** 66 | * Retrieve the details of an order cancellation. 67 | * 68 | * @param cancelId Supply in this path parameter the unique eBay-assigned ID of the cancellation request to 69 | * retrieve. 70 | * @param fieldGroups The value set in this query parameter controls the level of detail that is returned in the 71 | * response. 72 | */ 73 | public getCancellation(cancelId: string, fieldGroups?: string) { 74 | cancelId = encodeURIComponent(cancelId); 75 | return this.get(`/cancellation/${cancelId}`, { 76 | params: { 77 | fieldgroups: fieldGroups 78 | } 79 | }); 80 | } 81 | 82 | /** 83 | * Seller rejects a cancellation request. 84 | * 85 | * @param cancelId The unique eBay-assigned identifier of the cancellation request to be rejected. 86 | * @param payload the RejectCancelRequest 87 | */ 88 | public rejectCancellationRequest(cancelId: string, payload?: RejectCancelRequest) { 89 | cancelId = encodeURIComponent(cancelId); 90 | return this.post(`/cancellation/${cancelId}/reject`, payload); 91 | } 92 | 93 | /** 94 | * Search for cancellations. 95 | * 96 | * @param params the SearchParams 97 | */ 98 | public search(params: CancellationSearchParams) { 99 | return this.get(`/cancellation/search`, { 100 | params 101 | }); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/api/restful/postOrder/case/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AppealRequest, 3 | BuyerCloseCaseRequest, 4 | CaseSearchParams, 5 | ReturnAddressRequest, 6 | Text 7 | } from '../../../../types/index.js'; 8 | import Restful from '../../index.js'; 9 | 10 | /** 11 | * Post-Order Case Management API 12 | */ 13 | export default class Case extends Restful { 14 | 15 | static id = 'Case'; 16 | 17 | get basePath(): string { 18 | return '/post-order/v2'; 19 | } 20 | 21 | get useIaf() { 22 | return true; 23 | } 24 | 25 | /** 26 | * Buyer or seller appeals a case decision. 27 | * 28 | * @param caseId The unique identifier of a case. 29 | * @param payload the AppealRequest 30 | */ 31 | public appealCaseDecision(caseId: string, payload?: AppealRequest) { 32 | const id = encodeURIComponent(caseId); 33 | return this.post(`/casemanagement/${id}/appeal`, payload); 34 | } 35 | 36 | /** 37 | * Check the eligibility of an order cancellation. 38 | * 39 | * @param caseId The unique identifier of a case. 40 | * @param payload the BuyerCloseCaseRequest 41 | */ 42 | public closeCase(caseId: string, payload: BuyerCloseCaseRequest) { 43 | const id = encodeURIComponent(caseId); 44 | return this.post(`/casemanagement/${id}/close`, payload); 45 | } 46 | 47 | /** 48 | * Retrieve the details related to a specific case. 49 | * 50 | * @param caseId The unique identifier of a case. 51 | */ 52 | public getCase(caseId: string) { 53 | const id = encodeURIComponent(caseId); 54 | return this.get(`/casemanagement/${id}`); 55 | } 56 | 57 | /** 58 | * Seller issues a refund for a case. 59 | * 60 | * @param caseId The unique identifier of a case. 61 | * @param payload the CaseVoluntaryRefundRequest (Text) 62 | */ 63 | public issueCaseRefund(caseId: string, payload?: Text) { 64 | const id = encodeURIComponent(caseId); 65 | return this.post(`/casemanagement/${id}/issue_refund`, payload); 66 | } 67 | 68 | /** 69 | * This call allows the buyer to provide shipment tracking information for the item that is being returned to the 70 | * seller. 71 | * 72 | * @param caseId The unique identifier of a case. 73 | * @param shippingCarrierName The shipping carrier that is used to ship the item, such as 'FedEx', 'UPS', or 74 | * 'USPS'. 75 | * @param trackingNumber The tracking number assigned by the shipping carrier to the item shipment. 76 | */ 77 | public provideReturnShipmentInfo(caseId: string, {shippingCarrierName, trackingNumber}: 78 | { shippingCarrierName: string, trackingNumber: string }) { 79 | const id = encodeURIComponent(caseId); 80 | return this.post(`/casemanagement/${id}/provide_shipment_info`, { 81 | shippingCarrierName, 82 | trackingNumber 83 | }); 84 | } 85 | 86 | /** 87 | * Seller provides a return address to the buyer. 88 | * 89 | * @param cancelId The unique eBay-assigned identifier of the cancellation request to be rejected. 90 | * @param payload the ReturnAddressRequest 91 | */ 92 | public providesReturnAddress(cancelId: string, payload?: ReturnAddressRequest) { 93 | const id = encodeURIComponent(cancelId); 94 | return this.post(`/casemanagement/${id}/provide_return_address`, payload); 95 | } 96 | 97 | /** 98 | * This call is used to search for cases using multiple filter types. 99 | * 100 | * @param params the SearchParams 101 | */ 102 | public search(params: CaseSearchParams) { 103 | return this.get(`/casemanagement/search`, { 104 | params 105 | }); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/api/restful/postOrder/index.ts: -------------------------------------------------------------------------------- 1 | import Cancellation from './cancellation/index.js'; 2 | import Case from './case/index.js'; 3 | import Inquiry from './inquiry/index.js'; 4 | import Return from './return/index.js'; 5 | 6 | export type PostOrder = { 7 | cancellation: Cancellation, 8 | case: Case, 9 | inquiry: Inquiry, 10 | return: Return 11 | }; 12 | 13 | export { 14 | Cancellation, 15 | Case, 16 | Inquiry, 17 | Return 18 | }; 19 | -------------------------------------------------------------------------------- /src/api/restful/postOrder/inquiry/index.ts: -------------------------------------------------------------------------------- 1 | import Restful from '../../index.js'; 2 | import { 3 | BuyerCloseInquiryRequest, 4 | CheckInquiryEligibilityRequest, 5 | CreateInquiryRequest, 6 | EscalateInquiryRequest, 7 | InquirySearchParams, 8 | InquiryVoluntaryRefundRequest, 9 | SellerProvideRefundInfoRequest, 10 | SendMessageRequest, 11 | ShipmentInfoRequest 12 | } from '../../../../types/index.js'; 13 | 14 | /** 15 | * Post-Order Inquiry API 16 | */ 17 | export default class Inquiry extends Restful { 18 | 19 | static id = 'Inquiry'; 20 | 21 | get basePath(): string { 22 | return '/post-order/v2'; 23 | } 24 | 25 | get useIaf() { 26 | return true; 27 | } 28 | 29 | /** 30 | * Check if a buyer is eligible to open an inquiry on an order. 31 | * 32 | * @param payload the CheckInquiryEligibilityRequest 33 | */ 34 | public checkInquiryEligibility(payload: CheckInquiryEligibilityRequest) { 35 | return this.post(`/inquiry/check_eligibility`, payload); 36 | } 37 | 38 | /** 39 | * Close an inquiry for the buyer 40 | * 41 | * @param inquiryId The unique ID of the inquiry to be closed. 42 | * @param payload the BuyerCloseInquiryRequest 43 | */ 44 | public closeInquiry(inquiryId: string, payload?: BuyerCloseInquiryRequest) { 45 | inquiryId = encodeURIComponent(inquiryId); 46 | if (typeof payload?.closeReason === 'string') { 47 | payload.closeReason = payload.closeReason.trim(); 48 | } 49 | return this.post(`/inquiry/${inquiryId}/close`, payload); 50 | } 51 | 52 | /** 53 | * Buyer confirms the refund from an inquiry was received 54 | * 55 | * @param inquiryId The unique identifier of a case. 56 | */ 57 | public confirmInquiryRefund(inquiryId: string) { 58 | inquiryId = encodeURIComponent(inquiryId); 59 | return this.post(`/inquiry/${inquiryId}/confirm_refund`); 60 | } 61 | 62 | /** 63 | * Create an inquiry for the buyer. 64 | * 65 | * @param payload the CreateInquiryRequest 66 | */ 67 | public createInquiry(payload: CreateInquiryRequest) { 68 | if (typeof payload.desiredOutcome === 'string') { 69 | payload.desiredOutcome = payload.desiredOutcome.trim(); 70 | } 71 | return this.post(`/inquiry`, payload); 72 | } 73 | 74 | /** 75 | * Escalate an inquiry to an INR case. 76 | * 77 | * @param inquiryId the unique identifier of the inquiry to be escalated. 78 | * @param payload the EscalateInquiryRequest 79 | */ 80 | public escalateInquiry(inquiryId: string, payload: EscalateInquiryRequest) { 81 | inquiryId = encodeURIComponent(inquiryId); 82 | payload.escalateInquiryReason = payload.escalateInquiryReason.trim(); 83 | return this.post(`/inquiry/${inquiryId}/escalate`, payload); 84 | } 85 | 86 | /** 87 | * Retrieve the history and details related to a specific inquiry. 88 | * 89 | * @param inquiryId the unique ID of the inquiry for which details and history are to be retrieved. 90 | */ 91 | public getInquiry(inquiryId: string) { 92 | inquiryId = encodeURIComponent(inquiryId); 93 | return this.get(`/inquiry/${inquiryId}`); 94 | } 95 | 96 | /** 97 | * Issue a refund for an inquiry. 98 | * 99 | * @param inquiryId the unique ID of the inquiry for which a refund is to be issued. 100 | * @param payload the InquiryVoluntaryRefundRequest 101 | */ 102 | public issueInquiryRefund(inquiryId: string, payload?: InquiryVoluntaryRefundRequest) { 103 | inquiryId = encodeURIComponent(inquiryId); 104 | return this.post(`/inquiry/${inquiryId}/issue_refund`, payload); 105 | } 106 | 107 | /** 108 | * Provide refund information about an inquiry to the buyer. 109 | * 110 | * @param inquiryId The unique ID of the inquiry for which to provide refund information. 111 | * @param payload the InquiryVoluntaryRefundRequest 112 | */ 113 | public provideInquiryRefundInfo(inquiryId: string, payload: SellerProvideRefundInfoRequest) { 114 | inquiryId = encodeURIComponent(inquiryId); 115 | return this.post(`/inquiry/${inquiryId}/provide_refund_info`, payload); 116 | } 117 | 118 | /** 119 | * Provide shipment information for an inquiry. 120 | * 121 | * @param inquiryId The unique ID of the inquiry for which to provide shipment information. 122 | * @param payload the ShipmentInfoRequest 123 | */ 124 | public provideInquiryShipmentInfo(inquiryId: string, payload?: ShipmentInfoRequest) { 125 | inquiryId = encodeURIComponent(inquiryId); 126 | return this.post(`/inquiry/${inquiryId}/provide_shipment_info`, payload); 127 | } 128 | 129 | /** 130 | * This call is used to search for inquiries using multiple filter types. 131 | * 132 | * @param params the InquirySearchParams 133 | */ 134 | public search(params?: InquirySearchParams) { 135 | return this.get(`/inquiry/search`, { 136 | params 137 | }); 138 | } 139 | 140 | /** 141 | * Contact the buyer or seller about an inquiry. 142 | * 143 | * @param inquiryId The unique ID of the inquiry being discussed. 144 | * @param payload the SendMessageRequest 145 | */ 146 | public sendInquiryMessage(inquiryId: string, payload: SendMessageRequest) { 147 | inquiryId = encodeURIComponent(inquiryId); 148 | return this.post(`/inquiry/${inquiryId}/send_message`, payload); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/api/restful/sell/account/v2.ts: -------------------------------------------------------------------------------- 1 | import {RateTableUpdate, UpdatePayoutPercentageRequest} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/sell_account_v2_oas3.js'; 3 | 4 | import Restful, {OpenApi} from '../../index.js'; 5 | 6 | /** 7 | * This API allows sellers to retrieve and manage their custom shipping rate tables. 8 | */ 9 | export default class AccountV2 extends Restful implements OpenApi { 10 | static id = 'AccountV2'; 11 | 12 | get basePath(): string { 13 | return '/sell/account/v2'; 14 | } 15 | 16 | /** 17 | * This method retrieves an existing rate table identified by the rate_table_id path parameter. 18 | * @param rateTableId This path parameter is the unique identifier for the shipping rate table to retrieve. 19 | */ 20 | public getRateTable(rateTableId: string) { 21 | rateTableId = encodeURIComponent(rateTableId); 22 | return this.get(`/rate_table/${rateTableId}`); 23 | } 24 | 25 | /** 26 | * Request to update the shipping costs for the identified shipping rate table. 27 | * @param rateTableId This path parameter is the unique identifier for the shipping rate table to update. 28 | * @param body This request payload contains the shipping costs to update for the rate table. 29 | */ 30 | public updateShippingCost(rateTableId: string, body: RateTableUpdate) { 31 | rateTableId = encodeURIComponent(rateTableId); 32 | return this.post(`/rate_table/${rateTableId}/update_shipping_cost`, body); 33 | } 34 | 35 | /** 36 | * This method returns details on two payment instruments defined on a seller's account, including the ID, type, status, nickname, last four digits of the account number, and payout percentage for the instruments. 37 | */ 38 | public getPayoutSettings() { 39 | return this.get('/payout_settings'); 40 | } 41 | 42 | /** 43 | * This method allows sellers in mainland China to configure the split-payout percentage for two payout instruments available for seller payouts. For example, a seller can split payouts to have 70% of the payout go to a bank account and 30% go to a Payoneer account. 44 | * @param body 45 | */ 46 | public updatePayoutPercentage(body: UpdatePayoutPercentageRequest) { 47 | return this.post(`/payout_settings/update_percentage`, body); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/api/restful/sell/analytics/index.ts: -------------------------------------------------------------------------------- 1 | import {Metric} from '../../../../enums/index.js'; 2 | import {operations} from '../../../../types/restful/specs/sell_analytics_v1_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | /** 6 | * The Analytics API provides information about a seller's business performance. 7 | */ 8 | export default class Analytics extends Restful implements OpenApi { 9 | 10 | static id = 'Analytics'; 11 | 12 | get basePath(): string { 13 | return '/sell/analytics/v1'; 14 | } 15 | 16 | /** 17 | * This call retrieves all the profiles for the associated seller. 18 | */ 19 | public findSellerStandardsProfiles() { 20 | return this.get(`/seller_standards_profile`); 21 | } 22 | 23 | /** 24 | * This call retrieves seller's profiles based on a program or cycle. 25 | * 26 | * @param program Specifies the program of the requested profile. 27 | * @param cycle Specifies the cycle of the requested profile. 28 | */ 29 | public getSellerStandardsProfile(program: string, cycle: string) { 30 | program = encodeURIComponent(program); 31 | cycle = encodeURIComponent(cycle); 32 | return this.get(`/seller_standards_profile/${program}/${cycle}`); 33 | } 34 | 35 | /** 36 | * This call returns a report that details the user-traffic a seller's listings receives. 37 | * 38 | * @param dimension Specifies the basis of the report data. 39 | * @param filter Limits the report data returned. 40 | * @param metric Specifies a comma separated list of the metrics you want included in the report. 41 | * @param sort Specifies a single metric to be sorted and whether you want to sort in ascending or descending order. 42 | */ 43 | public getTrafficReport({dimension, filter, metric, sort}: 44 | { dimension?: string, filter?: string, metric?: string | Metric | `${Metric}`, sort?: string } = {}) { 45 | return this.get(`/traffic_report`, { 46 | params: { 47 | dimension, 48 | filter, 49 | metric, 50 | sort 51 | } 52 | }); 53 | } 54 | 55 | /** 56 | * Use this method to retrieve a seller's performance and rating for the customer service metric. 57 | * 58 | * @param customerServiceMetricType Use this path parameter to specify the type of customer service metrics and benchmark data you want returned for the seller. 59 | * @param evaluationType Use this query parameter to specify the Marketplace ID to evaluate for the customer service metrics and benchmark data. 60 | */ 61 | public getCustomerServiceMetric(customerServiceMetricType: string, evaluationType: string) { 62 | return this.get(`/customer_service_metric/${customerServiceMetricType}/${evaluationType}`); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/api/restful/sell/compliance/index.ts: -------------------------------------------------------------------------------- 1 | import {SuppressViolationRequest} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/sell_compliance_v1_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | /** 6 | * Service for providing the compliance violations of seller account/listings 7 | */ 8 | export default class Compliance extends Restful implements OpenApi { 9 | 10 | static id = 'Compliance'; 11 | 12 | get basePath(): string { 13 | return '/sell/compliance/v1'; 14 | } 15 | 16 | /** 17 | * This call returns listing violation counts for a seller. 18 | * 19 | * @param complianceType A user passes in one or more compliance type values through this query parameter. 20 | */ 21 | public getListingViolationsSummary(complianceType?: string) { 22 | return this.get(`/listing_violation_summary`, { 23 | params: { 24 | compliance_type: complianceType 25 | } 26 | }); 27 | } 28 | 29 | /** 30 | * This call returns specific listing violations for five different compliance types. 31 | * 32 | * @param complianceType A user passes in one or more compliance type values through this query parameter. 33 | * @param offset The first policy violation to return based on its position in the collection of listing 34 | * violations. 35 | * @param listingId 36 | * @param limit This query parameter is used if the user wants to set a limit on the number of listing violations 37 | * that are returned in the current result set. 38 | */ 39 | public getListingViolations({complianceType, offset, listingId, limit}: 40 | { complianceType?: string, offset?: number, listingId?: string, limit?: number } = {}) { 41 | return this.get(`/listing_violation`, { 42 | params: { 43 | compliance_type: complianceType, 44 | offset, 45 | listing_id: listingId, 46 | limit 47 | } 48 | }); 49 | } 50 | 51 | /** 52 | * This call suppresses a listing violation for a specific listing. Only listing violations in the AT_RISK state (returned in the violations.complianceState field of the getListingViolations call) can be suppressed. 53 | * 54 | * @param body SuppressViolationRequest 55 | */ 56 | public suppressViolation(body: SuppressViolationRequest) { 57 | return this.post(`/suppress_listing_violation`, body); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/api/restful/sell/finances/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/sell_finances_v1_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * The Finances API is used by sellers in eBay's managed payments program to retrieve seller payout information. 6 | * 7 | * https://api.ebay.com/oauth/api_scope/sell.finances 8 | * 9 | */ 10 | export default class Finances extends Restful implements OpenApi { 11 | 12 | static id = 'Finances'; 13 | 14 | get basePath(): string { 15 | return '/sell/finances/v1'; 16 | } 17 | 18 | get subdomain(): string { 19 | return 'apiz'; 20 | } 21 | 22 | /** 23 | * Use this call to retrieve the details of a specific seller payout. 24 | * 25 | * @param payoutId The unique identifier of the payout. 26 | */ 27 | public getPayout(payoutId: string) { 28 | payoutId = encodeURIComponent(payoutId); 29 | return this.get(`/payout/${payoutId}`); 30 | } 31 | 32 | /** 33 | * Use this call to search for and retrieve one or more payout based on their payout date, 34 | * or payout status using the filter parameter. 35 | * 36 | * @param filter One or more comma-separated criteria for narrowing down the collection of payout returned by this 37 | * call. 38 | * @param limit The number of payouts to return per page of the result set. 39 | * @param offset Specifies the number of payouts to skip in the result set before returning the first payout in the 40 | * paginated response. 41 | * @param sort Allows sorting by payouts date in descending order with '-payoutDate' (default) and ascending with 'payoutDate' 42 | */ 43 | public getPayouts({ 44 | filter, 45 | limit, 46 | offset, 47 | sort, 48 | }: { 49 | filter?: string; 50 | limit?: number; 51 | offset?: number; 52 | sort?: 'payoutDate' | '-payoutDate'; 53 | } = {}) { 54 | return this.get(`/payout`, { 55 | params: { 56 | filter, 57 | limit, 58 | offset, 59 | sort, 60 | }, 61 | }); 62 | } 63 | 64 | /** 65 | * Search for and retrieve the details of multiple payouts. 66 | * * 67 | * @param filter One or more comma-separated criteria for narrowing down the collection of payout returned by this 68 | * call. 69 | */ 70 | public getPayoutSummary({ 71 | filter, 72 | }: { 73 | filter?: string; 74 | } = {}) { 75 | return this.get(`/payout_summary`, {params: {filter}}); 76 | } 77 | 78 | /** 79 | * Retrieve details of one or more monetary transactions. 80 | * @param filter One or more comma-separated criteria for narrowing down the collection of transaction returned by this 81 | * call. 82 | * @param limit The number of transaction to return per page of the result set. 83 | * @param offset Specifies the number of payouts to skip in the result set before returning the first transaction in the 84 | * paginated response. 85 | * @param sort Allows sorting by transaction date in descending order with '-transactionDate' (default) and ascending with 'transactionDate' 86 | */ 87 | public getTransactions({ 88 | filter, 89 | limit, 90 | offset, 91 | sort 92 | }: { 93 | filter?: string; 94 | limit?: number; 95 | offset?: number; 96 | sort?: 'transactionDate' | '-transactionDate', 97 | } = {}) { 98 | return this.get(`/transaction`, { 99 | params: { 100 | filter, 101 | limit, 102 | offset, 103 | sort, 104 | }, 105 | }); 106 | } 107 | 108 | /** 109 | * Retrieve total counts and values of the seller's order sales, seller credits, buyer refunds, and payment holds. 110 | * @param filter One or more comma-separated criteria for narrowing down the collection of transaction returned by this 111 | * call. 112 | * @param limit The number of transaction to return per page of the result set. 113 | */ 114 | public getTransactionSummary({ 115 | filter, 116 | }: { 117 | filter?: string; 118 | } = {}) { 119 | return this.get(`/transaction_summary`, { 120 | params: { 121 | filter, 122 | }, 123 | }); 124 | } 125 | 126 | /** 127 | * Retrieve detailed information on a TRANSFER transaction type. 128 | * 129 | * @param transferId The unique identifier of the transfer. 130 | */ 131 | public getTransfer(transferId: string) { 132 | transferId = encodeURIComponent(transferId); 133 | return this.get(`/transfer/${transferId}`); 134 | } 135 | 136 | /** 137 | * Retrieve all pending funds that have not yet been distributed through a seller payout. 138 | */ 139 | public getSellerFundsSummary() { 140 | return this.get(`/seller_funds_summary`); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/api/restful/sell/index.ts: -------------------------------------------------------------------------------- 1 | import AccountV1 from './account/v1.js'; 2 | import AccountV2 from './account/v2.js'; 3 | import Analytics from './analytics/index.js'; 4 | import Compliance from './compliance/index.js'; 5 | import Finances from './finances/index.js'; 6 | import Fulfillment from './fulfillment/index.js'; 7 | import Inventory from './inventory/index.js'; 8 | import Marketing from './marketing/index.js'; 9 | import Metadata from './metadata/index.js'; 10 | import Recommendation from './recommendation/index.js'; 11 | import Feed from './feed/index.js'; 12 | import Logistics from './logistics/index.js'; 13 | import Negotiation from './negotiation/index.js'; 14 | import Listing from './listing/index.js'; 15 | 16 | export type Sell = { 17 | account: AccountV1, 18 | accountV2: AccountV2, 19 | analytics: Analytics, 20 | compliance: Compliance, 21 | fulfillment: Fulfillment, 22 | inventory: Inventory, 23 | marketing: Marketing, 24 | metadata: Metadata, 25 | recommendation: Recommendation, 26 | finances: Finances 27 | feed: Feed, 28 | logistics: Logistics, 29 | negotiation: Negotiation, 30 | listing: Listing 31 | }; 32 | 33 | export { 34 | AccountV1, 35 | AccountV2, 36 | Compliance, 37 | Analytics, 38 | Fulfillment, 39 | Inventory, 40 | Marketing, 41 | Metadata, 42 | Recommendation, 43 | Finances, 44 | Feed, 45 | Logistics, 46 | Negotiation, 47 | Listing 48 | }; 49 | -------------------------------------------------------------------------------- /src/api/restful/sell/listing/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/sell_listing_v1_beta_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * Enables a seller adding an ad or item on a Partner's site to automatically create an eBay listing draft using the item details from the Partner's site. 6 | */ 7 | export default class Listing extends Restful implements OpenApi { 8 | 9 | static id = 'Listing'; 10 | 11 | get basePath(): string { 12 | return '/sell/listing/v1_beta'; 13 | } 14 | 15 | /** 16 | * This call gives Partners the ability to create an eBay draft of a item for their seller using information from their site. 17 | * 18 | * @param data The ItemDraft 19 | */ 20 | public createItemDraft(data?: any) { 21 | return this.post(`/item_draft/`, data); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/api/restful/sell/logistics/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/sell_logistics_v1_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * The Logistics API resources offer the following capabilities:
  • shipping_quote – Consolidates into a list a set of live shipping rates, or quotes, from which you can select a rate to ship a package. 6 | */ 7 | export default class Logistics extends Restful implements OpenApi { 8 | 9 | static id = 'Logistics'; 10 | 11 | get basePath(): string { 12 | return '/sell/logistics/v1_beta'; 13 | } 14 | 15 | /** 16 | * The createShippingQuote method returns a shipping quote that contains a list of live "rates." 17 | * 18 | * @param data The ShippingQuoteRequest 19 | */ 20 | public createShippingQuote(data: any) { 21 | return this.post(`/shipping_quote`, data); 22 | } 23 | 24 | /** 25 | * This method retrieves the complete details of the shipping quote associated with the specified shippingQuoteId value. 26 | * 27 | * @param shippingQuoteId This path parameter specifies the unique eBay-assigned ID of the shipping quote you want to retrieve. 28 | */ 29 | public getShippingQuote(shippingQuoteId: string) { 30 | shippingQuoteId = encodeURIComponent(shippingQuoteId); 31 | return this.get(`/shipping_quote/${shippingQuoteId}`); 32 | } 33 | 34 | /** 35 | * This method creates a "shipment" based on the shippingQuoteId and rateId values supplied in the request. 36 | * 37 | * @param data The CreateShipmentFromQuoteRequest 38 | */ 39 | public createFromShippingQuote(data: any) { 40 | return this.post(`/shipment/create_from_shipping_quote`, data); 41 | } 42 | 43 | /** 44 | * This method retrieves the shipment details for the specified shipment ID. 45 | * 46 | * @param shipmentId This path parameter specifies the unique eBay-assigned ID of the shipment you want to retrieve. 47 | */ 48 | public getShipment(shipmentId: any) { 49 | return this.get(`/shipment/${shipmentId}`); 50 | } 51 | 52 | /** 53 | * This method returns the shipping label file that was generated for the shipmentId value specified in the request. 54 | * 55 | * @param shipmentId This path parameter specifies the unique eBay-assigned ID of the shipment associated with the shipping label you want to download. 56 | */ 57 | public downloadLabelFile(shipmentId: any) { 58 | return this.get(`/shipment/${shipmentId}/download_label_file`); 59 | } 60 | 61 | /** 62 | * This method cancels the shipment associated with the specified shipment ID and the associated shipping label is deleted. 63 | * 64 | * @param shipmentId This path parameter specifies the unique eBay-assigned ID of the shipment to be canceled. 65 | */ 66 | public cancelShipment(shipmentId: any) { 67 | return this.post(`/shipment/${shipmentId}/cancel`); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/api/restful/sell/negotiation/index.ts: -------------------------------------------------------------------------------- 1 | import {operations} from '../../../../types/restful/specs/sell_negotiation_v1_oas3.js'; 2 | import Restful, {OpenApi} from '../../index.js'; 3 | 4 | /** 5 | * The Negotiations API gives sellers the ability to proactively send discount offers to buyers who have shown an "interest" in their listings. 6 | */ 7 | export default class Negotiation extends Restful implements OpenApi { 8 | 9 | static id = 'Negotiation'; 10 | 11 | get basePath(): string { 12 | return '/sell/negotiation/v1'; 13 | } 14 | 15 | /** 16 | * This method evaluates a seller's current listings and returns the set of IDs that are eligible for a seller-initiated discount offer to a buyer. 17 | * 18 | * @param limit This query parameter specifies the maximum number of items to return from the result set on a page in the paginated response. 19 | * @param offset This query parameter specifies the number of results to skip in the result set before returning the first result in the paginated response. 20 | */ 21 | public findEligibleItems({limit, offset}: { limit?: string, offset?: string } = {}) { 22 | return this.get(`/find_eligible_items`, { 23 | params: { 24 | limit, 25 | offset 26 | } 27 | }); 28 | } 29 | 30 | /** 31 | * This method sends eligible buyers offers to purchase items in a listing at a discount. 32 | * 33 | * @param data The CreateOffersRequest 34 | */ 35 | public sendOfferToInterestedBuyers(data: any) { 36 | return this.post(`/send_offer_to_interested_buyers`, data); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/api/restful/sell/recommendation/index.ts: -------------------------------------------------------------------------------- 1 | import {FindListingRecommendationRequest} from '../../../../types/index.js'; 2 | import {operations} from '../../../../types/restful/specs/sell_recommendation_v1_oas3.js'; 3 | import Restful, {OpenApi} from '../../index.js'; 4 | 5 | 6 | /** 7 | * The Recommendation API returns information that sellers can use to optimize the configuration of their 8 | * listings on eBay. 9 | */ 10 | export default class Recommendation extends Restful implements OpenApi { 11 | 12 | static id = 'Recommendation'; 13 | 14 | get basePath(): string { 15 | return '/sell/recommendation/v1'; 16 | } 17 | 18 | /** 19 | * The find method returns recommendations and information that sellers can use to optimize their listing 20 | * configurations. 21 | * 22 | * @param filter Provide a list of key-value pairs to specify the criteria you want to use to filter the response. 23 | * @param limit Use this query parameter to set the maximum number of ads to return on a page from the paginated 24 | * response. Default: 10 Maximum: 500 25 | * @param offset Specifies the number of ads to skip in the result set before returning the first ad in the 26 | * paginated response. 27 | * @param body FindListingRecommendationRequest 28 | */ 29 | public findListingRecommendations({filter, limit, offset}: { filter?: string, limit?: number, offset?: number } = {}, 30 | body?: FindListingRecommendationRequest 31 | ) { 32 | return this.post(`/find`, { 33 | data: body, 34 | params: { 35 | filter, 36 | limit, 37 | offset 38 | } 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/api/traditional/clientAlerts/index.ts: -------------------------------------------------------------------------------- 1 | import {EventType} from './types.js'; 2 | 3 | // https://developer.ebay.com/devzone/client-alerts/docs/CallRef/index.html 4 | enum calls { 5 | GetPublicAlerts, 6 | GetUserAlerts, 7 | Login, 8 | Logout 9 | } 10 | 11 | export { 12 | EventType 13 | }; 14 | 15 | export default calls; 16 | -------------------------------------------------------------------------------- /src/api/traditional/clientAlerts/types.ts: -------------------------------------------------------------------------------- 1 | enum EventType { 2 | AskSellerQuestion = 'AskSellerQuestion', 3 | BestOffer = 'BestOffer', 4 | BestOfferDeclined = 'BestOfferDeclined', 5 | BestOfferPlaced = 'BestOfferPlaced', 6 | BidPlaced = 'BidPlaced', 7 | BidReceived = 'BidReceived', 8 | CounterOfferReceived = 'CounterOfferReceived', 9 | CustomCode = 'CustomCode', 10 | EndOfAuction = 'EndOfAuction', 11 | FeedbackLeft = 'FeedbackLeft', 12 | FeedbackReceived = 'FeedbackReceived', 13 | FeedbackStarChanged = 'FeedbackStarChanged', 14 | FixedPriceEndOfTransaction = 'FixedPriceEndOfTransaction', 15 | FixedPriceTransaction = 'FixedPriceTransaction', 16 | ItemAddedToWatchList = 'ItemAddedToWatchList', 17 | ItemEnded = 'ItemEnded', 18 | ItemListed = 'ItemListed', 19 | ItemLost = 'ItemLost', 20 | ItemMarkedPaid = 'ItemMarkedPaid', 21 | ItemMarkedShipped = 'ItemMarkedShipped', 22 | ItemRemovedFromWatchList = 'ItemRemovedFromWatchList', 23 | ItemSold = 'ItemSold', 24 | ItemUnsold = 'ItemUnsold', 25 | ItemWon = 'ItemWon', 26 | OutBid = 'OutBid', 27 | PriceChange = 'PriceChange', 28 | SecondChanceOffer = 'SecondChanceOffer', 29 | WatchedItemEndingSoon = 'WatchedItemEndingSoon' 30 | } 31 | 32 | export {EventType}; 33 | -------------------------------------------------------------------------------- /src/api/traditional/finding/index.ts: -------------------------------------------------------------------------------- 1 | enum calls { 2 | findCompletedItems, 3 | findItemsAdvanced, 4 | findItemsByCategory, 5 | findItemsByKeywords, 6 | findItemsByProduct, 7 | findItemsIneBayStores, 8 | getHistograms, 9 | getSearchKeywordsRecommendation, 10 | getVersion 11 | } 12 | 13 | export default calls; 14 | -------------------------------------------------------------------------------- /src/api/traditional/merchandising/index.ts: -------------------------------------------------------------------------------- 1 | enum calls { 2 | getMostWatchedItems, 3 | getRelatedCategoryItems, 4 | getSimilarItems, 5 | getVersion 6 | } 7 | 8 | export default calls; 9 | -------------------------------------------------------------------------------- /src/api/traditional/shopping/index.ts: -------------------------------------------------------------------------------- 1 | // https://developer.ebay.com/devzone/shopping/docs/callref/index.html 2 | enum calls { 3 | FindProducts, 4 | GetCategoryInfo, 5 | GeteBayTime, 6 | GetItemStatus, 7 | GetMultipleItems, 8 | GetShippingCosts, 9 | GetSingleItem, 10 | GetUserProfile 11 | } 12 | 13 | export default calls; 14 | -------------------------------------------------------------------------------- /src/api/traditional/trading/index.ts: -------------------------------------------------------------------------------- 1 | enum calls { 2 | AddDispute, 3 | AddDisputeResponse, 4 | AddFixedPriceItem, 5 | AddItem, 6 | AddItemFromSellingManagerTemplate, 7 | AddItems, 8 | AddMemberMessageAAQToPartner, 9 | AddMemberMessageRTQ, 10 | AddMemberMessagesAAQToBidder, 11 | AddOrder, 12 | AddSecondChanceItem, 13 | AddSellingManagerInventoryFolder, 14 | AddSellingManagerProduct, 15 | AddSellingManagerTemplate, 16 | AddToItemDescription, 17 | AddToWatchList, 18 | AddTransactionConfirmationItem, 19 | CompleteSale, 20 | ConfirmIdentity, 21 | DeleteMyMessages, 22 | DeleteSellingManagerInventoryFolder, 23 | DeleteSellingManagerItemAutomationRule, 24 | DeleteSellingManagerProduct, 25 | DeleteSellingManagerTemplate, 26 | DeleteSellingManagerTemplateAutomationRule, 27 | DisableUnpaidItemAssistance, 28 | EndFixedPriceItem, 29 | EndItem, 30 | EndItems, 31 | ExtendSiteHostedPictures, 32 | FetchToken, 33 | GetAccount, 34 | GetAdFormatLeads, 35 | GetAllBidders, 36 | GetApiAccessRules, 37 | GetBestOffers, 38 | GetBidderList, 39 | GetCategories, 40 | GetCategoryFeatures, 41 | GetCategoryMappings, 42 | GetCategorySpecifics, 43 | GetChallengeToken, 44 | GetCharities, 45 | GetClientAlertsAuthToken, 46 | GetContextualKeywords, 47 | GetDescriptionTemplates, 48 | GetDispute, 49 | GeteBayDetails, 50 | GeteBayOfficialTime, 51 | GetFeedback, 52 | GetItem, 53 | GetItemsAwaitingFeedback, 54 | GetItemShipping, 55 | GetItemTransactions, 56 | GetMemberMessages, 57 | GetMessagePreferences, 58 | GetMyeBayBuying, 59 | GetMyeBayReminders, 60 | GetMyeBaySelling, 61 | GetMyMessages, 62 | GetNotificationPreferences, 63 | GetNotificationsUsage, 64 | GetOrders, 65 | GetOrderTransactions, 66 | GetPromotionalSaleDetails, 67 | GetSellerDashboard, 68 | GetSellerEvents, 69 | GetSellerList, 70 | GetSellerTransactions, 71 | GetSellingManagerAlerts, 72 | GetSellingManagerEmailLog, 73 | GetSellingManagerInventory, 74 | GetSellingManagerInventoryFolder, 75 | GetSellingManagerItemAutomationRule, 76 | GetSellingManagerSaleRecord, 77 | GetSellingManagerSoldListings, 78 | GetSellingManagerTemplateAutomationRule, 79 | GetSellingManagerTemplates, 80 | GetSessionID, 81 | GetShippingDiscountProfiles, 82 | GetStore, 83 | GetStoreCategoryUpdateStatus, 84 | GetStoreCustomPage, 85 | GetStoreOptions, 86 | GetStorePreferences, 87 | GetSuggestedCategories, 88 | GetTaxTable, 89 | GetTokenStatus, 90 | GetUser, 91 | GetUserContactDetails, 92 | GetUserDisputes, 93 | GetUserPreferences, 94 | GetVeROReasonCodeDetails, 95 | GetVeROReportStatus, 96 | LeaveFeedback, 97 | MoveSellingManagerInventoryFolder, 98 | PlaceOffer, 99 | RelistFixedPriceItem, 100 | RelistItem, 101 | RemoveFromWatchList, 102 | RespondToBestOffer, 103 | RespondToFeedback, 104 | ReviseCheckoutStatus, 105 | ReviseFixedPriceItem, 106 | ReviseInventoryStatus, 107 | ReviseItem, 108 | ReviseMyMessages, 109 | ReviseMyMessagesFolders, 110 | ReviseSellingManagerInventoryFolder, 111 | ReviseSellingManagerProduct, 112 | ReviseSellingManagerSaleRecord, 113 | ReviseSellingManagerTemplate, 114 | RevokeToken, 115 | SaveItemToSellingManagerTemplate, 116 | SellerReverseDispute, 117 | SendInvoice, 118 | SetMessagePreferences, 119 | SetNotificationPreferences, 120 | SetPromotionalSale, 121 | SetPromotionalSaleListings, 122 | SetSellingManagerFeedbackOptions, 123 | SetSellingManagerItemAutomationRule, 124 | SetSellingManagerTemplateAutomationRule, 125 | SetShippingDiscountProfiles, 126 | SetStore, 127 | SetStoreCategories, 128 | SetStoreCustomPage, 129 | SetStorePreferences, 130 | SetTaxTable, 131 | SetUserNotes, 132 | SetUserPreferences, 133 | UploadSiteHostedPictures, 134 | ValidateChallengeInput, 135 | ValidateTestUserRegistration, 136 | VerifyAddFixedPriceItem, 137 | VerifyAddItem, 138 | VerifyAddSecondChanceItem, 139 | VerifyRelistItem, 140 | VeROReportItems 141 | } 142 | 143 | export default calls; 144 | -------------------------------------------------------------------------------- /src/auth/authNAuth.ts: -------------------------------------------------------------------------------- 1 | import debug from 'debug'; 2 | import Base from '../api/base.js'; 3 | import XMLRequest from '../api/traditional/XMLRequest.js'; 4 | import {IEBayApiRequest} from '../request.js'; 5 | import {AppConfig} from '../types/index.js'; 6 | 7 | const log = debug('ebay:authNAuth'); 8 | 9 | export type AuthToken = { 10 | eBayAuthToken: string, 11 | Timestamp?: string, 12 | HardExpirationTime?: string 13 | }; 14 | 15 | export default class AuthNAuth extends Base { 16 | 17 | public static readonly SIGNIN_ENDPOINT = { 18 | sandbox: 'https://signin.sandbox.ebay.com/ws/eBayISAPI.dll', 19 | production: 'https://signin.ebay.com/ws/eBayISAPI.dll' 20 | }; 21 | 22 | public static readonly API_ENDPOINT = { 23 | production: 'https://api.ebay.com/ws/api.dll', 24 | sandbox: 'https://api.sandbox.ebay.com/ws/api.dll' 25 | }; 26 | 27 | public static generateAuthUrl(sandbox: boolean, ruName: string, sessionId: string, prompt = false) { 28 | return [ 29 | sandbox ? AuthNAuth.SIGNIN_ENDPOINT.sandbox : AuthNAuth.SIGNIN_ENDPOINT.production, 30 | '?SignIn', 31 | '&RuName=', encodeURIComponent(ruName), 32 | '&SessID=', encodeURIComponent(sessionId), 33 | prompt ? '&prompt=login' : '' 34 | ].join(''); 35 | } 36 | 37 | private authToken: AuthToken | null = null; 38 | 39 | constructor(config: AppConfig, req?: IEBayApiRequest) { 40 | super(config, req); 41 | 42 | if (this.config.authToken) { 43 | this.setAuthToken(this.config.authToken); 44 | } 45 | } 46 | 47 | get apiEndpoint() { 48 | return this.config.sandbox ? AuthNAuth.API_ENDPOINT.sandbox : AuthNAuth.API_ENDPOINT.production; 49 | } 50 | 51 | /** 52 | * Generates URL for consent page landing. 53 | * 54 | * @param ruName RuName 55 | */ 56 | public async getSessionIdAndAuthUrl(ruName?: string) { 57 | if (!this.config.devId) { 58 | throw new Error('DevId is required.'); 59 | } 60 | 61 | ruName = ruName || this.config.ruName; 62 | if (!ruName) { 63 | throw new Error('RuName is required.'); 64 | } 65 | 66 | const xmlApi = new XMLRequest('GetSessionID', { 67 | RuName: ruName 68 | }, this.getRequestConfig('GetSessionID'), this.req); 69 | 70 | const data = await xmlApi.request(); 71 | 72 | log('GetSessionID data', data); 73 | 74 | return { 75 | sessionId: data.SessionID, 76 | url: AuthNAuth.generateAuthUrl(this.config.sandbox, ruName, data.SessionID) 77 | }; 78 | } 79 | 80 | public async mintToken(sessionId: string) { 81 | if (!this.config.devId) { 82 | throw new Error('DevId is required.'); 83 | } 84 | 85 | const xmlApi = new XMLRequest('FetchToken', { 86 | SessionID: sessionId 87 | }, this.getRequestConfig('FetchToken'), this.req); 88 | 89 | try { 90 | return await xmlApi.request(); 91 | } catch (error) { 92 | log('Fetch auth token failed', error); 93 | throw error; 94 | } 95 | } 96 | 97 | public async obtainToken(sessionId: string) { 98 | const token = await this.mintToken(sessionId); 99 | log('Obtain auth token', token) 100 | this.setAuthToken(token); 101 | 102 | return token; 103 | } 104 | 105 | public setAuthToken(authToken: AuthToken | string | null) { 106 | if (typeof authToken === 'string') { 107 | this.authToken = { 108 | eBayAuthToken: authToken 109 | }; 110 | } else { 111 | this.authToken = authToken; 112 | } 113 | } 114 | 115 | public getAuthToken(): AuthToken | null { 116 | if (!this.authToken) { 117 | return null; 118 | } 119 | 120 | return { 121 | ...this.authToken 122 | }; 123 | } 124 | 125 | get eBayAuthToken() { 126 | return this.authToken?.eBayAuthToken ?? null; 127 | } 128 | 129 | public getRequestConfig(callName: string) { 130 | if (typeof this.config.siteId !== 'number') { 131 | throw new Error('"siteId" is required for Auth\'n\'Auth.'); 132 | } 133 | 134 | return { 135 | useIaf: false, 136 | xmlns: 'urn:ebay:apis:eBLBaseComponents', 137 | endpoint: this.apiEndpoint, 138 | headers: { 139 | 'X-EBAY-API-CALL-NAME': callName, 140 | 'X-EBAY-API-CERT-NAME': this.config.certId, 141 | 'X-EBAY-API-APP-NAME': this.config.appId, 142 | 'X-EBAY-API-DEV-NAME': this.config.devId, 143 | 'X-EBAY-API-SITEID': this.config.siteId, 144 | 'X-EBAY-API-COMPATIBILITY-LEVEL': 967 145 | } 146 | }; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/auth/index.ts: -------------------------------------------------------------------------------- 1 | import Base from '../api/base.js'; 2 | import {IEBayApiRequest} from '../request.js'; 3 | import {AppConfig} from '../types/index.js'; 4 | import AuthNAuth from './authNAuth.js'; 5 | import OAuth2 from './oAuth2.js'; 6 | 7 | /** 8 | * Container with Auth'N'Auth and OAuth2. 9 | */ 10 | export default class Auth extends Base { 11 | public readonly authNAuth: AuthNAuth; 12 | public readonly oAuth2: OAuth2; 13 | // tslint:disable-next-line:variable-name 14 | public readonly OAuth2: OAuth2; 15 | 16 | constructor(config: AppConfig, req: IEBayApiRequest) { 17 | super(config, req); 18 | this.authNAuth = new AuthNAuth(this.config, this.req); 19 | this.OAuth2 = new OAuth2(this.config, this.req); 20 | this.oAuth2 = this.OAuth2; 21 | } 22 | 23 | public async getHeaderAuthorization(useIaf: boolean) { 24 | if (this.authNAuth.eBayAuthToken) { 25 | return { 26 | Authorization: 'Token ' + this.authNAuth.eBayAuthToken 27 | } 28 | } 29 | 30 | const accessToken = await this.OAuth2.getAccessToken(); 31 | return { 32 | Authorization: (useIaf ? 'IAF ' : 'Bearer ') + accessToken 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/eBayApi.ts: -------------------------------------------------------------------------------- 1 | import ApiFactory from './api/apiFactory.js'; 2 | import Api from './api/index.js'; 3 | import {Buy} from './api/restful/buy/index.js'; 4 | import {Commerce} from './api/restful/commerce/index.js'; 5 | import {Developer} from './api/restful/developer/index.js'; 6 | import {PostOrder} from './api/restful/postOrder/index.js'; 7 | import {Sell} from './api/restful/sell/index.js'; 8 | import AuthNAuth from './auth/authNAuth.js'; 9 | import OAuth2 from './auth/oAuth2.js'; 10 | import * as enums from './enums/index.js'; 11 | import {ContentLanguage, Locale, MarketplaceId, SiteId} from './enums/index.js'; 12 | import * as errors from './errors/index.js'; 13 | import {ApiEnvError} from './errors/index.js'; 14 | import {IEBayApiRequest} from './request.js'; 15 | import * as types from './types/index.js'; 16 | import {AppConfig, ClientAlerts, Finding, Keyset, Merchandising, Shopping, Signature, Trading} from './types/index.js'; 17 | 18 | const defaultConfig: Omit = { 19 | sandbox: false, 20 | autoRefreshToken: true, 21 | siteId: SiteId.EBAY_US, 22 | marketplaceId: MarketplaceId.EBAY_US, 23 | acceptLanguage: Locale.en_US, 24 | contentLanguage: ContentLanguage.en_US 25 | }; 26 | 27 | // tslint:disable-next-line:class-name 28 | export default class eBayApi extends Api { 29 | public static readonly SiteId = SiteId; 30 | public static readonly MarketplaceId = MarketplaceId; 31 | public static readonly ContentLanguage = ContentLanguage; 32 | public static readonly Locale = Locale; 33 | 34 | /** 35 | * Loads config from `process.env` 36 | * 37 | * @return {eBayApi} a new eBayApi instance 38 | * @param {request} req request 39 | * @throws {ApiEnvError} 40 | */ 41 | public static fromEnv(req?: IEBayApiRequest) { 42 | if (!process.env.EBAY_APP_ID) { 43 | throw new ApiEnvError('EBAY_APP_ID'); 44 | } 45 | if (!process.env.EBAY_CERT_ID) { 46 | throw new ApiEnvError('EBAY_CERT_ID'); 47 | } 48 | 49 | let signature: Signature | null = null; 50 | if (process.env.EBAY_JWE && process.env.EBAY_PRIVATE_KEY) { 51 | signature = { 52 | jwe: process.env.EBAY_JWE, 53 | privateKey: process.env.EBAY_PRIVATE_KEY 54 | }; 55 | } 56 | 57 | return new eBayApi({ 58 | appId: process.env.EBAY_APP_ID, 59 | certId: process.env.EBAY_CERT_ID, 60 | devId: process.env.EBAY_DEV_ID, 61 | authToken: process.env.EBAY_AUTH_TOKEN, 62 | siteId: process.env.EBAY_SITE_ID ? parseInt(process.env.EBAY_SITE_ID, 10) : SiteId.EBAY_US, 63 | marketplaceId: process.env.EBAY_MARKETPLACE_ID && process.env.EBAY_MARKETPLACE_ID in MarketplaceId ? 64 | MarketplaceId[process.env.EBAY_MARKETPLACE_ID as keyof typeof MarketplaceId] as MarketplaceId : 65 | MarketplaceId.EBAY_US, 66 | ruName: process.env.EBAY_RU_NAME, 67 | sandbox: (process.env.EBAY_SANDBOX === 'true'), 68 | signature 69 | }, 70 | req); 71 | } 72 | 73 | // Shortcuts to auth 74 | public readonly authNAuth: AuthNAuth; 75 | public readonly oAuth2: OAuth2; 76 | // tslint:disable-next-line:variable-name 77 | public readonly OAuth2: OAuth2; 78 | 79 | private readonly factory: ApiFactory; 80 | 81 | // RESTful API 82 | private _buy?: Buy; 83 | private _commerce?: Commerce; 84 | private _developer?: Developer; 85 | private _postOrder?: PostOrder; 86 | private _sell?: Sell; 87 | 88 | // Traditional API 89 | private _trading?: Trading; 90 | private _finding?: Finding; 91 | private _shopping?: Shopping; 92 | 93 | private _merchandising?: Merchandising; 94 | private _clientAlerts?: ClientAlerts; 95 | 96 | /** 97 | * @param {AppConfig} config the app config 98 | * @param {IEBayApiRequest} req the request 99 | */ 100 | constructor(config: AppConfig, req?: IEBayApiRequest) { 101 | super({...defaultConfig, ...config}, req); 102 | 103 | this.factory = new ApiFactory(this.config, this.req, this.auth); 104 | 105 | // Shortcuts 106 | this.authNAuth = this.auth.authNAuth; 107 | this.OAuth2 = this.auth.OAuth2; 108 | this.oAuth2 = this.OAuth2; 109 | } 110 | 111 | get buy(): Buy { 112 | return this._buy || (this._buy = this.factory.createBuyApi()); 113 | } 114 | 115 | get commerce(): Commerce { 116 | return this._commerce || (this._commerce = this.factory.createCommerceApi()); 117 | } 118 | 119 | get developer(): Developer { 120 | return this._developer || (this._developer = this.factory.createDeveloperApi()); 121 | } 122 | 123 | get postOrder(): PostOrder { 124 | return this._postOrder || (this._postOrder = this.factory.createPostOrderApi()); 125 | } 126 | 127 | get sell(): Sell { 128 | return this._sell || (this._sell = this.factory.createSellApi()); 129 | } 130 | 131 | // Traditional 132 | get trading(): Trading { 133 | return this._trading || (this._trading = this.factory.createTradingApi()); 134 | } 135 | 136 | get finding(): Finding { 137 | return this._finding || (this._finding = this.factory.createFindingApi()); 138 | } 139 | 140 | get shopping(): Shopping { 141 | return this._shopping || (this._shopping = this.factory.createShoppingApi()); 142 | } 143 | 144 | get merchandising(): Merchandising { 145 | return this._merchandising || (this._merchandising = this.factory.createMerchandisingApi()); 146 | } 147 | 148 | get clientAlerts(): ClientAlerts { 149 | return this._clientAlerts || (this._clientAlerts = this.factory.createClientAlertsApi()); 150 | } 151 | 152 | setSignature(signature: Signature) { 153 | this.config.signature = signature; 154 | } 155 | } 156 | 157 | export { 158 | eBayApi, 159 | SiteId, 160 | MarketplaceId, 161 | ContentLanguage, 162 | Locale, 163 | enums, 164 | errors, 165 | types 166 | }; -------------------------------------------------------------------------------- /src/enums/apiEnums.ts: -------------------------------------------------------------------------------- 1 | export enum SiteId { 2 | EBAY_US = 0, 3 | EBAY_ENCA = 2, 4 | EBAY_GB = 3, 5 | EBAY_AU = 15, 6 | EBAY_AT = 16, 7 | EBAY_FRBE = 23, 8 | EBAY_FR = 71, 9 | EBAY_DE = 77, 10 | EBAY_MOTOR = 100, 11 | EBAY_IT = 101, 12 | EBAY_NLBE = 123, 13 | EBAY_NL = 146, 14 | EBAY_ES = 186, 15 | EBAY_CH = 193, 16 | EBAY_HK = 201, 17 | EBAY_IN = 203, 18 | EBAY_IE = 205, 19 | EBAY_MY = 207, 20 | EBAY_FRCA = 210, 21 | EBAY_PH = 211, 22 | EBAY_PL = 212, 23 | EBAY_SG = 216 24 | } 25 | 26 | export enum MarketplaceId { 27 | EBAY_US = 'EBAY_US', 28 | EBAY_AT = 'EBAY_AT', 29 | EBAY_AU = 'EBAY_AU', 30 | EBAY_BE = 'EBAY_BE', 31 | EBAY_CA = 'EBAY_CA', 32 | EBAY_CH = 'EBAY_CH', 33 | EBAY_DE = 'EBAY_DE', 34 | EBAY_ES = 'EBAY_ES', 35 | EBAY_FR = 'EBAY_FR', 36 | EBAY_GB = 'EBAY_GB', 37 | EBAY_HK = 'EBAY_HK', 38 | EBAY_IE = 'EBAY_IE', 39 | EBAY_IN = 'EBAY_IN', 40 | EBAY_IT = 'EBAY_IT', 41 | EBAY_MY = 'EBAY_MY', 42 | EBAY_NL = 'EBAY_NL', 43 | EBAY_PH = 'EBAY_PH', 44 | EBAY_PL = 'EBAY_PL', 45 | EBAY_SG = 'EBAY_SG', 46 | EBAY_TH = 'EBAY_TH', 47 | EBAY_TW = 'EBAY_TW', 48 | EBAY_VN = 'EBAY_VN', 49 | EBAY_MOTORS_US = 'EBAY_MOTORS_US' 50 | } -------------------------------------------------------------------------------- /src/enums/index.ts: -------------------------------------------------------------------------------- 1 | export * from './apiEnums.js'; 2 | export * from './restfulEnums.js'; 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import eBayApi from './eBayApi.js'; 2 | 3 | export = eBayApi; -------------------------------------------------------------------------------- /src/nanoevents.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/ai/nanoevents 2 | export type EventCallback = (...args: any) => void 3 | 4 | export let createNanoEvents = () => ({ 5 | events: {} as Record, 6 | emit(event: string, ...args: any[]) { 7 | const callbacks = this.events[event] || []; 8 | for (let i = 0, length = callbacks.length; i < length; i++) { 9 | callbacks[i](...args); 10 | } 11 | }, 12 | on(event: string, cb: EventCallback) { 13 | if (this.events[event]) { 14 | this.events[event].push(cb); 15 | } else { 16 | this.events[event] = [cb]; 17 | } 18 | return () => { 19 | this.events[event] = this.events[event]?.filter(i => cb !== i); 20 | }; 21 | } 22 | }); -------------------------------------------------------------------------------- /src/request.ts: -------------------------------------------------------------------------------- 1 | import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'axios'; 2 | import debug from 'debug'; 3 | import {stringify} from 'qs'; 4 | 5 | const log = debug('ebay:request'); 6 | 7 | export const defaultGlobalHeaders = { 8 | 'Access-Control-Allow-Origin': '*', 9 | 'Access-Control-Allow-Headers': 'X-Requested-With, Origin, Content-Type, X-Auth-Token', 10 | 'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE' 11 | } 12 | 13 | export const multipartHeader = { 14 | 'Content-Type': 'multipart/form-data' 15 | } 16 | 17 | export interface IEBayApiRequest { 18 | readonly instance: T; 19 | 20 | get(url: string, config?: C): Promise; 21 | 22 | delete(url: string, config?: C): Promise; 23 | 24 | post(url: string, data?: any, config?: C): Promise; 25 | 26 | postForm(url: string, data?: any, config?: C): Promise; 27 | 28 | put(url: string, data?: any, config?: C): Promise; 29 | } 30 | 31 | export class AxiosRequest implements IEBayApiRequest { 32 | public readonly instance: AxiosInstance; 33 | 34 | constructor(config: AxiosRequestConfig = {}) { 35 | this.instance = axios.create({ 36 | headers: { 37 | ...defaultGlobalHeaders 38 | }, 39 | ...config 40 | }); 41 | } 42 | 43 | public get(url: string, config?: AxiosRequestConfig): Promise { 44 | log('get: ' + url, config); 45 | return this.instance.get(url, config); 46 | } 47 | 48 | public post(url: string, payload?: any, config?: AxiosRequestConfig): Promise { 49 | log('post: ' + url, {payload, config}); 50 | return this.instance.post(url, payload, config); 51 | } 52 | 53 | public delete(url: string, config?: AxiosRequestConfig): Promise { 54 | log('delete: ' + url, config); 55 | return this.instance.delete(url, config); 56 | } 57 | 58 | public put(url: string, payload?: any, config?: AxiosRequestConfig): Promise { 59 | log('put: ' + url, {payload, config}); 60 | return this.instance.put(url, payload, config); 61 | } 62 | 63 | public postForm(url: string, payload?: any, config?: AxiosRequestConfig): Promise { 64 | log('postForm: ' + url); 65 | const body = stringify(payload); 66 | return this.instance.post(url, body, config); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/types/apiTypes.ts: -------------------------------------------------------------------------------- 1 | import {AxiosRequestConfig} from 'axios'; 2 | import {Locale, MarketplaceId, SiteId} from '../enums/index.js'; 3 | 4 | export type Scope = string[]; 5 | 6 | export type Keyset = { 7 | appId: string, // (Client ID) 8 | certId: string, // (Client Secret) 9 | devId?: string, 10 | }; 11 | 12 | export type RestConfig = { 13 | marketplaceId?: MarketplaceId | `${MarketplaceId}`, 14 | endUserCtx?: string, 15 | contentLanguage?: Locale | `${Locale}` 16 | acceptLanguage?: Locale | `${Locale}` 17 | } 18 | 19 | export type TraditionalConfig = { 20 | siteId?: SiteId | `${SiteId}` 21 | authToken?: string | null 22 | } 23 | 24 | export type Cipher = 'sha256' | 'sha512'; 25 | 26 | export type Signature = { 27 | cipher?: Cipher 28 | jwe: string, // The value of the x-ebay-signature-key header is the Public Key as JWE value that has been created by the Key Management API. 29 | privateKey: string 30 | } 31 | 32 | export type eBayConfig = Keyset & { 33 | sandbox: boolean, 34 | ruName?: string, 35 | scope?: Scope, 36 | signature?: Signature | null 37 | } & TraditionalConfig & RestConfig; 38 | 39 | export type ApiConfig = { 40 | autoRefreshToken?: boolean, 41 | axiosConfig?: AxiosRequestConfig 42 | } 43 | 44 | export type Headers = Record; 45 | 46 | export type ApiRequestConfig = { 47 | headers?: Headers, 48 | returnResponse?: boolean 49 | } 50 | 51 | export type AppConfig = eBayConfig & ApiConfig; 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './apiTypes.js'; 2 | export * from './restfulTypes.js'; 3 | export * from './traditonalTypes.js'; -------------------------------------------------------------------------------- /src/types/restful/specs/cancellation_oas3.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by openapi-typescript. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | 7 | export interface paths { 8 | "/cancellation/{cancelId}/approve": { 9 | /** @description Seller approves a cancellation request */ 10 | post: operations["approveCancellationRequest"]; 11 | }; 12 | "/cancellation/check_eligibility": { 13 | /** @description Check the eligibility of an order cancellation */ 14 | post: operations["checkCancellationEligibility"]; 15 | }; 16 | "/cancellation/{cancelId}/confirm": { 17 | /** @description Buyer confirms the refund from a cancellation was received */ 18 | post: operations["confirmRefundReceived"]; 19 | }; 20 | "/cancellation": { 21 | /** @description Request or perform an order cancellation */ 22 | post: operations["createCancellation"]; 23 | }; 24 | "/cancellation/{cancelId}": { 25 | /** @description Request or perform an order cancellation */ 26 | get: operations["getCancellation"]; 27 | }; 28 | "/cancellation/{cancelId}/reject": { 29 | /** @description Seller rejects a cancellation request */ 30 | post: operations["rejectCancellationRequest"]; 31 | }; 32 | "/cancellation/search": { 33 | /** @description Search for cancellations */ 34 | get: operations["search"]; 35 | }; 36 | } 37 | 38 | export type webhooks = Record; 39 | 40 | export type components = Record; 41 | 42 | export type external = Record; 43 | 44 | export interface operations { 45 | 46 | /** @description Seller approves a cancellation request */ 47 | approveCancellationRequest: { 48 | parameters: { 49 | path: { 50 | /** @description The unique eBay-assigned identifier of the cancellation request to be approved. */ 51 | cancelId: string; 52 | }; 53 | }; 54 | responses: { 55 | /** @description OK */ 56 | 200: never; 57 | }; 58 | }; 59 | /** @description Check the eligibility of an order cancellation */ 60 | checkCancellationEligibility: { 61 | responses: { 62 | /** @description OK */ 63 | 200: never; 64 | }; 65 | }; 66 | /** @description Buyer confirms the refund from a cancellation was received */ 67 | confirmRefundReceived: { 68 | parameters: { 69 | path: { 70 | /** @description The unique eBay-assigned identifier of the cancellation request to be approved. */ 71 | cancelId: string; 72 | }; 73 | }; 74 | responses: { 75 | /** @description OK */ 76 | 200: never; 77 | }; 78 | }; 79 | /** @description Request or perform an order cancellation */ 80 | createCancellation: { 81 | responses: { 82 | /** @description OK */ 83 | 200: never; 84 | }; 85 | }; 86 | /** @description Request or perform an order cancellation */ 87 | getCancellation: { 88 | parameters: { 89 | path: { 90 | /** @description The unique eBay-assigned identifier of the cancellation request to be approved. */ 91 | cancelId: string; 92 | }; 93 | }; 94 | responses: { 95 | /** @description OK */ 96 | 200: never; 97 | }; 98 | }; 99 | /** @description Seller rejects a cancellation request */ 100 | rejectCancellationRequest: { 101 | parameters: { 102 | path: { 103 | /** @description The unique eBay-assigned identifier of the cancellation request to be approved. */ 104 | cancelId: string; 105 | }; 106 | }; 107 | responses: { 108 | /** @description OK */ 109 | 200: never; 110 | }; 111 | }; 112 | /** @description Search for cancellations */ 113 | search: { 114 | responses: { 115 | /** @description OK */ 116 | 200: never; 117 | }; 118 | }; 119 | } 120 | -------------------------------------------------------------------------------- /src/types/restful/specs/case_oas3.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by openapi-typescript. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | 7 | export interface paths { 8 | "/casemanagement/{caseId}/appeal": { 9 | /** @description Buyer or seller appeals a case decision */ 10 | post: operations["appealCaseDecision"]; 11 | }; 12 | "/casemanagement/{caseId}/close": { 13 | /** @description Buyer closes a case */ 14 | post: operations["closeCase"]; 15 | }; 16 | "/casemanagement/{caseId}": { 17 | /** @description Retrieve the details related to a specific case */ 18 | get: operations["getCase"]; 19 | }; 20 | "/casemanagement/{caseId}/issue_refund": { 21 | /** @description Seller issues a refund for a case */ 22 | post: operations["issueCaseRefund"]; 23 | }; 24 | "/casemanagement/{caseId}/provide_shipment_info": { 25 | /** @description Buyer provides return shipment information */ 26 | post: operations["provideReturnShipmentInfo"]; 27 | }; 28 | "/casemanagement/{caseId}/provide_return_address": { 29 | /** @description Seller provides a return address to the buyer */ 30 | post: operations["providesReturnAddress"]; 31 | }; 32 | "/casemanagement/search": { 33 | /** @description This call is used to search for cases using multiple filter types. */ 34 | get: operations["search"]; 35 | }; 36 | } 37 | 38 | export type webhooks = Record; 39 | 40 | export type components = Record; 41 | 42 | export type external = Record; 43 | 44 | export interface operations { 45 | 46 | /** @description Buyer or seller appeals a case decision */ 47 | appealCaseDecision: { 48 | parameters: { 49 | path: { 50 | /** @description The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI. */ 51 | caseId: string; 52 | }; 53 | }; 54 | responses: { 55 | /** @description OK */ 56 | 200: never; 57 | }; 58 | }; 59 | /** @description Buyer closes a case */ 60 | closeCase: { 61 | parameters: { 62 | path: { 63 | /** @description The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI. */ 64 | caseId: string; 65 | }; 66 | }; 67 | responses: { 68 | /** @description OK */ 69 | 200: never; 70 | }; 71 | }; 72 | /** @description Retrieve the details related to a specific case */ 73 | getCase: { 74 | parameters: { 75 | path: { 76 | /** @description The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI. */ 77 | caseId: string; 78 | }; 79 | }; 80 | responses: { 81 | /** @description OK */ 82 | 200: never; 83 | }; 84 | }; 85 | /** @description Seller issues a refund for a case */ 86 | issueCaseRefund: { 87 | parameters: { 88 | path: { 89 | /** @description The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI. */ 90 | caseId: string; 91 | }; 92 | }; 93 | responses: { 94 | /** @description OK */ 95 | 200: never; 96 | }; 97 | }; 98 | /** @description Buyer provides return shipment information */ 99 | provideReturnShipmentInfo: { 100 | parameters: { 101 | path: { 102 | /** @description The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI. */ 103 | caseId: string; 104 | }; 105 | }; 106 | responses: { 107 | /** @description OK */ 108 | 200: never; 109 | }; 110 | }; 111 | /** @description Seller provides a return address to the buyer */ 112 | providesReturnAddress: { 113 | parameters: { 114 | path: { 115 | /** @description The unique identifier of a case. This URI parameter is required in order to identify the case for which an appeal will be filed against. The case is identified by the caseId that is passed in as part of the call URI. */ 116 | caseId: string; 117 | }; 118 | }; 119 | responses: { 120 | /** @description OK */ 121 | 200: never; 122 | }; 123 | }; 124 | /** @description This call is used to search for cases using multiple filter types. */ 125 | search: { 126 | responses: { 127 | /** @description OK */ 128 | 200: never; 129 | }; 130 | }; 131 | } 132 | -------------------------------------------------------------------------------- /src/types/restful/specs/commerce_translation_v1_beta_oas3.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by openapi-typescript. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | 7 | export interface paths { 8 | "/translate": { 9 | /** @description This method translates listing title and listing description text from one language into another. For a full list of supported language translations, see the table in the API Overview page. */ 10 | post: operations["translate"]; 11 | }; 12 | } 13 | 14 | export type webhooks = Record; 15 | 16 | export interface components { 17 | schemas: { 18 | /** @description This type defines the fields that can be returned in an error. */ 19 | Error: { 20 | /** @description Identifies the type of erro. */ 21 | category?: string; 22 | /** @description Name for the primary system where the error occurred. This is relevant for application errors. */ 23 | domain?: string; 24 | /** 25 | * Format: int32 26 | * @description A unique number to identify the error. 27 | */ 28 | errorId?: number; 29 | /** @description An array of request elements most closely associated to the error. */ 30 | inputRefIds?: (string)[]; 31 | /** @description A more detailed explanation of the error. */ 32 | longMessage?: string; 33 | /** @description Information on how to correct the problem, in the end user's terms and language where applicable. */ 34 | message?: string; 35 | /** @description An array of request elements most closely associated to the error. */ 36 | outputRefIds?: (string)[]; 37 | /** @description An array of name/value pairs that describe details the error condition. These are useful when multiple errors are returned. */ 38 | parameters?: (components["schemas"]["ErrorParameter"])[]; 39 | /** @description Further helps indicate which subsystem the error is coming from. System subcategories include: Initialization, Serialization, Security, Monitoring, Rate Limiting, etc. */ 40 | subdomain?: string; 41 | }; 42 | ErrorParameter: { 43 | /** @description The object of the error. */ 44 | name?: string; 45 | /** @description The value of the object. */ 46 | value?: string; 47 | }; 48 | /** @description This is the base type of the translate method request payload. */ 49 | TranslateRequest: { 50 | /** @description The language of the input text to be translated. Not all LanguageEnum values are supported in this field. For a full list of supported language translations, see the table in the API Overview page. For implementation help, refer to eBay API documentation */ 51 | from?: string; 52 | /** @description The input text to translate. For ITEM_DESCRIPTION translations, HTML/CSS markup and links can be included, but will count toward max character limit. Max Length: 1,000 characters for ITEM_TITLE 100,000 characters for ITEM_DESCRIPTION, including markup/tagsMax Occurrence: 1. Only one continuous text string currently supported. */ 53 | text?: (string)[]; 54 | /** @description The target language for the translation of the input text. Not all LanguageEnum values are supported in this field. For a full list of supported language translations, see the table in the API Overview page. For implementation help, refer to eBay API documentation */ 55 | to?: string; 56 | /** @description Input the listing entity to be translated. Valid Values: ITEM_TITLE and ITEM_DESCRIPTION For implementation help, refer to eBay API documentation */ 57 | translationContext?: string; 58 | }; 59 | /** @description This is the base type of the translate method response payload. */ 60 | TranslateResponse: { 61 | /** @description The enumeration value indicates the language of the input text. For implementation help, refer to eBay API documentation */ 62 | from?: string; 63 | /** @description The enumeration value indicates the language of the translated text. For implementation help, refer to eBay API documentation */ 64 | to?: string; 65 | /** @description An array showing the input and translated text. Only one input string can be translated at this time. Support for multiple continuous text strings is expected in the future. */ 66 | translations?: (components["schemas"]["Translation"])[]; 67 | }; 68 | /** @description This type is used by the translations array, which shows the original text supplied by the user in the request payload, and the text translated by eBay. Only one input string can be translated at this time. Support for multiple continuous text strings is expected in the future. */ 69 | Translation: { 70 | /** @description The original text, in the language specified in the from field, that was input into the text field in the request. */ 71 | originalText?: string; 72 | /** @description The translation of the original text into the language specified in the to field. */ 73 | translatedText?: string; 74 | }; 75 | }; 76 | responses: never; 77 | parameters: never; 78 | requestBodies: never; 79 | headers: never; 80 | pathItems: never; 81 | } 82 | 83 | export type external = Record; 84 | 85 | export interface operations { 86 | 87 | /** @description This method translates listing title and listing description text from one language into another. For a full list of supported language translations, see the table in the API Overview page. */ 88 | translate: { 89 | requestBody: { 90 | content: { 91 | "application/json": components["schemas"]["TranslateRequest"]; 92 | }; 93 | }; 94 | responses: { 95 | /** @description OK */ 96 | 200: { 97 | content: { 98 | "application/json": components["schemas"]["TranslateResponse"]; 99 | }; 100 | }; 101 | /** @description Bad Request */ 102 | 400: never; 103 | /** @description Internal Server Error */ 104 | 500: never; 105 | }; 106 | }; 107 | } 108 | -------------------------------------------------------------------------------- /src/types/restful/specs/inquiry_oas3.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file was auto-generated by openapi-typescript. 3 | * Do not make direct changes to the file. 4 | */ 5 | 6 | 7 | export interface paths { 8 | "/inquiry/check_eligibility": { 9 | /** @description Check if a buyer is eligible to open an inquiry on an order */ 10 | post: operations["checkInquiryEligibility"]; 11 | }; 12 | "/inquiry/{inquiryId}/close": { 13 | /** @description Close an inquiry for the buyer */ 14 | post: operations["closeInquiry"]; 15 | }; 16 | "/inquiry/{inquiryId}/confirm_refund": { 17 | /** @description Buyer confirms the refund from an inquiry was received */ 18 | post: operations["confirmInquiryRefund"]; 19 | }; 20 | "/inquiry": { 21 | /** @description Buyer confirms the refund from an inquiry was received */ 22 | post: operations["createInquiry"]; 23 | }; 24 | "/inquiry/{inquiryId}/escalate": { 25 | /** @description Escalate an inquiry to an INR case */ 26 | post: operations["escalateInquiry"]; 27 | }; 28 | "/inquiry/{inquiryId}": { 29 | /** @description Retrieve the history and details related to a specific inquiry */ 30 | get: operations["getInquiry"]; 31 | }; 32 | "/inquiry/{inquiryId}/issue_refund": { 33 | /** @description Issue a refund for an inquiry */ 34 | post: operations["issueInquiryRefund"]; 35 | }; 36 | "/inquiry/{inquiryId}/provide_refund_info": { 37 | /** @description Provide refund information about an inquiry to the buyer */ 38 | post: operations["provideInquiryRefundInfo"]; 39 | }; 40 | "/inquiry/{inquiryId}/provide_shipment_info": { 41 | /** @description Provide shipment information for an inquiry */ 42 | post: operations["provideInquiryShipmentInfo"]; 43 | }; 44 | "/inquiry/search": { 45 | /** @description This call is used to search for inquiries using multiple filter types. */ 46 | get: operations["search"]; 47 | }; 48 | "/inquiry/{inquiryId}/send_message": { 49 | /** @description Contact the buyer or seller about an inquiry */ 50 | post: operations["sendInquiryMessage"]; 51 | }; 52 | } 53 | 54 | export type webhooks = Record; 55 | 56 | export type components = Record; 57 | 58 | export type external = Record; 59 | 60 | export interface operations { 61 | 62 | /** @description Check if a buyer is eligible to open an inquiry on an order */ 63 | checkInquiryEligibility: { 64 | responses: { 65 | /** @description OK */ 66 | 200: never; 67 | }; 68 | }; 69 | /** @description Close an inquiry for the buyer */ 70 | closeInquiry: { 71 | parameters: { 72 | path: { 73 | /** @description The unique ID of the inquiry to be closed. */ 74 | inquiryId: string; 75 | }; 76 | }; 77 | responses: { 78 | /** @description OK */ 79 | 200: never; 80 | }; 81 | }; 82 | /** @description Buyer confirms the refund from an inquiry was received */ 83 | confirmInquiryRefund: { 84 | parameters: { 85 | path: { 86 | /** @description The unique ID of the inquiry to be closed. */ 87 | inquiryId: string; 88 | }; 89 | }; 90 | responses: { 91 | /** @description OK */ 92 | 200: never; 93 | }; 94 | }; 95 | /** @description Buyer confirms the refund from an inquiry was received */ 96 | createInquiry: { 97 | responses: { 98 | /** @description OK */ 99 | 200: never; 100 | }; 101 | }; 102 | /** @description Escalate an inquiry to an INR case */ 103 | escalateInquiry: { 104 | parameters: { 105 | path: { 106 | /** @description The unique ID of the inquiry to be closed. */ 107 | inquiryId: string; 108 | }; 109 | }; 110 | responses: { 111 | /** @description OK */ 112 | 200: never; 113 | }; 114 | }; 115 | /** @description Retrieve the history and details related to a specific inquiry */ 116 | getInquiry: { 117 | parameters: { 118 | path: { 119 | /** @description The unique ID of the inquiry to be closed. */ 120 | inquiryId: string; 121 | }; 122 | }; 123 | responses: { 124 | /** @description OK */ 125 | 200: never; 126 | }; 127 | }; 128 | /** @description Issue a refund for an inquiry */ 129 | issueInquiryRefund: { 130 | parameters: { 131 | path: { 132 | /** @description The unique ID of the inquiry to be closed. */ 133 | inquiryId: string; 134 | }; 135 | }; 136 | responses: { 137 | /** @description OK */ 138 | 200: never; 139 | }; 140 | }; 141 | /** @description Provide refund information about an inquiry to the buyer */ 142 | provideInquiryRefundInfo: { 143 | parameters: { 144 | path: { 145 | /** @description The unique ID of the inquiry to be closed. */ 146 | inquiryId: string; 147 | }; 148 | }; 149 | responses: { 150 | /** @description OK */ 151 | 200: never; 152 | }; 153 | }; 154 | /** @description Provide shipment information for an inquiry */ 155 | provideInquiryShipmentInfo: { 156 | parameters: { 157 | path: { 158 | /** @description The unique ID of the inquiry to be closed. */ 159 | inquiryId: string; 160 | }; 161 | }; 162 | responses: { 163 | /** @description OK */ 164 | 200: never; 165 | }; 166 | }; 167 | /** @description This call is used to search for inquiries using multiple filter types. */ 168 | search: { 169 | responses: { 170 | /** @description OK */ 171 | 200: never; 172 | }; 173 | }; 174 | /** @description Contact the buyer or seller about an inquiry */ 175 | sendInquiryMessage: { 176 | parameters: { 177 | path: { 178 | /** @description The unique ID of the inquiry to be closed. */ 179 | inquiryId: string; 180 | }; 181 | }; 182 | responses: { 183 | /** @description OK */ 184 | 200: never; 185 | }; 186 | }; 187 | } 188 | -------------------------------------------------------------------------------- /src/types/traditonalTypes.ts: -------------------------------------------------------------------------------- 1 | import ClientAlertsCalls from '../api/traditional/clientAlerts/index.js'; 2 | import {Fields} from '../api/traditional/fields.js'; 3 | import FindingCalls from '../api/traditional/finding/index.js'; 4 | import MerchandisingCalls from '../api/traditional/merchandising/index.js'; 5 | import ShoppingCalls from '../api/traditional/shopping/index.js'; 6 | import TradingCalls from '../api/traditional/trading/index.js'; 7 | import {TraditionalApiConfig} from '../api/traditional/XMLRequest.js'; 8 | 9 | export type XMLApiCall = (fields?: Fields | null, apiConfig?: TraditionalApiConfig) => Promise; 10 | 11 | export type Trading = { 12 | [key in keyof typeof TradingCalls]: XMLApiCall; 13 | }; 14 | 15 | export type Shopping = { 16 | [key in keyof typeof ShoppingCalls]: XMLApiCall; 17 | }; 18 | 19 | export type Finding = { 20 | [key in keyof typeof FindingCalls]: XMLApiCall; 21 | }; 22 | 23 | export type ClientAlerts = { 24 | [key in keyof typeof ClientAlertsCalls]: (fields?: object, options?: TraditionalApiConfig) => Promise; 25 | }; 26 | 27 | export type Merchandising = { 28 | [key in keyof typeof MerchandisingCalls]: (fields?: object, options?: TraditionalApiConfig) => Promise; 29 | }; 30 | 31 | type Endpoint = { 32 | production: string, 33 | sandbox: string 34 | }; 35 | 36 | export type TraditionalApi = { 37 | endpoint: Endpoint, 38 | xmlns: string, 39 | path: string, 40 | calls: typeof TradingCalls | typeof ShoppingCalls | typeof FindingCalls | typeof ClientAlertsCalls | typeof MerchandisingCalls, 41 | headers: (callName: string, accessToken?: string | null) => object 42 | }; 43 | -------------------------------------------------------------------------------- /test/api/authNAuth.spec.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import 'mocha'; 3 | // @ts-ignore 4 | import sinon from 'sinon'; 5 | import AuthNAuth from '../../src/auth/authNAuth.js'; 6 | 7 | describe('AuthNAuth', () => { 8 | const config = {appId: 'appId', certId: 'certId', sandbox: true, siteId: 0, devId: 'devId'}; 9 | let req: any = null; 10 | beforeEach(() => { 11 | req = { 12 | get: sinon.stub().returns(Promise.resolve({data: {}})), 13 | delete: sinon.stub().returns(Promise.resolve({data: {}})), 14 | put: sinon.stub().returns(Promise.resolve({data: {}})), 15 | post: sinon.stub().returns(Promise.resolve({data: {}})), 16 | postForm: sinon.stub().returns(Promise.resolve({ 17 | data: { 18 | access_token: 'new_access_token' 19 | } 20 | })), 21 | instance: sinon.stub() 22 | }; 23 | }); 24 | 25 | it('Sets the auth token', () => { 26 | const auth = new AuthNAuth({...config, authToken: 'authToken'}, req); 27 | expect(auth.getAuthToken()?.eBayAuthToken).to.equal('authToken'); 28 | }); 29 | 30 | describe('Get session id and auth url', () => { 31 | it('Throws error if devId is not defined', async () => { 32 | const auth = new AuthNAuth({...config, devId: undefined}, req); 33 | try { 34 | await auth.getSessionIdAndAuthUrl(); 35 | } catch (error: any) { 36 | expect(error.message).to.equal('DevId is required.'); 37 | } 38 | }); 39 | 40 | it('Throws error if ruName is not defined', async () => { 41 | const auth = new AuthNAuth({...config}, req); 42 | try { 43 | await auth.getSessionIdAndAuthUrl(); 44 | } catch (error: any) { 45 | expect(error.message).to.equal('RuName is required.'); 46 | } 47 | }); 48 | 49 | it('Throws error if siteId is not a Number', async () => { 50 | // @ts-ignore 51 | const auth = new AuthNAuth({...config, siteId: 'xxx', ruName: 'ruName'}, req); 52 | try { 53 | await auth.getSessionIdAndAuthUrl(); 54 | } catch (error: any) { 55 | expect(error.message).to.equal('"siteId" is required for Auth\'n\'Auth.'); 56 | } 57 | }); 58 | 59 | it('Throws error if siteId is not a Number', async () => { 60 | const post = sinon.stub().returns(Promise.resolve({ 61 | data: ` 62 | 63 | SessionID 64 | ` 65 | })); 66 | // @ts-ignore 67 | const auth = new AuthNAuth({...config, ruName: 'ruName'}, {...req, post}); 68 | 69 | const data = await auth.getSessionIdAndAuthUrl(); 70 | expect(data.sessionId).to.equal('SessionID'); 71 | expect(data.url).to.equal('https://signin.sandbox.ebay.com/ws/eBayISAPI.dll?SignIn&RuName=ruName&SessID=SessionID'); 72 | }); 73 | }); 74 | 75 | describe('Auth Token', () => { 76 | it('Throws error if devId is not defined', async () => { 77 | const auth = new AuthNAuth({...config, devId: undefined}, req); 78 | try { 79 | await auth.mintToken('SessionID'); 80 | } catch (error: any) { 81 | expect(error.message).to.equal('DevId is required.'); 82 | } 83 | }); 84 | 85 | it('fetch auth token', async () => { 86 | const post = sinon.stub().returns(Promise.resolve({ 87 | data: ` 88 | 89 | SessionID 90 | ` 91 | })); 92 | const auth = new AuthNAuth(config, {...req, post}); 93 | await auth.mintToken('SessionID'); 94 | }); 95 | 96 | it('sets and gets the token correctly', async () => { 97 | // @ts-ignore 98 | const auth = new AuthNAuth(config, req); 99 | auth.setAuthToken('authToken'); 100 | expect(auth.eBayAuthToken).to.equal('authToken'); 101 | }); 102 | }); 103 | 104 | 105 | it('Returns correct XML request config', async () => { 106 | const auth = new AuthNAuth(config, req); 107 | const xmlConfig = await auth.getRequestConfig('callName'); 108 | expect(xmlConfig).to.eql({ 109 | useIaf: false, 110 | xmlns: 'urn:ebay:apis:eBLBaseComponents', 111 | endpoint: 'https://api.sandbox.ebay.com/ws/api.dll', 112 | headers: { 113 | 'X-EBAY-API-CALL-NAME': 'callName', 114 | 'X-EBAY-API-CERT-NAME': 'certId', 115 | 'X-EBAY-API-APP-NAME': 'appId', 116 | 'X-EBAY-API-DEV-NAME': 'devId', 117 | 'X-EBAY-API-SITEID': 0, 118 | 'X-EBAY-API-COMPATIBILITY-LEVEL': 967 119 | } 120 | }); 121 | }); 122 | 123 | describe('Generate AuthUrl', () => { 124 | it('generates correct auth url', () => { 125 | const url = AuthNAuth.generateAuthUrl(false, 'ruName', 'sessionId', true); 126 | expect(url).to.equal('https://signin.ebay.com/ws/eBayISAPI.dll?SignIn&RuName=ruName&SessID=sessionId&prompt=login'); 127 | }); 128 | }); 129 | }); 130 | -------------------------------------------------------------------------------- /test/api/digitalSignature.spec.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import 'mocha'; 3 | // @ts-ignore 4 | import sinon from 'sinon'; 5 | import {generateContentDigestValue, generateSignature, generateSignatureInput} from '../../src/api/digitalSignature.js'; 6 | 7 | const privateKey = ` 8 | -----BEGIN PRIVATE KEY----- 9 | MC4CAQAwBQYDK2VwBCIEIJ+DYvh6SEqVTm50DFtMDoQikTmiCqirVv9mWG9qfSnF 10 | -----END PRIVATE KEY-----`; 11 | 12 | describe('Digital Signature', () => { 13 | it('should be able to generate \'signature-input\' header when request has payload', () => { 14 | const signatureInput = generateSignatureInput({}, 123); 15 | expect(signatureInput).to.eql(`sig1=("content-digest" "x-ebay-signature-key" "@method" "@path" "@authority");created=123`); 16 | }); 17 | 18 | it('should be able to generate \'signature-input\' header when request has no payload', () => { 19 | const signatureInput = generateSignatureInput(null, 123); 20 | expect(signatureInput).to.eql(`sig1=("x-ebay-signature-key" "@method" "@path" "@authority");created=123`); 21 | }); 22 | 23 | it('should be able to generate \'Signature\' header', () => { 24 | const payload = '{"hello": "world"}'; 25 | const contentDigest = generateContentDigestValue(payload); 26 | expect(contentDigest).to.eql('sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:'); 27 | const signature = generateSignature({ 28 | 'content-digest': contentDigest, 29 | 'signature-input': 'sig1=("content-digest" "x-ebay-signature-key" "@method" "@path" "@authority");created=1663459378', 30 | 'x-ebay-signature-key': 'eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMjU2R0NNIiwiemlwIjoiREVGIiwiaXYiOiJvSzFwdXJNVHQtci14VUwzIiwidGFnIjoiTjB4WjI4ZklZckFmYkd5UWFrTnpjZyJ9.AYdKU7ObIc7Z764OrlKpwUViK8Rphxl0xMP9v2_o9mI.1DbZiSQNRK6pLeIw.Yzp3IDV8RM_h_lMAnwGpMA4DXbaDdmqAh-65kO9xyDgzHD6s0kY3p-yO6oPR9kEcAbjGXIULeQKWVYzbfHKwXTY09Npj_mNuO5yxgZtWnL55uIgP2HL1So2dKkZRK0eyPa6DEXJT71lPtwZtpIGyq9R5h6s3kGMbqA.m4t_MX4VnlXJGx1X_zZ-KQ' 31 | }, privateKey, { 32 | method: 'POST', 33 | authority: 'localhost:8080', 34 | path: '/test' 35 | }, payload, 1663459378); 36 | expect(signature).to.eql('sig1=:gkk7dqudw21DFHDVBoRUWe/F6/2hTEmWRFDBxiN6COD4PjozXziiDFML1nFHu+0UcMXC/niltxzABjnugu4DCA==:'); 37 | }); 38 | 39 | it('should throw an error if content-digest is not in the header', () => { 40 | expect(() => generateSignature({}, privateKey, { 41 | method: 'POST', 42 | authority: 'localhost:8080', 43 | path: '/test' 44 | }, {}, 1663459378)).to.throw(/content-digest/); 45 | }); 46 | 47 | it('should throw an error pseudo header is not known', () => { 48 | expect(() => generateSignature({}, privateKey, { 49 | method: 'POST', 50 | authority: 'localhost:8080', 51 | path: '/test' 52 | }, {}, 1663459378)).to.throw(/content-digest/); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /test/api/errors/errors.json: -------------------------------------------------------------------------------- 1 | { 2 | "traditional": { 3 | "Timestamp": "2021-10-23T19:11:42.335Z", 4 | "Ack": "Failure", 5 | "Errors": { 6 | "ShortMessage": "Error Message", 7 | "LongMessage": "description", 8 | "ErrorCode": 930, 9 | "SeverityCode": "Error", 10 | "ErrorClassification": "RequestError" 11 | }, 12 | "Version": 1177, 13 | "Build": "E1177_CORE_APIMSG_19110890_R1" 14 | }, 15 | "restful": { 16 | "errors": [ 17 | { 18 | "errorId": 1, 19 | "domain": "domain", 20 | "severity": "ERROR", 21 | "category": "REQUEST", 22 | "message": "Error Message", 23 | "parameter": [ 24 | { 25 | "value": "value", 26 | "name": "name" 27 | } 28 | ], 29 | "longMessage": "description", 30 | "inputRefIds": [], 31 | "httpStatusCode": 400 32 | } 33 | ] 34 | }, 35 | "oauth": { 36 | "error": "Error Message", 37 | "error_description": "description" 38 | }, 39 | "postOrder": { 40 | "errorMessage": { 41 | "error": { 42 | "errorId": 1, 43 | "domain": "domain", 44 | "severity": "ERROR", 45 | "category": "REQUEST", 46 | "message": "Error Message" 47 | } 48 | } 49 | }, 50 | "plain": "Error Message" 51 | } -------------------------------------------------------------------------------- /test/api/errors/errors.spec.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import { 3 | checkEBayTraditionalResponse, 4 | EbayApiError, 5 | EBayApiError, 6 | EBayError, 7 | extractEBayError, 8 | handleEBayError 9 | } from '../../../src/errors/index.js'; 10 | import {readJSONSync} from '../jsonfile.js'; 11 | 12 | describe('eBay Errors', () => { 13 | const errors = readJSONSync('./errors.json', import.meta.url); 14 | 15 | Object.entries(errors).forEach(([key, payload]: [string, any]) => { 16 | it('maps errors correctly for ' + key, () => { 17 | const result = { 18 | response: { 19 | data: payload 20 | } 21 | }; 22 | 23 | const {message, description} = extractEBayError(result); 24 | expect(message).to.equal('Error Message'); 25 | if (description) { 26 | expect(description).to.equal('description'); 27 | } 28 | }); 29 | }); 30 | 31 | it('Throw correct error chain', () => { 32 | expect(() => handleEBayError({ 33 | response: { 34 | data: errors.traditional 35 | } 36 | })).to.throw(EBayApiError).with.property('errorCode', 930); 37 | 38 | expect(() => handleEBayError({ 39 | response: { 40 | data: errors.oauth 41 | } 42 | })).to.throw(EbayApiError); 43 | expect(() => handleEBayError({ 44 | response: { 45 | data: errors.restful 46 | } 47 | })).to.throw(EBayError) 48 | .with.property('errorCode', 1); 49 | }); 50 | 51 | it('Does not throw if the error is warning', () => { 52 | expect(() => checkEBayTraditionalResponse({}, { 53 | 'Timestamp': '2021-10-23T19:11:42.335Z', 54 | 'Ack': 'Warning', 55 | 'Errors': { 56 | 'ShortMessage': 'Error Message', 57 | 'LongMessage': 'description', 58 | 'ErrorCode': 930, 59 | 'SeverityCode': 'Error', 60 | 'ErrorClassification': 'RequestError' 61 | }, 62 | 'Version': 1177, 63 | 'Build': 'E1177_CORE_APIMSG_19110890_R1' 64 | })).to.not.throw(); 65 | }) 66 | 67 | }); -------------------------------------------------------------------------------- /test/api/factory.spec.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import 'mocha'; 3 | // @ts-ignore 4 | import sinon from 'sinon'; 5 | import ApiFactory from '../../src/api/apiFactory.js'; 6 | import {IEBayApiRequest} from '../../src/request.js'; 7 | import {eBayConfig} from '../../src/types/index.js'; 8 | 9 | describe('FactoryTest', () => { 10 | let config: eBayConfig; 11 | const request: IEBayApiRequest = { 12 | get: sinon.stub(), 13 | delete: sinon.stub(), 14 | put: sinon.stub(), 15 | post: sinon.stub(), 16 | postForm: sinon.stub(), 17 | instance: sinon.stub() 18 | }; 19 | 20 | beforeEach(() => { 21 | config = {appId: 'appId', certId: 'certId', sandbox: true, siteId: 0, devId: 'devId'}; 22 | }); 23 | 24 | it('Throws an error if siteId is not defined', () => { 25 | delete config.siteId; 26 | const factory = new ApiFactory(config, request); 27 | expect(factory.createTradingApi.bind(factory)).to.throw(/siteId/); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/api/jsonfile.ts: -------------------------------------------------------------------------------- 1 | import {readFileSync} from 'fs'; 2 | import {dirname, join} from 'path'; 3 | import {fileURLToPath} from 'url'; 4 | 5 | export const readJSONSync = (path: string, metaUrl: string) => JSON.parse(readFileSync(join(dirname(fileURLToPath(metaUrl)), path), 'utf-8')); 6 | export const readSpecs = (path: string, metaUrl: string) => readJSONSync('../../../../specs/' + path, metaUrl) -------------------------------------------------------------------------------- /test/api/restful/buy/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Browse, 3 | Deal, 4 | Feed, 5 | Marketing, 6 | MarketplaceInsights, 7 | Offer, 8 | Order 9 | } from '../../../../src/api/restful/buy/index.js'; 10 | import {readSpecs} from '../../jsonfile.js'; 11 | 12 | const tests = new Map(); 13 | tests.set(Browse, readSpecs('buy_browse_v1_oas3.json', import.meta.url)); 14 | tests.set(Feed, readSpecs('buy_feed_v1_beta_oas3.json', import.meta.url)); 15 | tests.set(Marketing, readSpecs('buy_marketing_v1_beta_oas3.json', import.meta.url)); 16 | tests.set(Offer, readSpecs('buy_offer_v1_beta_oas3.json', import.meta.url)); 17 | tests.set(Order, readSpecs('buy_order_v1_beta_oas3.json', import.meta.url)); 18 | tests.set(Deal, readSpecs('buy_deal_v1_oas3.json', import.meta.url)); 19 | tests.set(MarketplaceInsights, readSpecs('buy_marketplace_insights_v1_beta_oas3.json', import.meta.url)); 20 | 21 | export default tests; -------------------------------------------------------------------------------- /test/api/restful/commerce/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Catalog, 3 | Charity, 4 | Identity, 5 | Media, 6 | Notification, 7 | Taxonomy, 8 | Translation 9 | } from '../../../../src/api/restful/commerce/index.js'; 10 | import {readSpecs} from '../../jsonfile.js'; 11 | 12 | const tests = new Map(); 13 | tests.set(Catalog, readSpecs( 'commerce_catalog_v1_beta_oas3.json', import.meta.url)); 14 | tests.set(Identity, readSpecs( 'commerce_identity_v1_oas3.json', import.meta.url)); 15 | tests.set(Taxonomy, readSpecs( 'commerce_taxonomy_v1_oas3.json', import.meta.url)); 16 | tests.set(Translation, readSpecs('commerce_translation_v1_beta_oas3.json', import.meta.url)); 17 | tests.set(Charity, readSpecs('commerce_charity_v1_oas3.json', import.meta.url)); 18 | tests.set(Notification, readSpecs('commerce_notification_v1_oas3.json', import.meta.url)); 19 | tests.set(Media, readSpecs('commerce_media_v1_beta_oas3.json', import.meta.url)); 20 | 21 | export default tests; -------------------------------------------------------------------------------- /test/api/restful/developer/index.ts: -------------------------------------------------------------------------------- 1 | import {Analytics, KeyManagement} from '../../../../src/api/restful/developer/index.js'; 2 | import {readSpecs} from '../../jsonfile.js'; 3 | 4 | const tests = new Map(); 5 | tests.set(Analytics, readSpecs( 'developer_analytics_v1_beta_oas3.json', import.meta.url)); 6 | tests.set(KeyManagement, readSpecs('developer_key_management_v1_oas3.json', import.meta.url)); 7 | 8 | export default tests; -------------------------------------------------------------------------------- /test/api/restful/oas.spec.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import 'mocha'; 3 | // @ts-ignore 4 | import sinon from 'sinon'; 5 | import Auth from '../../../src/auth/index.js'; 6 | import {IEBayApiRequest} from '../../../src/request.js'; 7 | 8 | import buyTests from './buy/index.js'; 9 | import commerceTests from './commerce/index.js'; 10 | import developerTests from './developer/index.js'; 11 | import postOrderTests from './postOrder/index.js'; 12 | import sellTests from './sell/index.js'; 13 | 14 | const allTests = { 15 | Buy: buyTests, 16 | Commerce: commerceTests, 17 | Developer: developerTests, 18 | Sell: sellTests, 19 | PostOrder: postOrderTests 20 | }; 21 | 22 | const appConfig = {appId: 'appId', certId: 'certId', sandbox: false, siteId: 77}; 23 | 24 | function createReq(): IEBayApiRequest { 25 | return { 26 | get: sinon.stub().returns(Promise.resolve({data: {}})), 27 | delete: sinon.stub().returns(Promise.resolve({data: {}})), 28 | put: sinon.stub().returns(Promise.resolve({data: {}})), 29 | post: sinon.stub().returns(Promise.resolve({data: {}})), 30 | postForm: sinon.stub().returns(Promise.resolve({data: {}})), 31 | instance: sinon.stub().returns(Promise.resolve({data: {}})), 32 | }; 33 | } 34 | 35 | const request = createReq(); 36 | 37 | const auth = new Auth(appConfig, request); 38 | auth.OAuth2.setClientToken({ 39 | access_token: 'token', 40 | expires_in: 1, 41 | token_type: 'test', 42 | }); 43 | 44 | describe('Open API Tests', () => { 45 | Object.entries(allTests).forEach(([name, tests]) => { 46 | describe('API > restful > ' + name, () => { 47 | // tslint:disable-next-line:variable-name 48 | tests.forEach((Oas, RestfulApi) => { 49 | it('should match name with id', () => { 50 | expect(RestfulApi.id).to.equal(RestfulApi.name); 51 | }); 52 | 53 | const api = new RestfulApi(appConfig, request, auth); 54 | 55 | if (Oas.servers) { 56 | it('"' + name + ':' + RestfulApi.name + '" should return url', () => { 57 | expect(api.baseUrl).to.oneOf( 58 | Oas.servers.map((server: any) => server.url.replace('{basePath}', server.variables.basePath.default)), 59 | ); 60 | }); 61 | 62 | it('"' + name + ':' + RestfulApi.name + '" should return correct path', () => { 63 | expect(api.basePath).to.equal( 64 | Oas.servers[0].variables.basePath.default 65 | ); 66 | }); 67 | } 68 | 69 | Object.keys(Oas.paths).forEach((path: any) => { 70 | Object.keys(Oas.paths[path]).forEach(method => { 71 | const endpoint = Oas.paths[path]; 72 | const call = endpoint[method]; 73 | if (!call.operationId || call.deprecated) { 74 | return; 75 | } 76 | const queryParams = path.match(/(?<={).+?(?=})/gi); 77 | const paramsInPath = queryParams ? queryParams : []; 78 | const paramsInHeader = call.parameters 79 | ? call.parameters.filter((p: any) => p.in === 'header') 80 | : []; 81 | const paramsInBody = (call.parameters 82 | ? call.parameters.filter((p: any) => p.in === 'body') 83 | : []).reduce((result: any, p: any) => { 84 | result[p.name] = p.name; 85 | return result; 86 | }, {}); 87 | const args = paramsInPath 88 | .map((paramName: any) => '{' + paramName + '}') 89 | .concat(paramsInHeader.map((p: any) => p.name)) 90 | .concat(paramsInBody); 91 | 92 | const req: any = createReq(); 93 | 94 | const restApi = new RestfulApi(appConfig, req, auth); 95 | 96 | it(`"${name}:${RestfulApi.name}" should implement this method (${path}). `, () => { 97 | expect(restApi[call.operationId]).to.be.a( 98 | 'function', 99 | 'AssertionError: expected to have "' + 100 | call.operationId + 101 | '" implemented.' 102 | ); 103 | }); 104 | 105 | it(`"${name}:${RestfulApi.name}:${call.operationId}" call correct method ${method} (${path}).`, () => { 106 | return restApi[call.operationId](...args).then(() => { 107 | // tslint:disable-next-line:no-unused-expression 108 | expect(req[method].calledOnce).to.be.true; 109 | }); 110 | }); 111 | 112 | it(`"${name}:${RestfulApi.name}:${call.operationId}" calls correct url (${path}).`, () => { 113 | return restApi[call.operationId](...args).then(() => { 114 | expect(decodeURI(req[method].args[0][0])).to.equal(decodeURI(encodeURI(restApi.baseUrl + path))); 115 | }); 116 | }); 117 | }); 118 | }); 119 | }); 120 | }); 121 | }); 122 | }); 123 | -------------------------------------------------------------------------------- /test/api/restful/postOrder/index.ts: -------------------------------------------------------------------------------- 1 | import {Cancellation, Case, Inquiry, Return} from '../../../../src/api/restful/postOrder/index.js'; 2 | import {readSpecs} from '../../jsonfile.js'; 3 | 4 | const tests = new Map(); 5 | tests.set(Cancellation, readSpecs( 'cancellation_oas3.json', import.meta.url)); 6 | tests.set(Case, readSpecs( 'case_oas3.json', import.meta.url)); 7 | tests.set(Inquiry, readSpecs( 'inquiry_oas3.json', import.meta.url)); 8 | tests.set(Return, readSpecs( 'return_oas3.json', import.meta.url)); 9 | 10 | export default tests; -------------------------------------------------------------------------------- /test/api/restful/restful.spec.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import {expect} from 'chai'; 3 | import sinon from 'sinon'; 4 | import Restful, {defaultApiHeaders} from '../../../src/api/restful/index.js'; 5 | import {MarketplaceId} from '../../../src/enums/index.js'; 6 | 7 | class TestApi extends Restful { 8 | get basePath(): string { 9 | return '/basePath'; 10 | } 11 | 12 | updateThings() { 13 | return this.post('/things', { 14 | headers: { 15 | 'X-TEST': 'X-TEST' 16 | } 17 | }); 18 | } 19 | } 20 | 21 | describe('Restful API', () => { 22 | const config = { 23 | appId: 'appId', 24 | certId: 'certId', 25 | sandbox: true, 26 | siteId: 0, 27 | devId: 'devId', 28 | }; 29 | 30 | let req: any = null; 31 | const cred = { 32 | access_token: 'access_token', 33 | expires_in: 0, 34 | token_type: 'token_type', 35 | refresh_token: 'refresh_token', 36 | refresh_token_expires_in: 0 37 | }; 38 | 39 | beforeEach(() => { 40 | req = { 41 | get: sinon.stub(), 42 | delete: sinon.stub(), 43 | put: sinon.stub(), 44 | post: sinon.stub(), 45 | postForm: sinon.stub().returns(Promise.resolve({ 46 | data: {access_token: 'new_access_token'} 47 | })), 48 | instance: sinon.stub() 49 | }; 50 | }); 51 | 52 | describe('extend Restful API with additional parameters', () => { 53 | it('returns correct baseUrl', () => { 54 | const api = new TestApi(config, req); 55 | const apix = new TestApi(config, req).apix; 56 | const apiz = new TestApi(config, req).apiz; 57 | const apiy = new TestApi(config, req).api({subdomain: 'apiy'}); 58 | 59 | expect(api.baseUrl).to.equal('https://api.sandbox.ebay.com/basePath'); 60 | expect(apix.baseUrl).to.equal('https://apix.sandbox.ebay.com/basePath'); 61 | expect(apiz.baseUrl).to.equal('https://apiz.sandbox.ebay.com/basePath'); 62 | expect(apiy.baseUrl).to.equal('https://apiy.sandbox.ebay.com/basePath'); 63 | }); 64 | 65 | it('extends headers', async () => { 66 | const post = sinon.stub().returns({item: '1'}); 67 | const api = new TestApi(config, {...req, post}).api({headers: {'X-HEADER': 'X-HEADER'}}); 68 | api.auth.OAuth2.setCredentials(cred); 69 | 70 | await api.updateThings(); 71 | expect(post.args[0][2].headers).to.eql({ 72 | ...defaultApiHeaders, 73 | 'Authorization': 'Bearer access_token', 74 | 'X-HEADER': 'X-HEADER' 75 | }); 76 | }); 77 | }); 78 | 79 | it('returns correct additional headers', () => { 80 | const api = new TestApi({ 81 | ...config, 82 | marketplaceId: MarketplaceId.EBAY_DE 83 | }, req); 84 | 85 | expect(api.additionalHeaders).to.eql({ 86 | 'X-EBAY-C-MARKETPLACE-ID': MarketplaceId.EBAY_DE 87 | }); 88 | }); 89 | 90 | it('returns correct RequestConfig', async () => { 91 | // @ts-ignore 92 | const api = new TestApi(config, req, { 93 | getHeaderAuthorization: sinon.stub().returns({'Authorization': 'Authorization'}) 94 | }); 95 | 96 | expect(await api.enrichRequestConfig({ 97 | method: 'post', 98 | path: '/', 99 | config: { 100 | headers: { 101 | 'X-HEADER': 'X-HEADER' 102 | } 103 | } 104 | })).to.eql({ 105 | headers: { 106 | 'Authorization': 'Authorization', 107 | 'Content-Type': 'application/json', 108 | 'Cache-Control': 'no-cache', 109 | 'Accept-Encoding': 'application/gzip', 110 | 'X-HEADER': 'X-HEADER' 111 | } 112 | }); 113 | }); 114 | 115 | describe('restful response test', () => { 116 | it('returns data', async () => { 117 | const post = sinon.stub().returns({data: {item: '1'}}); 118 | const api = new TestApi(config, {...req, post}); 119 | 120 | const response = await api.updateThings(); 121 | expect(response).to.eql({item: '1'}); 122 | }); 123 | 124 | it('returns response', async () => { 125 | const post = sinon.stub().returns({data: {item: '1'}}); 126 | const api = new TestApi(config, {...req, post}, undefined, {returnResponse: true}); 127 | 128 | const response = await api.updateThings(); 129 | expect(response).to.eql({data: {item: '1'}}); 130 | }); 131 | }); 132 | 133 | it('refresh the token if invalid token returned', async () => { 134 | const post = sinon.stub().onCall(0).rejects({ 135 | response: { 136 | data: { 137 | error: 'Invalid access token' 138 | } 139 | } 140 | }).onCall(1).resolves({data: {updateThings: 'ok'}}); 141 | 142 | const api = new TestApi({ 143 | ...config, 144 | autoRefreshToken: true 145 | }, { 146 | ...req, 147 | post, 148 | postForm: sinon.stub().resolves(cred) 149 | }); 150 | 151 | api.auth.OAuth2.setCredentials(cred); 152 | 153 | const result = await api.updateThings(); 154 | 155 | expect(post.callCount).to.equal(2); 156 | expect(result).to.eql({updateThings: 'ok'}); 157 | }); 158 | 159 | it('refresh the token on PostOrder call if response is 401', async () => { 160 | const post = sinon.stub().onCall(0).rejects({ 161 | response: { 162 | status: 401, 163 | } 164 | }).onCall(1).resolves({data: {updateThings: 'ok'}}); 165 | 166 | const api = new TestApi({ 167 | ...config, 168 | autoRefreshToken: true 169 | }, { 170 | ...req, 171 | post, 172 | postForm: sinon.stub().resolves(cred), 173 | }, undefined, { 174 | basePath: '/post-order/v2' 175 | }); 176 | 177 | api.auth.OAuth2.setCredentials(cred); 178 | 179 | const result = await api.updateThings(); 180 | 181 | expect(post.callCount).to.equal(2); 182 | expect(result).to.eql({updateThings: 'ok'}); 183 | }); 184 | 185 | it('refresh the token on Inventory call if response is 403', async () => { 186 | const post = sinon.stub().onCall(0).rejects({ 187 | response: { 188 | status: 403, 189 | } 190 | }).onCall(1).resolves({data: {updateThings: 'ok'}}); 191 | 192 | const api = new TestApi({ 193 | ...config, 194 | autoRefreshToken: true 195 | }, { 196 | ...req, 197 | post, 198 | postForm: sinon.stub().resolves(cred), 199 | }, undefined, { 200 | basePath: '/sell/inventory/v1' 201 | }); 202 | 203 | api.auth.OAuth2.setCredentials(cred); 204 | 205 | const result = await api.updateThings(); 206 | 207 | expect(post.callCount).to.equal(2); 208 | expect(result).to.eql({updateThings: 'ok'}); 209 | }); 210 | 211 | }); 212 | -------------------------------------------------------------------------------- /test/api/restful/sell/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AccountV1, 3 | AccountV2, 4 | Analytics, 5 | Compliance, 6 | Feed, 7 | Finances, 8 | Fulfillment, 9 | Inventory, 10 | Listing, 11 | Logistics, 12 | Marketing, 13 | Metadata, 14 | Negotiation, 15 | Recommendation 16 | } from '../../../../src/api/restful/sell/index.js'; 17 | import {readSpecs} from '../../jsonfile.js'; 18 | 19 | const tests = new Map(); 20 | tests.set(AccountV1, readSpecs( 'sell_account_v1_oas3.json', import.meta.url)); 21 | tests.set(AccountV2, readSpecs( 'sell_account_v2_oas3.json', import.meta.url)); 22 | tests.set(Analytics, readSpecs( 'sell_analytics_v1_oas3.json', import.meta.url)); 23 | tests.set(Compliance, readSpecs( 'sell_compliance_v1_oas3.json', import.meta.url)); 24 | tests.set(Fulfillment, readSpecs( 'sell_fulfillment_v1_oas3.json', import.meta.url)); 25 | tests.set(Inventory, readSpecs( 'sell_inventory_v1_oas3.json', import.meta.url)); 26 | tests.set(Marketing, readSpecs( 'sell_marketing_v1_oas3.json', import.meta.url)); 27 | tests.set(Metadata, readSpecs( 'sell_metadata_v1_oas3.json', import.meta.url)); 28 | tests.set(Recommendation, readSpecs( 'sell_recommendation_v1_oas3.json', import.meta.url)); 29 | tests.set(Finances, readSpecs( 'sell_finances_v1_oas3.json', import.meta.url)); 30 | tests.set(Feed, readSpecs( 'sell_feed_v1_oas3.json', import.meta.url)); 31 | tests.set(Logistics, readSpecs( 'sell_logistics_v1_oas3.json', import.meta.url)); 32 | tests.set(Negotiation, readSpecs( 'sell_negotiation_v1_oas3.json', import.meta.url)); 33 | tests.set(Listing, readSpecs( 'sell_listing_v1_beta_oas3.json', import.meta.url)); 34 | 35 | export default tests; 36 | -------------------------------------------------------------------------------- /test/api/traditional/traditional.spec.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import 'mocha'; 3 | // @ts-ignore 4 | import sinon from 'sinon'; 5 | import Traditional from '../../../src/api/traditional/index.js'; 6 | import Auth from '../../../src/auth/index.js'; 7 | import {IEBayApiRequest} from '../../../src/request.js'; 8 | import {eBayConfig} from '../../../src/types/index.js'; 9 | 10 | describe('Traditional', () => { 11 | const config: eBayConfig = { 12 | authToken: 'eBayAuthToken', 13 | appId: 'appId', 14 | certId: 'certId', 15 | sandbox: true, 16 | siteId: 0, 17 | devId: 'devId' 18 | }; 19 | 20 | const request: IEBayApiRequest = { 21 | get: sinon.stub(), 22 | delete: sinon.stub(), 23 | put: sinon.stub(), 24 | post: sinon.stub(), 25 | postForm: sinon.stub(), 26 | instance: sinon.stub() 27 | }; 28 | 29 | let auth: Auth; 30 | 31 | beforeEach(() => { 32 | auth = new Auth(config, request); 33 | }); 34 | 35 | it('return correct eBayAuthToken', () => { 36 | const traditional = new Traditional(config, request, auth); 37 | expect(traditional.auth.authNAuth.eBayAuthToken).to.equal('eBayAuthToken'); 38 | }); 39 | 40 | it('use "eBayAuthToken" if useIaf is set to false', () => { 41 | const post = sinon.stub().returns(Promise.resolve({data: ''})); 42 | const req: IEBayApiRequest = { 43 | get: sinon.stub(), 44 | delete: sinon.stub(), 45 | put: sinon.stub(), 46 | post, 47 | postForm: sinon.stub(), 48 | instance: sinon.stub() 49 | }; 50 | const traditional = new Traditional(config, req, auth); 51 | 52 | const trading = traditional.createTradingApi(); 53 | return trading.GetAccount({}, {raw: true, useIaf: false}).then(data => { 54 | expect(post.args[0][1]).to.equal([ 55 | '', 56 | '', 57 | 'eBayAuthToken', 58 | '' 59 | ].join('')); 60 | expect(data).to.equal(''); 61 | }); 62 | }); 63 | 64 | it('use Auth Token event if "accessToken" is available', () => { 65 | const post = sinon.stub().returns(Promise.resolve({data: ''})); 66 | const req: IEBayApiRequest = { 67 | get: sinon.stub(), 68 | delete: sinon.stub(), 69 | put: sinon.stub(), 70 | post, 71 | postForm: sinon.stub(), 72 | instance: sinon.stub() 73 | }; 74 | auth.OAuth2.setCredentials({ 75 | access_token: 'accessToken', 76 | refresh_token_expires_in: 0, 77 | refresh_token: 'refresh_token', 78 | token_type: 'token_type', 79 | expires_in: 0 80 | }); 81 | 82 | const traditional = new Traditional(config, req, auth); 83 | const trading = traditional.createTradingApi(); 84 | return trading.GetAccount({}, {raw: true}).then(data => { 85 | expect(post.args[0][1]).to.equal([ 86 | '', 87 | '', 88 | 'eBayAuthToken', 89 | ].join('')); 90 | expect(data).to.equal(''); 91 | expect(post.args[0][2].headers['X-EBAY-API-IAF-TOKEN']).to.equal(undefined); 92 | }); 93 | }); 94 | 95 | it('use IAF token if "accessToken" is available', () => { 96 | const post = sinon.stub().returns(Promise.resolve({data: ''})); 97 | const req: IEBayApiRequest = { 98 | get: sinon.stub(), 99 | delete: sinon.stub(), 100 | put: sinon.stub(), 101 | post, 102 | postForm: sinon.stub(), 103 | instance: sinon.stub() 104 | }; 105 | auth.OAuth2.setCredentials({ 106 | access_token: 'accessToken', 107 | refresh_token_expires_in: 0, 108 | refresh_token: 'refresh_token', 109 | token_type: 'token_type', 110 | expires_in: 0 111 | }); 112 | 113 | auth.authNAuth.setAuthToken(null); 114 | const traditional = new Traditional(config, req, auth); 115 | const trading = traditional.createTradingApi(); 116 | return trading.GetAccount({}, {raw: true}).then(data => { 117 | expect(post.args[0][1]).to.equal([ 118 | '', 119 | '', 120 | '' 121 | ].join('')); 122 | expect(data).to.equal(''); 123 | expect(post.args[0][2].headers['X-EBAY-API-IAF-TOKEN']).to.equal('accessToken'); 124 | }); 125 | }); 126 | 127 | it('throws EBayIAFTokenExpired of error code is 21917053', () => { 128 | const post = sinon.stub().returns(Promise.resolve({data: '21917053'})); 129 | const req: IEBayApiRequest = { 130 | get: sinon.stub(), 131 | delete: sinon.stub(), 132 | put: sinon.stub(), 133 | post, 134 | postForm: sinon.stub(), 135 | instance: sinon.stub() 136 | }; 137 | auth.OAuth2.setCredentials({ 138 | access_token: 'accessToken', 139 | refresh_token_expires_in: 0, 140 | refresh_token: 'refresh_token', 141 | token_type: 'token_type', 142 | expires_in: 0 143 | }); 144 | const traditional = new Traditional(config, req, auth); 145 | const trading = traditional.createTradingApi(); 146 | return trading.GetAccount({}).catch(error => { 147 | expect(error.name).to.equal('EBayIAFTokenExpired'); 148 | }); 149 | }); 150 | 151 | it('returns response', () => { 152 | const post = sinon.stub().returns(Promise.resolve({data: 'data'})); 153 | const req: IEBayApiRequest = { 154 | get: sinon.stub(), 155 | delete: sinon.stub(), 156 | put: sinon.stub(), 157 | post, 158 | postForm: sinon.stub(), 159 | instance: sinon.stub() 160 | }; 161 | auth.OAuth2.setCredentials({ 162 | access_token: 'accessToken', 163 | refresh_token_expires_in: 0, 164 | refresh_token: 'refresh_token', 165 | token_type: 'token_type', 166 | expires_in: 0 167 | }); 168 | const traditional = new Traditional(config, req, auth); 169 | const trading = traditional.createTradingApi(); 170 | return trading.GetAccount({}, {returnResponse: true}).catch(error => { 171 | expect(error.name).to.eql({data: 'data'}); 172 | }); 173 | }); 174 | }); 175 | -------------------------------------------------------------------------------- /tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2020", 5 | "outDir": "./lib", 6 | "moduleResolution": "node" 7 | }, 8 | "exclude": [], 9 | "extends": "./tsconfig.json" 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "node16", 5 | "outDir": "./dist", 6 | "lib": ["ES2020", "DOM"], 7 | "declaration": true, 8 | "moduleResolution": "node16", 9 | "sourceMap": false, 10 | "esModuleInterop": true, 11 | "resolveJsonModule": true, 12 | "strict": true, 13 | "noUnusedLocals": true, 14 | "noUnusedParameters": true, 15 | "noImplicitReturns": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "removeComments": true 18 | }, 19 | "exclude": ["src/index.ts"], 20 | "include": ["src"], 21 | "ts-node": { 22 | "esm": true 23 | } 24 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "jsRules": {}, 7 | "rules": { 8 | "indent": [ 9 | true, 10 | "spaces", 11 | 2 12 | ], 13 | "object-literal-sort-keys": false, 14 | "quotemark": [ 15 | true, 16 | "single" 17 | ], 18 | "trailing-comma": [ 19 | false 20 | ], 21 | "variable-name": [ 22 | true, 23 | "check-format", 24 | "allow-leading-underscore", 25 | "allow-snake-case" 26 | ], 27 | "interface-over-type-literal": false, 28 | "arrow-parens": [ 29 | true, 30 | "ban-single-arg-parens" 31 | ], 32 | "no-bitwise": false 33 | }, 34 | "rulesDirectory": [], 35 | "linterOptions": { 36 | "exclude": [ 37 | "src/types/restful/specs/**/*.ts" 38 | ] 39 | } 40 | } --------------------------------------------------------------------------------