Skip to content

Demo pipeline: import products from Google Sheets, resolve productType, build Listings payloads, dry-run or submit to Amazon SP-API sandbox. Note: Definitions in sandbox return only the mock LUGGAGE type (use overrides/fallbacks or prod creds for real types). MIT.

License

Notifications You must be signed in to change notification settings

ursaloper/AmazonListingsAutomation

Repository files navigation

Amazon Listings Automation (SP-API sandbox demo)

Русская версия

Overview

Small demo that:

  • pulls products from Google Sheets,
  • resolves productType via SP-API Definitions (or uses overrides),
  • builds Listings Items payloads,
  • optionally submits them (--submit).

Sandbox limitation (critical)

In the US sandbox the Definitions search often returns only one productType: LUGGAGE. This is a SP-API sandbox constraint, not a bug in the code. To get real product types you need a production Seller Central account (paid), verification, and production credentials. Amazon confirms static sandbox data: Product Type Definitions in sandbox provide only LUGGAGE as test product type; see Amazon maintainer note: “Please note that the sandbox in most cases returns limited static data, if you need production data it is not recommended to use the sandbox environment.” (ref: amzn/selling-partner-api-models#3837)

Workarounds:

  • Add a product_type column in the sheet to override per row.
  • Set SPAPI_DEFAULT_PRODUCT_TYPE / SPAPI_PRODUCT_TYPE_PREFERRED_TOKENS in config/.env to bias selection or provide a fallback.
  • Use production credentials on an account with access to the needed categories.

Stack

  • Python 3.11+, httpx, pydantic, google-api-python-client, dotenv.
  • Tooling: ruff, black, flake8.

Structure

  • src/sheets/ — Google Sheets reader.
  • src/spapi/ — LWA auth, SP-API client, product type search.
  • src/validators/ — input models, payload builder, productType resolver.
  • src/utils/ — config loader, logging.
  • config/.env.example — env template.
  • logs/ — rotating logs.

Setup

  1. Copy config/.env.exampleconfig/.env and fill:
    • Google: GOOGLE_SHEETS_ID, GOOGLE_SHEETS_RANGE (e.g. INVENTORY!A1:T), GOOGLE_CREDENTIALS_FILE (service account JSON with sheet access) or GOOGLE_API_KEY.
    • SP-API (sandbox creds from task work for LWA):
      • SPAPI_CLIENT_ID, SPAPI_CLIENT_SECRET, SPAPI_REFRESH_TOKEN
      • SPAPI_ENDPOINT=https://sandbox.sellingpartnerapi-na.amazon.com
      • SPAPI_MARKETPLACE_ID=ATVPDKIKX0DER
      • SPAPI_SELLER_ID=<seller_id>
    • Optional resolver tuning:
      • SPAPI_DEFAULT_PRODUCT_TYPE — fallback on empty search.
      • SPAPI_PRODUCT_TYPE_PREFERRED_TOKENS — bias selection (comma-separated).
    • Brand fallback: SPAPI_DEFAULT_BRAND (used if sheet has no brand column).
  2. Install deps: pip install -r requirements.txt.

Run

  • Dry-run (no submission, logs payloads):
    python -m src.main --log-level DEBUG
    
  • Submit Listings Items:
    python -m src.main --submit --log-level INFO
    
  • Override sheet/range/marketplace on the fly:
    python -m src.main --sheet-id <id> --range INVENTORY!A1:T --marketplace ATVPDKIKX0DER
    

Resolver behavior

  • If the sheet has product_type, it is used directly.
  • Else: keywords from title/model/mpn/color → Definitions search → choose best candidate (or first if no preferences).
  • If no candidates and no SPAPI_DEFAULT_PRODUCT_TYPE, raises an error. In sandbox this is expected when only LUGGAGE is available.

Payload builder

  • Uses brand from sheet if present, otherwise SPAPI_DEFAULT_BRAND.
  • Maps basic fields (title, description, bullets, UPC, price, availability, images); extend as needed for specific productType schemas.

Logs

  • Console + logs/app.log (10 MB rotation). INFO shows keywords, productType candidates, final choice, and payload summary.

Dry-run example (sandbox returning only LUGGAGE)

python -m src.main --log-level DEBUG
... Starting run for sheet=... submit=False
... Parsed 7 products from sheet
... Resolved keywords for sku=Kushtym1: [...]
... Candidates for keywords=[...]: ['LUGGAGE']
... Dry-run payload for sku=Kushtym1 productType=LUGGAGE (reason=search_match): {...}

Submit example (sandbox, Listings Items accepted, productType=LUGGAGE)

python -m src.main --submit --log-level INFO
... Starting run for sheet=... submit=True
... Parsed 7 products from sheet
... Candidates for keywords=[...]: ['LUGGAGE']
... Submitted listing sku=Kushtym1 productType=LUGGAGE response={'sku': 'GM-ZDPI-9B4E', 'status': 'ACCEPTED', ...}

Tests

  • Minimal unit tests for parser, resolver, and payload builder:
    pytest -q
    

Next steps for production

  • Use production creds and real categories to get correct productTypes.
  • Map attributes against Product Type Definitions schemas and validate.
  • Add Feeds API submission and polling.
  • Expand tests: parser, resolver, builder, SP-API stubs.

License

MIT © 2025 ursaloper

About

Demo pipeline: import products from Google Sheets, resolve productType, build Listings payloads, dry-run or submit to Amazon SP-API sandbox. Note: Definitions in sandbox return only the mock LUGGAGE type (use overrides/fallbacks or prod creds for real types). MIT.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages