Skip to content

fix(trading): derive X-EBAY-API-SITEID from EBAY_MARKETPLACE_ID#141

Open
teetlaja wants to merge 1 commit into
YosefHayim:mainfrom
teetlaja:fix/trading-site-id
Open

fix(trading): derive X-EBAY-API-SITEID from EBAY_MARKETPLACE_ID#141
teetlaja wants to merge 1 commit into
YosefHayim:mainfrom
teetlaja:fix/trading-site-id

Conversation

@teetlaja

@teetlaja teetlaja commented Jul 20, 2026

Copy link
Copy Markdown

User description

Problem

src/api/clientTrading.ts hardcoded the Trading API site:

const SITE_ID = '0';   // eBay US

EBAY_MARKETPLACE_ID never reached the Trading API — it is read in getEbayConfig() and only becomes the X-EBAY-C-MARKETPLACE-ID header on REST calls. clientTrading.ts imports just getBaseUrl from the config module.

Reads still work (own-listing reads are not site-scoped), so the misconfiguration is invisible until the first write. Creating a listing on a non-US marketplace then fails at eBay:

eBay POST https://api.ebay.com/ws/api.dll failed: Invalid auction currency.

The currency is validated against the site, so an EUR listing sent to site 0 is rejected. In practice ebay_create_listing / ebay_revise_listing are unusable on every marketplace except the US, with no environment variable to work around it. Hit this on a live eBay.de seller account with EBAY_MARKETPLACE_ID=EBAY_DE set.

Fix

Derive the site ID from EBAY_MARKETPLACE_ID using eBay's fixed mapping (EBAY_DE77, EBAY_GB3, …), so one setting drives REST and Trading traffic alike. EBAY_SITE_ID is added as an override for sites the map does not cover, or when REST and Trading must intentionally differ.

Unknown or unset marketplaces still resolve to 0, so existing US setups behave exactly as before.

Changes

  • src/config/environment.tsTRADING_SITE_IDS map + exported getTradingSiteId()
  • src/api/clientTrading.ts — header uses getTradingSiteId() instead of the constant
  • tests/unit/config/environment.test.ts — 5 tests: marketplace mapping, unset default, unknown-marketplace fallback, override, blank-override ignored
  • README.md + docs/auth/CONFIGURATION.md — document EBAY_SITE_ID and the REST/Trading header split

Verification

  • npx vitest run → 1051 passed (59 files)
  • npx tsc --noEmit → clean
  • Verified against the live Trading API: same AddFixedPriceItem payload that returned Invalid auction currency on site 0 is accepted with EBAY_MARKETPLACE_ID=EBAY_DE.

Note: biome check src/api/clientTrading.ts panics with an internal error, but it does so on unmodified main too — pre-existing, unrelated to this change.


Summary by cubic

Derives Trading’s X-EBAY-API-SITEID from EBAY_MARKETPLACE_ID so listing writes work on non-US sites and no longer fail with “Invalid auction currency.” Adds EBAY_SITE_ID as an optional override; US behavior stays the default.

  • Bug Fixes
    • Added getTradingSiteId() mapping and used it in src/api/clientTrading.ts.
    • Default and unknown marketplace → site 0 (US); blank override ignored.
    • New EBAY_SITE_ID env var to override the mapping when needed.
    • Tests cover mapping, defaults, unknown fallback, and override.
    • Docs updated to explain REST vs Trading headers and the new env var.

Written for commit 8ad9363. Summary will update on new commits.

Review in cubic


CodeAnt-AI Description

Use the correct Trading API site for the chosen marketplace

What Changed

  • Trading API requests now send the site ID that matches EBAY_MARKETPLACE_ID instead of always using the US site
  • Non-US marketplaces can now create and revise listings with the right site and currency combination
  • EBAY_SITE_ID can override the mapped site when a marketplace is not covered or REST and Trading need different sites
  • Documentation and tests now cover the marketplace-to-site mapping and override behavior

Impact

✅ Fewer listing failures on non-US eBay accounts
✅ Clearer marketplace-to-site behavior
✅ Lower risk of "Invalid auction currency" errors

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features

    • Trading API requests now automatically use the site associated with the configured marketplace.
    • Added support for overriding the Trading API site with EBAY_SITE_ID.
  • Bug Fixes

    • Improved handling of marketplace and currency differences by selecting the appropriate Trading API site.
  • Documentation

    • Expanded configuration guidance for EBAY_SITE_ID, including defaults, overrides, and API-specific behavior.

The Trading API client hardcoded site ID 0 (eBay US), so every Trading
call ignored EBAY_MARKETPLACE_ID. Reads still worked, but any listing
write on a non-US marketplace failed at eBay with "Invalid auction
currency", because the currency is validated against the site: an EUR
listing cannot be created on site 0. That made create/revise listing
unusable on every marketplace except the US, with no way to configure
around it.

Site ID is now derived from EBAY_MARKETPLACE_ID via the fixed eBay
mapping (EBAY_DE -> 77, EBAY_GB -> 3, ...), so the marketplace setting
drives REST and Trading traffic alike. EBAY_SITE_ID overrides it for
sites the map does not cover, or when REST and Trading must target
different sites. Unknown marketplaces keep falling back to 0, so US
setups are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@teetlaja
teetlaja requested a review from YosefHayim as a code owner July 20, 2026 19:40
@codeant-ai

codeant-ai Bot commented Jul 20, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 8ad9363 Jul 20, 2026 · 19:40 19:46

Updated in place by CodeAnt AI · last 5 reviews

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@codeant-ai

codeant-ai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8ad9363

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Trading API site IDs are now derived from EBAY_MARKETPLACE_ID, optionally overridden by EBAY_SITE_ID, and passed dynamically in Trading API headers. Documentation and unit tests cover the mapping, fallback, override, and blank-value behavior.

Changes

Trading API site configuration

Layer / File(s) Summary
Trading site ID resolution
src/config/environment.ts, tests/unit/config/environment.test.ts
Adds marketplace-to-site mapping and getTradingSiteId(), with tests for mappings, defaults, fallbacks, overrides, and whitespace handling.
Trading client integration and configuration documentation
src/api/clientTrading.ts, README.md, docs/auth/CONFIGURATION.md
Replaces the hard-coded Trading API site header value with the derived site ID and documents EBAY_SITE_ID behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: yosefhayim

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: deriving Trading API site ID from EBAY_MARKETPLACE_ID.
Description check ✅ Passed The description is detailed and covers the problem, fix, changes, and verification, though it doesn't follow the full template structure.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Jul 20, 2026
Comment thread src/api/clientTrading.ts

const buildTradingHeaders = (callName: string): Record<string, string> => ({
'X-EBAY-API-SITEID': SITE_ID,
'X-EBAY-API-SITEID': getTradingSiteId(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The Trading header is derived from process-wide environment instead of the active client configuration, so REST calls can target one marketplace while Trading calls use a different site when the API is instantiated with a custom config object. Derive the site ID from the same runtime config used by the EbayApiClient to keep both protocols aligned per client instance. [api mismatch]

Severity Level: Major ⚠️
❌ Trading createListing uses site from global env.
❌ Trading reviseListing routed to wrong marketplace site.
⚠️ Embedded consumers using custom EbayConfig see protocol drift.
⚠️ Debugging marketplace mismatch across REST/Trading is harder.
Steps of Reproduction ✅
1. An embedded consumer constructs a custom eBay configuration object (type `EbayConfig`
from `src/types/ebay.js`) where `marketplaceId` is set to a non-US marketplace such as
`'EBAY_DE'`, and passes it into the public facade `new EbaySellerApi(config)` defined in
`src/api/index.ts:31-58`.

2. The `EbaySellerApi` constructor at `src/api/index.ts:58-84` builds a shared REST client
via `new EbayApiClient(config)` and then instantiates a Trading client with `const
tradingClient = new TradingApiClient(this.client);` (`TradingApiClient` constructor in
`src/api/clientTrading.ts:234-239`).

3. The REST client uses the per-instance configuration to set marketplace headers:
`EbayApiClient.getDefaultHeaders()` in `src/api/client.ts:89-105` adds
`headers['X-EBAY-C-MARKETPLACE-ID'] = this.config.marketplaceId;`, so REST requests
correctly target the custom marketplace from the `config` object rather than
`process.env`.

4. A Trading write is performed via a high-level method such as
`tradingApi.createListing()` in `src/api/trading/trading.ts:148-158`, which calls
`tradingClient.execute('AddFixedPriceItem', {...})`. Inside `TradingApiClient.execute`
(`src/api/clientTrading.ts:35-71`), request headers are built with
`buildTradingHeaders(callName)` at `src/api/clientTrading.ts:51-56`, which sets
`'X-EBAY-API-SITEID': getTradingSiteId()`. `getTradingSiteId()` in
`src/config/environment.ts:364-371` ignores the client configuration and instead derives
the site purely from process-wide environment (`EBAY_SITE_ID` / `EBAY_MARKETPLACE_ID`), so
if those environment variables do not match the custom `config.marketplaceId`, REST and
Trading traffic are routed to different sites, and Trading writes for the configured
marketplace can fail at eBay due to site/currency mismatch.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/api/clientTrading.ts
**Line:** 52:52
**Comment:**
	*Api Mismatch: The Trading header is derived from process-wide environment instead of the active client configuration, so REST calls can target one marketplace while Trading calls use a different site when the API is instantiated with a custom config object. Derive the site ID from the same runtime config used by the `EbayApiClient` to keep both protocols aligned per client instance.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread src/config/environment.ts
Comment on lines +365 to +368
const override = (process.env.EBAY_SITE_ID ?? '').trim();
if (override !== '') {
return override;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The override is returned as-is for any non-empty value, but Trading expects a numeric site ID; a typo like EBAY_SITE_ID=EBAY_DE will produce invalid headers and fail every Trading write at runtime. Validate that the override is numeric (and ideally within known site IDs) before using it, otherwise reject or fall back safely. [api mismatch]

Severity Level: Major ⚠️
❌ Trading createListing fails when EBAY_SITE_ID is mistyped.
❌ Trading reviseListing fails due to invalid numeric site header.
⚠️ Misconfiguration leads to hard-to-diagnose Trading write errors.
Steps of Reproduction ✅
1. Configure the environment for a non-US marketplace (for example,
`process.env.EBAY_MARKETPLACE_ID = 'EBAY_DE'`) and set an invalid Trading override such as
`process.env.EBAY_SITE_ID = 'EBAY_DE'` instead of the numeric site ID. The override
handling in `getTradingSiteId()` at `src/config/environment.ts:364-371` reads `const
override = (process.env.EBAY_SITE_ID ?? '').trim();` and returns it verbatim whenever it
is non-empty.

2. When any Trading operation is invoked via the public API — e.g.,
`tradingApi.createListing()` in `src/api/trading/trading.ts:148-158` — the call flows into
`TradingApiClient.execute()` at `src/api/clientTrading.ts:35-71`. This method constructs
headers with `const headers = buildTradingHeaders(callName);` where
`buildTradingHeaders()` (`src/api/clientTrading.ts:51-56`) sets `'X-EBAY-API-SITEID':
getTradingSiteId()`.

3. With `EBAY_SITE_ID` misconfigured to `'EBAY_DE'`, `getTradingSiteId()` returns this
non-numeric string, so `buildTradingHeaders()` sends `X-EBAY-API-SITEID: EBAY_DE` on every
Trading request. The Trading API expects a numeric site ID as documented in the comments
at `src/config/environment.ts:47-52`, so eBay will reject or mishandle these requests,
causing the HTTP call in `postTradingXml()` (`src/api/clientTrading.ts:113-130`) to fail
or return error responses.

4. The failure is surfaced to callers through the error-handling chain:
`createTradingApiError()` at `src/api/clientTrading.ts:73-87` wraps the Trading failure,
and `validateTradingAck()` at `src/api/clientTrading.ts:197-223` returns an `Effect.fail`
when `Ack` indicates failure. Because there is no validation of `EBAY_SITE_ID` being
numeric in `getTradingSiteId()` or in `validateEnvironmentConfig()`
(`src/config/environment.ts:57-107`), any typo or non-numeric override value consistently
breaks all Trading writes at runtime until the environment is corrected.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/config/environment.ts
**Line:** 365:368
**Comment:**
	*Api Mismatch: The override is returned as-is for any non-empty value, but Trading expects a numeric site ID; a typo like `EBAY_SITE_ID=EBAY_DE` will produce invalid headers and fail every Trading write at runtime. Validate that the override is numeric (and ideally within known site IDs) before using it, otherwise reject or fall back safely.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Confidence score: 4/5

  • In src/config/environment.ts, EBAY_SITE_ID currently accepts nonnumeric values, so a simple config typo can propagate into every Trading API call and cause hard-to-diagnose request failures in production. Validate EBAY_SITE_ID as numeric at startup and fail fast with a clear configuration error before merging.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/config/environment.ts">

<violation number="1" location="src/config/environment.ts:367">
P2: A nonnumeric `EBAY_SITE_ID` is accepted and attached to every Trading request, causing opaque API failures from a simple configuration typo. Validate the override as a numeric site ID and surface a configuration error before sending calls.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/config/environment.ts
export const getTradingSiteId = (): string => {
const override = (process.env.EBAY_SITE_ID ?? '').trim();
if (override !== '') {
return override;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A nonnumeric EBAY_SITE_ID is accepted and attached to every Trading request, causing opaque API failures from a simple configuration typo. Validate the override as a numeric site ID and surface a configuration error before sending calls.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/config/environment.ts, line 367:

<comment>A nonnumeric `EBAY_SITE_ID` is accepted and attached to every Trading request, causing opaque API failures from a simple configuration typo. Validate the override as a numeric site ID and surface a configuration error before sending calls.</comment>

<file context>
@@ -311,6 +311,65 @@ export const getEbayConfig = (): EbayConfig => {
+export const getTradingSiteId = (): string => {
+  const override = (process.env.EBAY_SITE_ID ?? '').trim();
+  if (override !== '') {
+    return override;
+  }
+  const marketplaceId = (process.env.EBAY_MARKETPLACE_ID ?? '').trim() || 'EBAY_US';
</file context>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant